Linux上PowerShell Core函数应用:禁用Application Insights本地认证后日志丢失
问题解决方案:PowerShell函数应用禁用Application Insights本地认证后无法发送日志
核心问题分析
- 当前代码直接使用Instrumentation Key(
iKey)向Application Insights发送数据,这属于本地认证方式。当AI禁用本地认证后,该方式会被拒绝,导致请求失败;同时函数的日志(如Write-Host输出)默认通过AI管道发送,因此整个日志链路会因认证失败中断。 - .NET应用正常是因为它利用了Azure Functions的Application Insights扩展,该扩展会自动通过托管标识获取AD令牌完成认证,无需手动处理。
修复步骤
1. 替换Application Insights ingestion端点
将硬编码的通用端点替换为你的AI实例专属端点,可在Azure Portal的AI资源概述页获取,格式示例:https://<你的AI资源名称>.in.applicationinsights.azure.com/v2/track
2. 修改函数脚本,添加托管标识认证逻辑
移除iKey认证,改为通过托管标识获取AD令牌访问AI,修改后的脚本如下:
param($Timer) # 替换为你的Application Insights专属 ingestion 端点 $ApplicationInsightsURL = "https://<你的AI资源名称>.in.applicationinsights.azure.com/v2/track" $minimumDaysValid = 20 # 使用托管标识获取Application Insights的访问令牌 $token = (Get-AzAccessToken -ResourceUrl "https://monitor.azure.com/").Token # 获取JSON文件路径 $jsonFilePath = Join-Path $PSScriptRoot "licensesdates.json" # 记录定时器触发状态 if ($Timer -ne $null) { Write-Host "Function triggered by Timer: $($Timer.ScheduleStatus.Last)" } # 加载许可证数据 $licenseData = Get-Content -Raw -Path $jsonFilePath | ConvertFrom-Json foreach ($license in $licenseData.licenses) { $licenseName = $license.licenseName $expirationDate = $license.expirationDate $expirationRealDate = Get-Date $expirationDate $today = Get-Date ("{0:yyyy-MM-dd}" -f (Get-Date)) $daysDifference = (New-TimeSpan -Start $today -End $expirationRealDate).Days # 生成状态消息 $msg = switch ($daysDifference) { { $_ -gt $minimumDaysValid } { "OK: $licenseName license has $daysDifference days left." } { $_ -gt 0 } { "WARNING: Take action! $licenseName license expires in $daysDifference days." } { $_ -eq 0 } { "ALERT: $licenseName license expires TODAY!" } { $_ -lt 0 } { "EXPIRED: $licenseName license expired $((-1 * $daysDifference)) days ago." } default { "UNKNOWN: Could not determine status for $licenseName." } } # 构造AI请求负载(移除iKey字段) $OperationId = [Guid]::NewGuid().ToString() $Payload = @{ name = "Microsoft.ApplicationInsights.Metric" time = (Get-Date).ToString("o") data = @{ baseType = "MetricData" baseData = @{ ver = 2 metrics = @( @{ name = "LicenseDaysRemaining" value = $daysDifference } ) properties = @{ "LicenseName" = $licenseName "StatusMessage" = $msg "OperationId" = $OperationId "DaysRemaining" = $daysDifference } } } } # 转换为JSON格式 $PayloadJson = $Payload | ConvertTo-Json -Compress -Depth 10 # 发送数据到AI,添加Authorization头 try { Invoke-RestMethod ` -Uri $ApplicationInsightsURL ` -Method 'Post' ` -Body $PayloadJson ` -ContentType "application/json" ` -Headers @{ "Authorization" = "Bearer $token" } Write-Host $msg } catch { Write-Error "Failed to send data to Application Insights: $_" throw $_ } }
3. 更新host.json,强制日志通道使用托管标识
修改host.json,明确指定AI扩展使用托管标识认证:
{ "version": "2.0", "managedDependency": { "Enabled": true }, "extensionBundle": { "id": "Microsoft.Azure.Functions.ExtensionBundle", "version": "[4.*, 5.0.0)" }, "logging": { "applicationInsights": { "samplingSettings": { "isEnabled": true, "maxTelemetryItemsPerSecond": 5 }, "enableDependencyTracking": true, "authenticationMode": "ManagedIdentity" // 新增:强制使用托管标识 }, "logLevel": { "Function": "Information", "Host": "Error" } } }
4. 验证权限与环境配置
- 确认函数应用的托管标识已被授予目标AI资源的Metric Publisher角色,且角色分配已生效(通常需等待数分钟)。
- 删除函数应用的
APPLICATIONINSIGHTS_INSTRUMENTATION_KEY环境变量,避免扩展误触发本地认证。
关键说明
- 禁用本地认证后,Application Insights仅接受Azure AD认证的请求,不再认可iKey。
- 函数的系统日志依赖host.json配置的AI扩展,必须确保扩展使用托管标识,否则日志无法正常上传。
内容的提问来源于stack exchange,提问作者kiran
相关产品推荐
相关产品推荐

