PowerShell中AppInsights 2.5.1:EventTelemetry.Properties类型异常致数据丢失
我之前也碰到过类似PowerShell和Application Insights交互的坑,针对你用的2.5.1版本net45库的问题,咱们拆解一下:你遇到的核心问题是EventTelemetry.Properties的类型在ConcurrentDictionary和Dictionary之间随机切换,当它是Dictionary时,自定义维度/度量无法被正确持久化。这大概率是PowerShell的动态特性和该特定版本AI库的初始化逻辑交互导致的——在常规.NET环境下,EventTelemetry的Properties默认应该是ConcurrentDictionary,但PowerShell的对象初始化方式可能触发了不同的构造路径,导致偶尔生成Dictionary类型的实例。
这里有几个直接可行的修复方案,按优先级排序:
1. 显式强制Properties为ConcurrentDictionary
在创建EventTelemetry实例后,立即检查并替换其Properties类型,确保后续操作都基于ConcurrentDictionary:
# 加载AI库 $AI = "C:\Microsoft.ApplicationInsights.dll" $null = [Reflection.Assembly]::LoadFile($AI) $InstrumentationKey = "XXXXX" $TelClient = New-Object Microsoft.ApplicationInsights.TelemetryClient $TelClient.InstrumentationKey = $InstrumentationKey # 创建事件遥测并修复Properties类型 $eventTelemetry = New-Object Microsoft.ApplicationInsights.DataContracts.EventTelemetry("MyCustomEvent") # 检查当前Properties类型,不是ConcurrentDictionary就替换 if (-not ($eventTelemetry.Properties -is [System.Collections.Concurrent.ConcurrentDictionary[string, string]])) { $newConcurrentProps = New-Object System.Collections.Concurrent.ConcurrentDictionary[string, string] # 复制原有属性(如果有的话) foreach ($kvPair in $eventTelemetry.Properties.GetEnumerator()) { $newConcurrentProps.TryAdd($kvPair.Key, $kvPair.Value) | Out-Null } # 替换为ConcurrentDictionary $eventTelemetry.Properties = $newConcurrentProps } # 添加自定义维度和度量 $eventTelemetry.Properties.Add("CustomDimensionKey", "CustomValue") $eventTelemetry.Metrics.Add("CustomMetricKey", 123.45) # 发送遥测 $TelClient.TrackEvent($eventTelemetry) $TelClient.Flush()
2. 直接构造带ConcurrentDictionary的EventTelemetry
如果默认构造函数偶尔出问题,你可以跳过默认初始化,手动给Properties赋值:
$eventTelemetry = New-Object Microsoft.ApplicationInsights.DataContracts.EventTelemetry $eventTelemetry.Properties = New-Object System.Collections.Concurrent.ConcurrentDictionary[string, string] # 后续添加自定义属性、发送遥测的操作同上
3. 升级AI库版本(可选)
2.5.1是2018年左右的老版本,后续版本大概率修复了这类跨环境的初始化问题。如果你的场景允许升级,换成较新的稳定版本(比如2.21.0及以上),可能从根源上避免这个类型切换的问题。
在这个老版本的Application Insights中,后端处理和序列化逻辑可能依赖ConcurrentDictionary的线程安全特性或特定的序列化标记,而Dictionary没有这些特性,导致自定义属性无法被正确识别或序列化,最终丢失。
内容的提问来源于stack exchange,提问作者lidong

