Azure Function App - Problem getting the operation_id

367 views Asked by At

I have an Azure Function App with a single PowerShell function that responds to an Event Grid trigger. The runtime stack for the Function App is PowerShell Core 7.2 and the OS is Windows. It's hosted under the consumption plan. I have a dedicated Application Insights instance connected to it for logging.

In the function code, I create custom logging to log some information from the Event Grid trigger payload. This custom logging will be used in a KQL query for an Application Insights alert rule. I need a way to correlate this data with the default data that gets logged each time the function app is run. It seems like adding the operation_id to the custom logging would be the most appropriate way to accomplish this. The only problem is, I can't figure out how to retrieve the operation_id in the function app script.

Here is a snippet of code that creates the custom logging:

$telemetryClient = New-Object "Microsoft.ApplicationInsights.TelemetryClient"
$telemetryClient.InstrumentationKey = $env:ApplicationInsights_InstrumentationKey

# Extract relevant details from $eventGridEvent
$telemetryKeyVaultResourceId = $eventGridEvent.topic
$telemetrySecretName = $eventGridEvent.subject
$telemetrySecretVersion = $eventGridEvent.data.Version

# UNIX epoch start
$epochStart = Get-Date -Date ([DateTime]::new(1970, 1, 1, 0, 0, 0, [System.DateTimeKind]::Utc))
# Convert UNIX timestamp to DateTime
$EXP_timestamp = $epochStart.AddSeconds($eventGridEvent.data.EXP)
# Format the DateTime to desired string format
$telemetrySecretExpiration = $EXP_timestamp.ToString("MM-dd-yyyy hh:mm:ss tt")

# Create dictionary with the payload data we're interested in
$properties = [System.Collections.Generic.Dictionary[string,string]]::new()
$properties["key_vault_resource_id"] = $telemetryKeyVaultResourceId
$properties["secret_name"] = $telemetrySecretName
$properties["secret_version"] = $telemetrySecretVersion
$properties["secret_expiration"] = $telemetrySecretExpiration

# Set current operation_Id to telemetry context. If it doesn't exist, terminate the script.
# This custom telemetry needs the operation_Id so its data can be properly correlated in
# the KQL query for the alert rule.

$telemetryOperationId = $telemetryClient.Context.Operation.Id
Write-Output "Operation Id is $telemetryOperationId"

if ($telemetryOperationId) {
    $properties["operation_Id"] = $telemetryOperationId
} else {
    Write-Error -Message "No operation_Id found. Cannot continue"
}

# Log the custom event
$telemetryClient.TrackEvent("FunctionAppEventPayload", $properties)

# Flush telemetry client to ensure data is sent
$telemetryClient.Flush()

When this code runs without the part that sets the operation_id, the telemetry is logged properly as I can retrieve it with a KQL query, but $telemetryClient.Context.Operation.Id is null so there's no way to reliably correlate it with the default data collected from a function app run that I know of. I also tried [System.Diagnostics.Activity]::Current.RootId, but that is also null.

Any ideas? I'm new to Function Apps so maybe there is a better way to do what I'm trying to accomplish.

1

There are 1 answers

5
Dasari Kamali On

When this code runs without the part that sets the operation_id, the telemetry is logged properly as I can retrieve it with a KQL query, but $telemetryClient.Context.Operation.Id is null

Yes, it returns null because you’re not fetching the telemetry data correctly from the telemetry client.

After analyzing your code:

Point 1 ($telemetryClient = New-Object "Microsoft.ApplicationInsights.TelemetryClient") initializes the telemetry client.
Point 2 ($telemetryClient.InstrumentationKey = $env:ApplicationInsights_InstrumentationKey) sets the instrumentation key to the telemetry client for pointing to that specific application insights resource.
Point 3 ($telemetryOperationId = $telemetryClient.Context.Operation.Id) will not fetch the operation id as telemetry client not having the sufficient data.

The correct code should be:


$telemetryClient = New-Object Microsoft.ApplicationInsights.TelemetryClient
$telemetryClient.Context.InstrumentationKey = $env:ApplicationInsights_InstrumentationKey

$kqlquery = "requests | order by timestamp desc | take 1"

$kqlqueryoid = $kqlquery.operation_id
# OR
$kqlqueryoid = $kqlquery["operation_id"]
# OR
Use the methods given in this [MS Doc](https://learn.microsoft.com/en-us/dotnet/api/microsoft.applicationinsights.telemetryclient?view=azure-dotnet) for fetching telemetry data using kql query
$telemetryData = $telemetryClient.GetMetric($kqlquery )
# OR
$telemetryData = $telemetryClient.track_event('operation_id',kqlquery )

$operationId = $telemetryData[0].Context.Operation.Id
Write-Output "Operation ID: $operationId"

The operation_id is fetched from the telemetry data by querying the Azure Function Logs as given in this Microsoft document and the above KQL Query provides the recent requests telemetry for extracting the operation_id.

enter image description here