log4net.GlobalContext.Properties是否每个请求不同?

the*_*ski 5 .net c# logging log4net asp.net-web-api

在log4net中,我想为特定的http请求的每个日志语句附加一个请求id.请求ID在多个请求中是不同的.在我的global.asax.cs中,我分配了一个requestId.

   protected void Application_BeginRequest(object sender, EventArgs e)
    {

        log4net.GlobalContext.Properties["requestId"] =
    System.Guid.NewGuid().ToString();
      log.Info("Starting request.");  
    }
Run Code Online (Sandbox Code Playgroud)

在我的Log4Net.config中,我将requestId添加到我的模式布局中:

<layout type="log4net.Layout.PatternLayout">
 <param name="ConversionPattern" value="%property{requestId} %d [%t] %-5p %c %m%n"/>
</layout>
Run Code Online (Sandbox Code Playgroud)

是使用GlobalContext设置变量线程安全的方法吗?我是否有并发http请求的风险,不安全地更改requestId以记录另一个请求?

如果这是不安全的,那么实施什么是安全的方法?

sam*_*amy 14

不,这不正确; 所有线程和域共享全局上下文.设置相同属性的两个线程GlobalContext将覆盖另一个属性.log4net.GlobalContext.Properties["requestId"]将始终包含已启动的最新请求的请求ID.

作为线程并不意味着线程独立的:这意味着该对象可以被多个线程同时进行操作.

使用ThreadContext每个线程的生命周期并让每个线程拥有一个属性(因此每个请求,假设你的线程在某个时候没有将工作委托给另一个线程): log4net.ThreadContext.Properties["requestId"]

  • 感谢您的答复。我选择了 LogicalThreadContext,我相信它在使用 await/async 时很有用,即不同的线程可能会在异步生命周期的不同点处理请求。 (2认同)
  • @ user1483903您可能现在已经知道这一点,但是LogicalThreadContext应该做您想要的。它使用CallContext.LogicalSetData / LogicalGetData实现。Logical [Get | Set] Data调用非常有用,因为使用这些函数存储的数据将传递给子线程。因此,如果您正在处理请求,并且存储了请求ID(或某些标识符),然后使用子线程(或任务)实际执行了请求,则子线程(或任务)将可以访问与存储的相同请求ID在前面。 (2认同)