这种情况发生时,信息不再位于global属性中,或者它的值已更改(例如循环处理订单),因此我在日志中得到了错误或空值.我能看到解决此问题的唯一方法是停止使用缓冲区,因此刷新条目时将在所有调用中评估属性值.由于仅在刷新缓冲区时才评估ThreadContext中的属性,所以我担心每个日志调用都不能具有不同的属性值.在缓冲条目而不是刷新条目时,有什么方法可以使Log4Net评估ThreadContext(或它具有的其他上下文)?谢谢解决方案默认情况下,log4net不会 fix 属性提供者的值在登录时来自上下文,用于缓冲的附加程序.它们在缓冲区刷新时得到评估.要解决此问题,必须从log4net.Core命名空间实现IFixingRequired.public class LoggerPropertyProvider : IFixingRequired{ private readonly string _value; public LoggerPropertyProvider(string value) { _value = value; } public override string ToString() { return _value; } object IFixingRequired.GetFixedObject() { return ToString(); }}(经过我自己的属性提供程序的测试,由于我自己的需要,该属性提供者依赖于http上下文:// We can not use log4net ThreadContext or LogicalThreadContext with asp.net, since// asp.net may switch thread while serving a request, and reset the call context in// the process.public class HttpContextValueProvider : IFixingRequired{ private string _contextKey; public HttpContextValueProvider(string contextKey) { _contextKey = contextKey; } public override string ToString() { var currContext = HttpContext.Current; if (currContext == null) return null; var value = currContext.Items[_contextKey]; if (value == null) return null; return value.ToString(); } object IFixingRequired.GetFixedObject() { return ToString(); }}一般想法来自同人博客.请参见我的其他答案如果您想了解有关此HttpContextValueProvider的最新信息.)I'm using Log4Net custom properties to add some environmental information into my logs. I created an utility class with global accessible properties that my program classes use to store context information (order id, user id, etc) and a lazy wrapper around them so I don't need to change Log4Net ThreadContext all the time. Something like this:public class LoggerPropertyProvider{ private readonly string _value; public LoggerPropertyProvider(string value) { _value = value; } public override string ToString() { return _value; }}Whatever value I want to expose as a property to Log4Net I just register using this lazy evaluator at the start of the application.ThreadContext.Properties["ORDER_ID"] = new LoggerPropertyProvider(ContextInformation.OrderId);It works just fine with buffer-less appenders (such as rolling file) or when the buffer is set to 0 in AdoNetAppender. However, when I have buffer > 1 Log4Net defers the evaluation of the property until the buffer is flushed at the end of the application or when entries in buffer > bufferSize.When this happens the information is not in the global property anymore or it's value has been changed (like a loop processing orders) so I get a wrong or null value in my logs.The only option I can see to fix this is stop using buffers so the property value is evaluated in all calls when the entry is being flushed. Since the properties in ThreadContext are only evaluated when the buffer is being flushed I'm afraid I cannot have a different property value for each log call.Is there any way I can make Log4Net evaluate a ThreadContext (or some other context it has) when buffering the entry instead of when it flushes it?Thanks 解决方案 By default, log4net does not fix property provider values from contexts at log time for buffered appenders. They get evaluated at buffer flush time.To solve this issue, you have to implement IFixingRequired from log4net.Core namespace.public class LoggerPropertyProvider : IFixingRequired{ private readonly string _value; public LoggerPropertyProvider(string value) { _value = value; } public override string ToString() { return _value; } object IFixingRequired.GetFixedObject() { return ToString(); }}(Tested with my own property provider, which relies on http context due to my own needs: // We can not use log4net ThreadContext or LogicalThreadContext with asp.net, since// asp.net may switch thread while serving a request, and reset the call context in// the process.public class HttpContextValueProvider : IFixingRequired{ private string _contextKey; public HttpContextValueProvider(string contextKey) { _contextKey = contextKey; } public override string ToString() { var currContext = HttpContext.Current; if (currContext == null) return null; var value = currContext.Items[_contextKey]; if (value == null) return null; return value.ToString(); } object IFixingRequired.GetFixedObject() { return ToString(); }}General idea coming from piers blog. See this my other answer to another questionif you'd like more up to date details about this HttpContextValueProvider.) 这篇关于在Log4Net中使用AdoNetAppender中的缓冲区进行延迟评估的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-22 18:12
查看更多