异常后,Application Insights RequestTelemetry 未显示在请求中

Application Insights RequestTelemetry not showing up in Requests after exception

我花了一段时间尝试让 RequestTelemetry 工作。当我第一次玩它时它确实如此,但奇怪的是只要抛出异常就停止工作。我已经阅读了使用 Application Insights for custom events and metrics as well as Custom Operations Tracking 的文档,并尝试添加所有最佳实践以查看是否可以让结果再次显示。我正在使用 .NET Core 3.1 和 Microsoft.ApplicationInsights.AspNetCore 2.14.0.

Web 应用程序的设置在 Startup.cs

中如下所示
services.AddApplicationInsightsTelemetry(new ApplicationInsightsServiceOptions { 
    EnableAdaptiveSampling = false
}); 

我在控制器 Post 动作中有遥测。我意识到 Application Insights 已经在跟踪 post 操作,但我想看看我是否可以跟踪内部方法。这是我控制器中的代码:


public MyController(IMyService myService, TelemetryClient telemetryClient, ILogger<MyController> logger) {
    _myService = myService;
    _telemetryClient = telemetryClient;
    _logger = logger;
}

[HttpPost]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> PostAsync([FromBody] MyModel model) {
    using var scope = _logger.BeginScope(new Dictionary<string, object> {
        { $"{nameof(PostAsync)}.Scope", Guid.NewGuid() },
        { nameof(model.Name), model.Name }
    });

    model.AuthenticatedUserId = User.GetUserIdFromClaims();

    var requestTelemetry = new RequestTelemetry { Name = nameof( _myService.MyFunctionAsync) };
    var operation = _telemetryClient.StartOperation(requestTelemetry);
    operation.Telemetry.Properties.Add("User", model.AuthenticatedUserId);

    try {
        await _myService.MyFunctionAsync(model).ConfigureAwait(false); // <-- throws exception
        operation.Telemetry.Success = true;
        return NoContent();
    } catch (Exception e) {
        operation.Telemetry.Success = false;
        throw;
    } finally {
        _telemetryClient.StopOperation(operation);
    }
}

我可以在 Visual Studio 控制台输出中看到代码执行,因为我得到以下日志,但它从未显示在 Application Insights Requests

Application Insights Telemetry: {
  "name": "AppRequests",
  "time": "2020-06-21T14:29:08.7469588Z",
  "iKey": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "tags": {
    "ai.application.ver": "1.0.0.0",
    "ai.cloud.roleInstance": "DESKTOP-K74PNCU",
    "ai.operation.id": "0443259d660125498cf28f8f7a275dab",
    "ai.operation.parentId": "1dea6f9b27220c4c",
    "ai.operation.name": "POST EventEmitter/Post",
    "ai.location.ip": "::1",
    "ai.internal.sdkVersion": "dotnetc:2.14.0-17971",
    "ai.internal.nodeName": "DESKTOP-K74PNCU"
  },
  "data": {
    "baseType": "RequestData",
    "baseData": {
      "ver": 2,
      "id": "2b7900eedfb7c34d",
      "name": "MyFunctionAsync",
      "duration": "00:00:00.3766937",
      "success": false,
      "properties": {
        "DeveloperMode": "true",
        "User": "pobl-dev",
        "_MS.ProcessedByMetricExtractors": "(Name:'Requests', Ver:'1.1')",
        "AspNetCoreEnvironment": "Development"
      }
    }
  }
}

有一个简单的解决方案,但由于缺少文档或错误,我不确定为什么需要它。我发现一旦提供 responseCode 一切正常。 200 的默认值 responseCode 显示在成功调用时。一旦我设置了失败的值,一切正常。


public MyController(IMyService myService, TelemetryClient telemetryClient, ILogger<MyController> logger) {
    _myService = myService;
    _telemetryClient = telemetryClient;
    _logger = logger;
}

[HttpPost]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> PostAsync([FromBody] MyModel model) {
    using var scope = _logger.BeginScope(new Dictionary<string, object> {
        { $"{nameof(PostAsync)}.Scope", Guid.NewGuid() },
        { nameof(model.Name), model.Name }
    });

    model.AuthenticatedUserId = User.GetUserIdFromClaims();

    var requestTelemetry = new RequestTelemetry { Name = nameof( _myService.MyFunctionAsync) };
    var operation = _telemetryClient.StartOperation(requestTelemetry);
    operation.Telemetry.Properties.Add("User", model.AuthenticatedUserId);

    try {
        await _myService.MyFunctionAsync(model).ConfigureAwait(false); // <-- throws exception
        operation.Telemetry.Success = true;
        operation.Telemetry.ResponseCode = "Roses";
        return NoContent();
    } catch (Exception e) {
        operation.Telemetry.Success = false;
        operation.Telemetry.ResponseCode = "Funky"; // <-- seems to be required on a failure
        throw;
    } finally {
        _telemetryClient.StopOperation(operation);
    }
}

如果您好奇的话,这是为了向已接受的答案添加一些上下文:

这是 RequestTelemetry

source code

当它准备要发送到 Azure 服务器的数据时,它明确选择不设置默认响应代码,除非 success == true 在这种情况下,默认值为 200

// Required fields
if (!this.Success.HasValue)
{
    this.Success = true;
}

if (string.IsNullOrEmpty(this.ResponseCode))
{
    this.ResponseCode = this.Success.Value ? "200" : string.Empty;
}     

如果您 运行 对日志进行简单的 Kusto 查询:

union requests | where timestamp > ago(1hr) | where customDimensions["CustomOperationCategory"] in ("Identity") | take 100

您只会在设置了状态代码的地方看到不成功的结果:

我不知道是否有任何改变,但微软的示例 sometimes do the same