.NET 4.8 Windows Service配置Application Insights无数据排查
问题描述
基于.NET 4.8的遗留Windows Service项目,配置Application Insights后无法在Azure平台看到TrackException、TrackTrace等遥测数据,已确认Instrumentation Key和连接字符串正确,尝试默认applicationinsight.config配置也无效。项目每分钟运行定时任务,期望捕获异常并发送日志,但数据始终无法上报。
相关代码如下:
Main方法
static void Main(string[] args) { var theService = new JobManagerService(); theService.Start(); }
JobManagerService类
internal class JobManagerService { private readonly List<JobManager> _jobs = new List<JobManager>(); private TelemetryClient _tc; public JobManagerService() { InitializeSomething(); } public void Start() { var config = TelemetryConfiguration.CreateDefault(); config.InstrumentationKey = ConfigurationManager.AppSettings["JobManagerInstrumentationKey"]; // 已废弃 config.ConnectionString = $"InstrumentationKey={ConfigurationManager.AppSettings["JobManagerInstrumentationKey"]};IngestionEndpoint=https://westeurope-5.in.applicationinsights.azure.com/;LiveEndpoint=https://westeurope.livediagnostics.monitor.azure.com/"; config.TelemetryInitializers.Add(new AppInsightsJobManagerTelemetryInitializer()); _tc = new TelemetryClient(config); _tc.TrackTrace($"Starting ApplicationInsights {nameof(TelemetryClient)} for {nameof(JobManagerService)}"); AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionEventRaised; _jobs.Add(new JobManager(interval, job, App_Online, _tc)); _tc.TrackTrace($"Job {job.Name} Initialized with interval {interval} ms"); _tc.Flush(); } private void UnhandledExceptionEventRaised(object sender, UnhandledExceptionEventArgs e) { _tc.TrackException((Exception)e.ExceptionObject); } private class AppInsightsJobManagerTelemetryInitializer { public void Initialize(ITelemetry telemetry) { telemetry.Context.Properties["SystemGuid"] = Config.SystemConfiguration.SystemGuid.ToString(); telemetry.Context.Properties["SystemName"] = Config.SystemConfiguration.SystemName.ToString(); telemetry.Context.Properties["SystemType"] = Config.SystemConfiguration.SystemType.ToString(); } } }
JobManager类
internal class JobManager { private readonly IJob _job; private readonly Timer _timer = new Timer(); private readonly TelemetryClient _telemetryClient; public JobManager(int intInterval, IJob objJob, TelemetryClient telemetryClient) { if (intInterval > 60000) throw new ArgumentException("Interval cannot exceed 1 minute"); _telemetryClient = telemetryClient; _job = objJob; _timer.Interval = intInterval; _timer.Enabled = true; _timer.Elapsed += mObjTimer_Elapsed; } private void mObjTimer_Elapsed(object sender, ElapsedEventArgs e) { try { _timer.Enabled = false; var _mObjJobCollection = new JobProviderService().ListByService(_job.Name); foreach (var objJob in _mObjJobCollection) { var objRunner = new JobRunner(objJob, _job); objRunner.Run(); } } catch (Exception ex) { _telemetryClient.TrackException(ex); } finally { _telemetryClient.TrackDependency("Windows Service", _job.Name, _job.Name); } } }
关键问题与修复步骤
1. 遥测初始化器未实现ITelemetryInitializer接口
你的AppInsightsJobManagerTelemetryInitializer类没有实现Application Insights要求的ITelemetryInitializer接口,导致初始化逻辑完全不会被执行,甚至可能干扰遥测数据的正常发送。
修复代码:
private class AppInsightsJobManagerTelemetryInitializer : ITelemetryInitializer { public void Initialize(ITelemetry telemetry) { telemetry.Context.Properties["SystemGuid"] = Config.SystemConfiguration.SystemGuid.ToString(); telemetry.Context.Properties["SystemName"] = Config.SystemConfiguration.SystemName.ToString(); telemetry.Context.Properties["SystemType"] = Config.SystemConfiguration.SystemType.ToString(); } }
2. Flush调用后未等待发送完成
TelemetryClient.Flush()是异步操作,直接调用后如果没有等待,遥测数据可能还没完成发送就继续执行后续逻辑,导致数据丢失。尤其是在服务启动、异常捕获、服务停止的场景下,必须等待足够时间让SDK完成数据上传。
修复示例:
- 在
Start方法末尾:
_tc.Flush(); System.Threading.Thread.Sleep(5000); // 等待5秒,可根据网络情况调整
- 在未处理异常事件中:
private void UnhandledExceptionEventRaised(object sender, UnhandledExceptionEventArgs e) { _tc.TrackException((Exception)e.ExceptionObject); _tc.Flush(); System.Threading.Thread.Sleep(5000); }
- 新增服务停止逻辑(需在服务的Stop方法中调用):
public void Stop() { _tc.TrackTrace("JobManagerService is stopping"); _jobs.ForEach(job => /* 清理定时任务资源 */); _tc.Flush(); System.Threading.Thread.Sleep(5000); }
3. 配置优先级与读取方式问题
同时设置InstrumentationKey和ConnectionString时,ConnectionString优先级更高,但硬编码拼接连接字符串容易出错。建议直接从配置文件读取完整的连接字符串,避免手动拼接。
步骤:
- 在
App.config中添加完整连接字符串:
<appSettings> <add key="JobManagerConnectionString" value="InstrumentationKey=YOUR_KEY_HERE;IngestionEndpoint=https://westeurope-5.in.applicationinsights.azure.com/;LiveEndpoint=https://westeurope.livediagnostics.monitor.azure.com/" /> </appSettings>
- 修改
Start方法中的配置代码:
var config = TelemetryConfiguration.CreateDefault(); // 移除InstrumentationKey设置,直接使用连接字符串 config.ConnectionString = ConfigurationManager.AppSettings["JobManagerConnectionString"]; config.TelemetryInitializers.Add(new AppInsightsJobManagerTelemetryInitializer());
4. 定时任务遗漏Timer重新启用
原JobManager的mObjTimer_Elapsed方法中,finally块未重新启用Timer,导致任务只执行一次就停止,自然也不会产生后续的遥测数据。
修复代码:
finally { _telemetryClient.TrackDependency("Windows Service", _job.Name, _job.Name); _timer.Enabled = true; // 重新启用定时任务 }
5. 确认SDK版本与依赖包
确保安装了兼容.NET 4.8的最新Application Insights SDK包,推荐安装Microsoft.ApplicationInsights.WindowsServer(包含针对Windows服务的优化功能),而非仅基础包。
通过NuGet安装:
Install-Package Microsoft.ApplicationInsights.WindowsServer
6. 验证遥测发送状态
可以启用SDK的调试日志,查看是否有发送失败的错误信息:
在App.config中添加:
<system.diagnostics> <trace autoflush="true"> <listeners> <add name="aiListener" type="Microsoft.ApplicationInsights.TraceListener.ApplicationInsightsTraceListener, Microsoft.ApplicationInsights.TraceListener" /> </listeners> </trace> </system.diagnostics>
本地调试时,可查看输出窗口的日志,排查是否有认证错误、网络问题等。
内容的提问来源于stack exchange,提问作者Newnamtab

