Azure Web App超时致Application Insights追踪丢失,如何解决?
解决方案:Azure WebAPI超时导致App Insights追踪丢失的问题
你的推测完全正确——Azure在230秒后强制终止请求的操作,并没有触发你的IExceptionHandler。因为这个终止行为是在应用程序管道之外发生的,本质上是请求被强制取消,而非抛出了能被异常处理器捕获的标准异常。下面是几个可行的解决办法:
1. 监听请求取消令牌,手动上报超时事件
在你的API控制器方法中注入CancellationToken,监听它的取消信号。当Azure终止请求时,这个令牌会被触发,你可以在此时手动向App Insights发送追踪数据:
public async Task<IHttpActionResult> LongRunningPost([FromBody] YourModel model, CancellationToken cancellationToken) { try { // 执行你的长时间运行逻辑 await YourLongRunningBusinessLogicAsync(cancellationToken); return Ok(); } catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) { // 检测到请求被Azure超时终止 var telemetryClient = new TelemetryClient(); telemetryClient.TrackException(new Exception("Request terminated by Azure due to 230s timeout")); telemetryClient.TrackEvent("AzureTimeoutTriggered", new Dictionary<string, string> { { "RequestPath", Request.RequestUri.PathAndQuery }, { "HttpMethod", Request.Method.ToString() } }); // 确保遥测数据被发送完成 await telemetryClient.FlushAsync(); return StatusCode(HttpStatusCode.InternalServerError); } }
2. 用全局DelegatingHandler拦截取消请求
如果不想在每个Action里重复代码,可以创建自定义的DelegatingHandler,在请求管道的早期全局监听取消信号:
public class TimeoutTrackingHandler : DelegatingHandler { protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { // 注册取消回调 var cancellationRegistration = cancellationToken.Register(() => { var telemetryClient = new TelemetryClient(); telemetryClient.TrackException(new Exception("Request canceled by Azure platform timeout")); telemetryClient.TrackEvent("GlobalAzureTimeout", new Dictionary<string, string> { { "RequestPath", request.RequestUri.PathAndQuery }, { "HttpMethod", request.Method.ToString() } }); telemetryClient.Flush(); }); try { return await base.SendAsync(request, cancellationToken); } finally { // 清理注册 cancellationRegistration.Dispose(); } } }
然后在WebApiConfig.Register中注册这个处理器:
config.MessageHandlers.Add(new TimeoutTrackingHandler());
3. 协调应用与Azure的超时配置
Azure的230秒是平台级硬限制,但你可以在应用层面设置更长的超时,让应用先于Azure检测到超时并抛出异常,这样你的IExceptionHandler就能捕获到:
在web.config中添加/修改配置:
<system.web> <httpRuntime executionTimeout="300" /> <!-- 设置为大于230秒,比如5分钟 --> </system.web> <system.webServer> <aspNetCore requestTimeout="00:05:00" /> <!-- ASP.NET Core项目用这个配置 --> </system.webServer>
之后在业务逻辑中添加自定义超时逻辑,比如用Task.WhenAny结合取消令牌,确保在Azure终止前主动抛出超时异常:
var longRunningTask = YourLongRunningBusinessLogicAsync(cancellationToken); var timeoutTask = Task.Delay(220000, cancellationToken); // 220秒,比Azure的230秒早10秒 var completedTask = await Task.WhenAny(longRunningTask, timeoutTask); if (completedTask == timeoutTask) { throw new TimeoutException("Application-level timeout triggered before Azure termination"); }
4. 排查App Insights采样配置
有时候不是追踪丢失,而是被采样过滤掉了。可以临时调整采样规则,确保异常事件不被丢弃:
在ApplicationInsights.config中修改:
<TelemetryProcessors> <Add Type="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.AdaptiveSamplingTelemetryProcessor, Microsoft.AI.ServerTelemetryChannel"> <MaxTelemetryItemsPerSecond>5</MaxTelemetryItemsPerSecond> <ExcludedTypes>Exception</ExcludedTypes> <!-- 排除异常类型的采样 --> </Add> </TelemetryProcessors>
注意:手动调用FlushAsync后,建议等待1-2秒让数据发送完成,因为App Insights是异步上报的,进程直接终止可能导致数据未发送成功。
内容的提问来源于stack exchange,提问作者Diana
相关产品推荐
相关产品推荐

