I love working with Github Actions for Continuous Integration and Deployment.
By default you get emails regarding failed workflows for Github monitoring.
To get more insights in the performance and success of workflows, you can leverage Application Insights to log performance, failures and release annotations.
To achieve this, I use:
In this example I’m logging a successful request (ResponseCode = 200) to Application Insights.
The PowerShell script logs the duration of the request
, success
and some custom properties
(ActionRunURL, MyTestProperty1, MyTestProperty2)
The Github Action consist of the following:
APPLICATIONINSIGHTS_INSTRUMENTATIONKEY
: Containing the Application Insights Instrumentation keyeapplication-insights-log-request
set-startdatetime-var
: gets the current time and sets it to an environment variablelogin-azure
: As explained in Use GitHub Actions to connect to Azureapplication-insights-log-request
: runs a PowerShell script to log the request to Application InsightsHere’s the full content of the Github Action:
name: Log - Application Insights - Request
on:
workflow_dispatch
env:
APPLICATIONINSIGHTS_INSTRUMENTATIONKEY: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
jobs:
application-insights-log-request:
runs-on: ubuntu-latest
steps:
- name: set-startdatetime-var
run: |
START_DATETIME=$(date '+%d/%m/%Y %H:%M:%S')
echo $START_DATETIME
echo "START_DATETIME=$START_DATETIME" >> $GITHUB_ENV
- name: login-azure
uses: azure/login@v1
with:
creds: '{"clientId":"$","clientSecret":"$","subscriptionId": "$","tenantId":"$"}'
enable-AzPSSession: true
- name: application-insights-log-request
shell: pwsh
run: |
# set variables
$InstrumentationKey = $env:APPLICATIONINSIGHTS_INSTRUMENTATIONKEY
$Name = $env:GITHUB_WORKFLOW
$Started = $env:START_DATETIME
$Success = $true # set to false for failed
$ResponseCode = 200 # set to 500 for failed
$startedDateTime = [datetime]::ParseExact($Started, "dd/MM/yyyy HH:mm:ss", $Null)
[System.TimeSpan]$Duration = New-TimeSpan -Start $startedDateTime -End (Get-Date)
$StartedDateTimeOffset = [System.DateTimeOffset]$startedDateTime
# setup telemetry client
$telemetryClient = New-Object -TypeName Microsoft.ApplicationInsights.TelemetryClient
$telemetryClient.InstrumentationKey = $InstrumentationKey
# initialize context information
$TelemetryClient.Context.User.Id = "$($env:GITHUB_ACTOR)"
$telemetryClient.Context.Operation.Name = $Name
# set telemetry context
$TelemetryClient.Context.Session.Id = "$($env:GITHUB_REPOSITORY)/$($env:GITHUB_WORKFLOW)/$($env:GITHUB_RUN_ID)/$($env:GITHUB_JOB)"
$telemetryClient.Context.Operation.Id = "$($env:GITHUB_REPOSITORY)/$($env:GITHUB_WORKFLOW)/$($env:GITHUB_RUN_ID)/$($env:GITHUB_JOB)"
Write-Host "SessionId: $($TelemetryClient.Context.Session.Id)"
Write-Host "User Id: $($TelemetryClient.Context.User.Id)"
Write-Host "Operation Id: $($TelemetryClient.Context.Operation.Id)"
Write-Host "Operation Name: $($TelemetryClient.Context.Operation.Name)"
# setup request telemetry information
$request = New-Object -TypeName Microsoft.ApplicationInsights.DataContracts.RequestTelemetry
$request.Name = $Name
$request.StartTime = $StartedDateTimeOffset
$request.Duration = $Duration
$request.Success = $Success
$request.ResponseCode = $ResponseCode
Write-Host "StartTime: $StartedDateTimeOffset"
Write-Host "Duration: $Duration"
Write-Host "Success: $Success"
Write-Host "ResponseCode: $ResponseCode"
# set actionurl
$ActionRunURL = "$($env:GITHUB_SERVER_URL)/$($env:GITHUB_REPOSITORY)/actions/runs/$($env:GITHUB_RUN_ID)"
Write-Host "ActionRunURL : $ActionRunURL"
# set properties
[HashTable]$Properties = @{}
$properties["ActionRunURL"] = "$ActionRunURL"
$properties["MyTestProperty1"] = "Test 1"
$properties["MyTestProperty2"] = "Test 2"
# copy properties to request
$properties.Keys | ForEach-Object { $request.Properties[$_] = $Properties[$_] }
# track the request
$telemetryClient.TrackRequest($request)
# flush
$telemetryClient.Flush()
Here’s the content of the inline PowerShell script:
# set variables
$InstrumentationKey = $env:APPLICATIONINSIGHTS_INSTRUMENTATIONKEY
$Name = $env:GITHUB_WORKFLOW
$Started = $env:START_DATETIME
$Success = $true # set to false for failed
$ResponseCode = 200 # set to 500 for failed
$startedDateTime = [datetime]::ParseExact($Started, "dd/MM/yyyy HH:mm:ss", $Null)
[System.TimeSpan]$Duration = New-TimeSpan -Start $startedDateTime -End (Get-Date)
$StartedDateTimeOffset = [System.DateTimeOffset]$startedDateTime
# setup telemetry client
$telemetryClient = New-Object -TypeName Microsoft.ApplicationInsights.TelemetryClient
$telemetryClient.InstrumentationKey = $InstrumentationKey
# initialize context information
$TelemetryClient.Context.User.Id = "$($env:GITHUB_ACTOR)"
$telemetryClient.Context.Operation.Name = $Name
# set telemetry context
$TelemetryClient.Context.Session.Id = "$($env:GITHUB_REPOSITORY)/$($env:GITHUB_WORKFLOW)/$($env:GITHUB_RUN_ID)/$($env:GITHUB_JOB)"
$telemetryClient.Context.Operation.Id = "$($env:GITHUB_REPOSITORY)/$($env:GITHUB_WORKFLOW)/$($env:GITHUB_RUN_ID)/$($env:GITHUB_JOB)"
Write-Host "SessionId: $($TelemetryClient.Context.Session.Id)"
Write-Host "User Id: $($TelemetryClient.Context.User.Id)"
Write-Host "Operation Id: $($TelemetryClient.Context.Operation.Id)"
Write-Host "Operation Name: $($TelemetryClient.Context.Operation.Name)"
# setup request telemetry information
$request = New-Object -TypeName Microsoft.ApplicationInsights.DataContracts.RequestTelemetry
$request.Name = $Name
$request.StartTime = $StartedDateTimeOffset
$request.Duration = $Duration
$request.Success = $Success
$request.ResponseCode = $ResponseCode
Write-Host "StartTime: $StartedDateTimeOffset"
Write-Host "Duration: $Duration"
Write-Host "Success: $Success"
Write-Host "ResponseCode: $ResponseCode"
# set actionurl
$ActionRunURL = "$($env:GITHUB_SERVER_URL)/$($env:GITHUB_REPOSITORY)/actions/runs/$($env:GITHUB_RUN_ID)"
Write-Host "ActionRunURL : $ActionRunURL"
# set properties
[HashTable]$Properties = @{}
$properties["ActionRunURL"] = "$ActionRunURL"
$properties["MyTestProperty1"] = "Test 1"
$properties["MyTestProperty2"] = "Test 2"
# copy properties to request
$properties.Keys | ForEach-Object { $request.Properties[$_] = $Properties[$_] }
# track the request
$telemetryClient.TrackRequest($request)
# flush
$telemetryClient.Flush()
When the workflow ran, the following result is shown:
In the Application Insights instance, the following appears:
When clicking on the request, the following details are shown:
In this example I’m logging a release annotation
for a new release with some custom properties
from the default Github environment variables.
The trigger of the request is a
The Github Action consist of the following:
main
branch of the repository.APPLICATION_INSIGHTS_RESOURCE_ID
: Containing the Application Insights Resource Idcreate-applicationinsightsannotation
set-startdatetime-var
: gets the current time and sets it to an environment variablelogin-azure
: As explained in Use GitHub Actions to connect to Azurecreate-applicationinsightsannotation
: runs a PowerShell script to ingest an annotation in application insightsHere’s the full content of the Github Action:
name: Log - Application Insights - Annotation
on:
pull_request:
branches:
- main
env:
APPLICATION_INSIGHTS_RESOURCE_ID: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rg-weu-prd-githubactionsapplicationinsights/providers/microsoft.insights/components/appi-weu-prd-githubactionsapplicationinsights"
jobs:
create-applicationinsightsannotation:
runs-on: ubuntu-latest
steps:
- name: login-azure
uses: azure/login@v1
with:
creds: '{"clientId":"$","clientSecret":"$","subscriptionId": "$","tenantId":"$"}'
enable-AzPSSession: true
- name: set-startdatetime-var
run: |
START_DATETIME=$(date '+%d/%m/%Y %H:%M:%S')
echo $START_DATETIME
echo "START_DATETIME=$START_DATETIME" >> $GITHUB_ENV
- name: create-applicationinsightsannotation
id: create-applicationinsightsannotation
uses: azure/powershell@v1
with:
inlineScript: |
# set annotation properties
$annotationProperties = @{"ReleaseDescription" = "$env:GITHUB_REF"; "TriggerBy" = "$env:GITHUB_ACTOR" }
$annotationPropertiesJson = ConvertTo-Json $annotationProperties -Compress
# build annotation
$annotation = @{
Id = [GUID]::NewGuid();
AnnotationName = "$($env:GITHUB_REF_NAME)";
EventTime = (Get-Date).ToUniversalTime().GetDateTimeFormats("s")[0];
Category = "Deployment";
Properties = $annotationPropertiesJson
}
# set body
$body = (ConvertTo-Json $annotation -Compress) -replace '(\\+)"', '$1$1"' -replace "`"", "`"`""
# submit annotation
az rest --method put --uri "$($env:APPLICATION_INSIGHTS_RESOURCE_ID)/Annotations?api-version=2015-05-01" --headers "Content-Type=application/json" --body "$($body) "
azPSVersion: "11.1.0"
errorActionPreference: stop
# set annotation properties
$annotationProperties = @{"ReleaseDescription" = "$env:GITHUB_REF"; "TriggerBy" = "$env:GITHUB_ACTOR" }
$annotationPropertiesJson = ConvertTo-Json $annotationProperties -Compress
# build annotation
$annotation = @{
Id = [GUID]::NewGuid();
AnnotationName = "$($env:GITHUB_REF_NAME)";
EventTime = (Get-Date).ToUniversalTime().GetDateTimeFormats("s")[0];
Category = "Deployment";
Properties = $annotationPropertiesJson
}
# set body
$body = (ConvertTo-Json $annotation -Compress) -replace '(\\+)"', '$1$1"' -replace "`"", "`"`""
# submit annotation
az rest --method put --uri "$($env:APPLICATION_INSIGHTS_RESOURCE_ID)/Annotations?api-version=2015-05-01" --headers "Content-Type=application/json" --body "$($body) "
When the workflow ran, the following result is shown:
As result, the release annotation is shown in the graph with some custom properties: