在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.");
}
在我的Log4Net.config中,我将requestId添加到我的模式布局中:
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%property{requestId} %d [%t] %-5p %c %m%n"/>
</layout>
使用GlobalContext设置变量线程安全的方法是什么?我是否有并发http请求的风险 不安全地更改requestId以记录另一个请求?
如果这不安全,有什么安全的实施方式?
答案 0 :(得分:14)
不,这不正确;所有线程和域共享全局上下文。在GlobalContext
上设置相同属性的两个线程将覆盖彼此的属性。 log4net.GlobalContext.Properties["requestId"]
将始终包含已启动的最新请求的请求ID。
成为threadsafe并不意味着线程无关:它意味着对象可以被多个线程同时操纵。
使用每个线程生成的ThreadContext
并允许每个线程拥有一个属性(因此每个请求,假设您的线程在某个时候没有将工作委托给另一个线程):
log4net.ThreadContext.Properties["requestId"]
答案 1 :(得分:1)
它对我有用。 我确实有这种情况,一个必须向日志发送不同信息的多线程应用程序取决于线程上下文。
使用ThreadContext而不是GlobalContext就像魅力一样。
答案 2 :(得分:0)
此类型对于多线程操作是安全的。 (log4net.GlobalContext Documentation)
编辑:doc链接可能会更新,这适用于v 1.2.15。 GlobalContextProperties
引用:
此类实现一个线程安全的属性集合,并支持存储属性和捕获当前属性的只读副本。此类针对频繁读取属性并且不经常修改的方案进行了优化。