Skip to content

Instantly share code, notes, and snippets.

@JustinGrote
Created September 6, 2024 07:38
Show Gist options
  • Save JustinGrote/50b0281400755d46cff214c8336a2b9e to your computer and use it in GitHub Desktop.
Save JustinGrote/50b0281400755d46cff214c8336a2b9e to your computer and use it in GitHub Desktop.
Watch Container App Job Logs
#requires -Version 7.2 -Module Az.App, Az.OperationalInsights, Az.ResourceGraph
using namespace Microsoft.Azure.Management.Internal.Resources.Utilities.Models
$ErrorActionPreference = 'Stop'
function Watch-AzContainerAppJobExecution {
[CmdletBinding(DefaultParameterSetName='ByName')]
param(
#The name of the execution
[Parameter(ParameterSetName='ByName', Mandatory)]$Name,
[Parameter(ParameterSetName='ByName', Mandatory)]$JobName,
[Parameter(ParameterSetName='ByName', Mandatory)]$ResourceGroupName,
[Parameter(ParameterSetName='ById', ValueFromPipelineByPropertyName, Mandatory)]$Id,
[Parameter(ParameterSetName='ByInputObject', ValueFromPipeline, Mandatory)]
[Microsoft.Azure.PowerShell.Cmdlets.App.Models.JobExecutionBase]$JobExecution,
[Switch]$Brief
)
if (-not $Id) {
$Id = $JobExecution.Id ?? (Get-AzContainerAppJobExecution -Name $Name -JobName $JobName -ResourceGroupName $ResourceGroupName).Id
}
#HACK: JobExecution is bugged and doesn't have the job status. https://github.com/Azure/azure-powershell/issues/24054
$executionResource = Get-AzResource -Id $Id -ApiVersion '2024-03-01'
#TODO: This could probably be done faster with a tricky Azure Resource Graph Search
$jobResourceId = $executionresource.ResourceId.split('/executions')[0]
#Get Parent Job to find its app insights location
$jobResource = Get-AzContainerAppJob -InputObject $jobResourceId
$environment = Get-AzContainerAppManagedEnv -InputObject $jobResource.EnvironmentId
$workspaceCustomerId = $environment.LogAnalyticConfigurationCustomerId
$logQuery = @'
union ContainerAppSystemLogs_CL,ContainerAppConsoleLogs_CL
| extend JobExecutionName = coalesce(ExecutionName_s,ContainerGroupName_s)
| where JobExecutionName startswith '{0}'
| extend
Code = coalesce(Reason_s,Stream_s),
Time = unixtime_seconds_todatetime(_timestamp_d)
| where Time > datetime('{1}')
| project-rename
Severity=Type_s,
Message=Log_s
| project
Time,
Severity,
Message,
Code,
Type,
JobExecutionName
| sort by Time asc
'@
$logPoint = $executionResource.Properties.startTime
do {
# $jobStatus = Get-AzResource -Id $Id -ApiVersion '2024-03-01'
# $status = $jobStatus.Properties.status
# $timeElapsed = [DateTimeOffSet]::Now - [DateTimeOffSet]($jobStatus.Properties.startTime)
# $timeElapsedString = $timeElapsed.ToString("hh\:mm\:ss")
Write-Progress -Id 1 -Activity "Azure Container Job: $($executionResource.Name)" -Status "[$timeElapsedString] $status"
$query = $logQuery -f $executionResource.Name, $logPoint
$response = Invoke-AzOperationalInsightsQuery -WorkspaceId $workspaceCustomerId -Query $query
#Results is an enumerable that can only be read once so we pipe it into an array
[Object[]]$logs = $response.Results | Foreach-Object {$_}
if ($logs.count) {
$Brief ? $(
$logs | Format-Table Time, Message
) : $logs
$logPoint = $logs[-1].Time
}
#TODO: Do this better
if ('ProcessExited' -in $logs.Code) {
$status = 'Completed'
}
} while ($status -ne 'Completed')
if ($status -ne 'Completed') {
throw "Job did not complete with status: $status"
}
Write-Progress -Id 1 -Completed
}
function Assert-Single ($x) {
if ($x.Count -ne 1) {
throw "Expected 1 result, got $($x.Count)"
}
}
$containerAppDateFormat = "yyyy-MM-dd HH:mm:ss zzz 'UTC'"
$datetimeOffset = [datetimeoffset]::ParseExact($datetimeString, $containerAppDateFormat, [cultureinfo]::InvariantCulture)
$datetimeOffset
$datetimeOffsetString = $datetimeOffset.ToString("yyyy-MM-dd HH:mm:ss zzz 'UTC'", [cultureinfo]::InvariantCulture)
$datetimeOffsetString
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment