【问题标题】:in ASP.NET core (.NET5) how can i write logs for each request on separate files? Using Serilog or other在 ASP.NET 核心 (.NET5) 中,如何将每个请求的日志写入单独的文件?使用 Serilog 或其他
【发布时间】:2021-06-30 16:20:49
【问题描述】:

我是 .NET 和 Web 服务开发的新手,所以我不确定如何实现我的要求。

  • 我的 web 服务收到一个包含一些数据的 POST 请求,我需要这些数据 生成pdf文件的过程:name_YYYYMMDDHHmmss.pdf。
  • 为了监控这一点,我想为每个请求创建一个单独的日志文件,命名为输出文件:name_YYYYMMDDHHmmss.log
  • 我想避免将配置对象传递到我需要向日志文件中添加内容的每个类/函数中

我已经成功安装了 Serilog,它可以满足我的需要,但当我收到并发请求时就不行了。我也不确定.NET 中是如何处理同时请求的(到目前为止我还没有编写线程特定的代码),但据我所知,当我更改 Global Logger 文件名时,该对象在所有线程之间共享所以他们都写入同一个文件。

我查看了一堆解决方案,但我没有找到任何适合这个的解决方案,而且似乎大多数人都将所有内容都放在一个文件中......

你有什么线索或提示可以给我吗?我愿意使用 Serilog 以外的东西。

【问题讨论】:

  • 当您创建特定的 PDF 时,似乎可以使用自定义接收器,如 this onepush a context property
  • 这方面有什么更新吗?
  • @tom 恐怕不会。我对此进行了进一步研究,问题似乎与每个线程中如何共享全局变量有关。在我的应用程序的下一个版本中,计划是在创建新对象时包含对父对象的引用,并让子对象要求父对象生成新日志。这样应该可以将每个请求的日志分开。

标签: asp.net .net concurrency serilog


【解决方案1】:

根据特定上下文获得动态文件名的一种方法是使用Serilog.Sinks.Map,然后通过请求管道中的中间件,您可以将属性添加到驱动要使用的文件名的日志上下文写入日志时。

Serilog.Sinks.Map 的类似用法示例来决定在运行时使用哪个文件名:

【讨论】:

  • 我已经看过了,但我正在努力了解如何使用 Sinks.Map 来做到这一点。我仍然需要在我进行的每个 Log 调用中传递文件名,这就是我试图避免的。我基本上需要在处理代码开始时为每个请求生成文件名,并将其传递给每个函数调用以便能够使用它。我误解了这个吗?或者有没有办法让一些全局变量不与其他线程共享?
【解决方案2】:

我发现这个问题的最佳解决方案是使用Serilog.Sinks.Map。我像这样配置了我的记录器:

Log.Logger = new LoggerConfiguration()
    .WriteTo.Map("Name", "Default", (name, wt) => {
        var fileName = name == "Default" ? "log" : $"{log-{name}}" 

        wt.File($"./{fileName}-.txt");
    }).CreateLogger();

然后在我的控制器上,在我需要此功能的每个方法上,我将所有指令包含在 LongContext 中,如下所示:

[HttpGet]
public IHttpActionResult Get() {
   using (LogContext.PushProperty("Name", "theFileName") {
       // ...
       _myService.Method1();
       // ...
   }
}
public class MyService : IMyService {
   // ...

   public void Method1() {
      // ...
      Log.Information("This is what happened at this point…");
      // ...
   }
   // ...
}

因此,所有日志内部都将使用该上下文,并将写入具有您为该上下文设置的名称的不同文件,而无需修改任何 Log.Information/Error/Warning/etc 您已经在您的代码上。 这是丑陋的部分……您必须在根位置定义上下文,以使这些日志写入不同的文件。所以对于一个控制器方法,你要做的第一件事就是用一个 LogContext 把所有的都括起来。

【讨论】:

  • 感谢您的回复。我的主要困难是“theFileName”。我需要将它作为输入传递给需要记录的每个方法/对象。还是我错过了什么?
  • 不,如果您为这些日志设置上下文,则无需再传递任何内容。我更新了答案,看看吧
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-24
  • 2018-02-03
  • 1970-01-01
相关资源
最近更新 更多