【问题标题】:ASP.NET Core Application Insights 400 ModelState DetailsASP.NET Core Application Insights 400 模型状态详细信息
【发布时间】:2022-01-14 21:57:09
【问题描述】:

我正在尝试确定是否可以查看应用程序中发生 400 错误的详细信息。我认为知道没有价值的属性将允许更好地针对错误进行调查。例如,知道它是“名称”属性。

我在 Azure 中配置了应用洞察。它成功收集了网络应用程序发出的 400 条响应,但没有显示任何细节。

特别是在这种情况下,我在 ActionFilterAttribute 中看到此代码生成的 400。

public override void OnActionExecuting(ActionExecutingContext context)
{
    if (!context.ModelState.IsValid)
    {
        context.Result = new BadRequestObjectResult(context.ModelState);
    }
}

响应的内容将包含 JSON 序列化的ModelState 值。

当发生这种情况时,App Insights 会记录错误,指出请求失败并显示 400 状态代码。它没有显示任何 ModelState 值。

我真正希望能够看到的关键信息不是模型的内容(这可能包含敏感信息),而是ModelState.Values 集合的详细信息的集合基本上它等同于以下属性:

ModelState.Values.Keys.Key
ModelState.Values.Keys.Errors()

无效属性会将 ModelState.Values.Keys.ValidationState 设置为 false。

到目前为止,我的发现似乎表明我可以通过手动获取 TelemetryClient 并向 App Insights 添加另一个事件来解决此问题。

有没有办法可以将此详细信息附加到任何具有 400 异常的请求中?或者我是否需要向TelemetryClient 添加另一个自定义调用并以这种方式进行跟踪?

如果是后者,我可以以某种方式将其添加到ActionFilterAttribute 中,以便在那里处理吗?

感觉就像我不理解一些简单的东西会让一切都变得有意义。

【问题讨论】:

    标签: azure-application-insights asp.net-core-2.1


    【解决方案1】:

    对于遇到此问题的任何人,我们最终在 ASP.Net Core 中创建了一个结果过滤器,它会在生成 400 响应时自动将模型状态记录为 json。它为我们提供了在错误发生时帮助解决错误所需的一切。

    public sealed class Log400DetailsResultFilter : IResultFilter
    {
        private readonly ILogger<Log400DetailsResultFilter> _log;
    
        public Log400DetailsResultFilter(ILogger<Log400DetailsResultFilter> log)
        {
            _log = log;
        }
    
        public void OnResultExecuted(ResultExecutedContext context)
        {
            if (context.HttpContext.Response.StatusCode == (int)HttpStatusCode.BadRequest && context.ModelState.ErrorCount > 0)
            {
                var errors = new SerializableError(context.ModelState);
                _log.LogError($"Bad Request Model State Errors: {JsonConvert.SerializeObject(errors)}");
            }
        }
    
        public void OnResultExecuting(ResultExecutingContext context)
        {
    
        }
    }
    

    然后只需在启动时注册它,它将运行所有 400 个结果。

    services.AddMvc(config =>
    {
        config.Filters.Add<Log400DetailsResultFilter>();
    });
    

    在 Application Insights 中,您只需单击“端到端事务详细信息”刀片中的“查看所有遥测数据”按钮,它就会显示该事务的所有日志,包括模型状态的详细信息。

    编辑 16/01/2020 过滤器注册代码在 .NET Core 3.0 中发生了变化。这是新的注册码:

    services.AddControllers(config =>
    {
        config.Filters.Add<ModelValidationResultFilter>();
    });
    

    编辑 14/01/2021 您现在可以使用内置的 HTTP 日志记录实现类似的功能,see here 以获取完整的详细信息。

    【讨论】:

      【解决方案2】:

      您可以尝试在 AI SDK 中使用 Telemetry InitializersThis GutHub repo 有一个关于如何更新正在收集的请求遥测属性的示例,但是,它没有涉及如何在 ModelState 上下文属性的情况下具体工作,但如果该上下文也可用,您应该能够使用您正在寻找的属性。

      它应该看起来像这样:

      public class PropertyTelemetryInitializer : ITelemetryInitializer
      {
          IHttpContextAccessor httpContextAccessor;
      
          public PropertyTelemetryInitializer(IHttpContextAccessor httpContextAccessor)
          {
              this.httpContextAccessor = httpContextAccessor;
          }
      
          public void Initialize(ITelemetry telemetry)
          {
              if (telemetry is RequestTelemetry request)
              {
                  request.Context.Properties["tenantName"] = httpContextAccessor.Value.Items["tenantName"].ToString();
              }
          }
      }
      

      然后在 DI 中注册这个:

      public void ConfigureServices(IServiceCollection services)
      {
      services.AddSingleton<ITelemetryInitializer, PropertyTelemetryInitializer>();
      services.AddApplicationInsightsTelemetry()
      ...
      }
      

      【讨论】:

      • 对于遇到此问题的任何人,我认为它需要使用 ITelemetryProcessor 而不是初始化程序。我已经被拉到别的东西上,所以这将不得不等待,但当我回到它时我会发布更新。 docs.microsoft.com/en-us/azure/application-insights/…
      • 但您在 2019 年最终使用了 IResultFilter ?您不会在应用洞察中获得重复的 400er 条目吗?当您手动连接所有内容并使用 Ilogger.log 时?
      猜你喜欢
      • 2018-02-12
      • 2015-11-07
      • 2021-05-25
      • 1970-01-01
      • 2022-01-14
      • 2017-11-01
      • 1970-01-01
      • 2018-11-10
      • 1970-01-01
      相关资源
      最近更新 更多