logging - MVC 日志记录范围

标签 logging scope asp.net-core asp.net-core-mvc

我读到在 MVC 中间件框架中使用日志范围和 Controller 的操作:

Use Scopes sparingly, and only for actions with a bounded start and end. For example, the framework provides a scope around MVC actions. Avoid nesting many scopes within one another.





A scope is an IDisposable type returned by calling the ILogger.BeginScope method, which lasts from the moment it is created until it is disposed. Any logging state, such as a transaction id, is attached to the scope when it is created.



我正在尝试使用此功能来写入一些日志信息。我执行了以下步骤:

1)创建Asp.net核心MVC应用程序
2) 在 appsetting.json 中将属性“IncludeScopes”设置为“true”
3)像这样创建 Controller 和 Action :
  [Route("api/[controller]")]
public class TodoController : Controller
{
    private readonly ILogger<TodoController> _logger;
    public TodoController(ILogger<TodoController> logger)
    {
        _logger = logger;
    }

    // GET: api/values
    [HttpGet]
    public IEnumerable<string> Get()
    {
        _logger.LogInformation(1000, "Listing all items started");
        Thread.Sleep(2000);
        _logger.LogInformation(1000, "Listing all items finished");
        return new string[] { "value1", "value2" };
    }
}

我希望我的日志消息流始终只包含“列出所有已开始的项目”和“列出所有已完成的项目”部分,它们彼此不分开。
但是当我同时启动两个请求时,得到的日志流为:

RequestId: xxx 列出所有项目已开始
RequestId: yyy 列出所有项目开始
RequestId: xxx 列出所有项目已完成
RequestId: yyy 列出所有项目完成

什么原因?这是正确的行为,我在日志记录上下文中误解了“范围”术语吗?

最佳答案

日志范围有助于创建范围,通过该范围在其中创建的任何日志语句都可以使用该信息。

以下来自 ConsoleLoggerIncludeScopes设置为 true :

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      => RequestId:0HKT6JC0EVFNA RequestPath:/api/values
      Request starting HTTP/1.1 GET http://localhost:5000/api/values
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      => RequestId:0HKT6JC0EVFNA RequestPath:/api/values => WebApplication8.Controllers.ValuesController.Get (WebApplication8)
      Executing action method WebApplication8.Controllers.ValuesController.Get (WebApplication8) with arguments () - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
      => RequestId:0HKT6JC0EVFNA RequestPath:/api/values => WebApplication8.Controllers.ValuesController.Get (WebApplication8)
      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      => RequestId:0HKT6JC0EVFNA RequestPath:/api/values => WebApplication8.Controllers.ValuesController.Get (WebApplication8)
      Executed action WebApplication8.Controllers.ValuesController.Get (WebApplication8) in 322.8533ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      => RequestId:0HKT6JC0EVFNA RequestPath:/api/values
      Request finished in 428.477ms 200 application/json; charset=utf-8

如果你注意到上面的日志,这里RequestId:0HKT6JC0EVFNA正在为每个日志语句打印(如前所述,范围或嵌套范围内的所有日志语句都将从所有这些范围中获取信息)

在 ASP.NET 中默认创建的一些日志范围是 RequestId如上所示的范围以及从日志中看到的 MVC Controller 操作调用的范围(例如这一行: => WebApplication8.Controllers.ValuesController.Get (WebApplication8) )

如果需要,您也可以自己创建范围:
using (logger.BeginScope("OrderOrchestrationId:{OrderOrchestrationId}", orderOrchestrationId))
{
   // any log statements from here on would have `OrderOrchestrationId` available
}

注:
默认情况下,所有记录器都不支持范围。如果是 ConsoleLogger它以文本格式打印范围,但范围在结构化日志记录的情况下确实很出色,如下所述。

范围如何有用?
ASP.NET 日志框架允许你做 structured logging .比如上面的代码{OrderOrchestrationId}被用于此目的。 Serilog有一个用于 ASP.NET 5 的记录器,它实现了结构化日志记录,使用它你可以例如将数据写为 json数据到 Azure 的 DocumentDB。
所以在这种情况下,如果 OrderOrchestrationId已写入 Azure 的 DocumentDB,您可以使用此 id 搜索日志,这在纯文本文件搜索中很难做到。

关于logging - MVC 日志记录范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38243239/

相关文章:

azure - ASP .NET Core 和 Azure 表存储

javascript - 嵌套对象内的函数调用失败

entity-framework - 现有数据库中的Entity Framework Core 2.0 Scaffold View

c# - Blazor OnAfterRenderAsync Javascript

java - Docker tomcat找不到应用程序日志

javascript - 如何在构造函数中设置javascript私有(private)变量?

'global' 数组的 javascript 作用域问题

python - 子类化 logging.Formatter 更改 logging.Formatter 的默认行为

c# - 如何获取 .NET WebAPI 调用的运行时间

c# - 记录器未显示在 ASP.NET Core 2.1 应用程序中