繁体   English   中英

在Log4Net中使用AdoNetAppender中的缓冲区进行延迟评估

[英]Lazy evaluation with buffers in AdoNetAppender in Log4Net

我正在使用Log4Net自定义属性将一些环境信息添加到我的日志中。 我创建了一个具有全局可访问属性的实用程序类,我的程序类使用它们来存储上下文信息(订单ID,用户ID等),并在它们周围进行惰性包装,因此无需始终更改Log4Net ThreadContext。 像这样:

public class LoggerPropertyProvider
{
    private readonly string _value;

    public LoggerPropertyProvider(string value)
    {
        _value = value;
    }

    public override string ToString()
    {
        return _value;
    }
}

我想将其作为Log4Net的属性公开的任何值,我都只是在应用程序开始时使用此惰性评估器进行注册。

ThreadContext.Properties["ORDER_ID"] = new LoggerPropertyProvider(ContextInformation.OrderId);

它适用于无缓冲区追加器 (例如滚动文件),或者在AdoNetAppender中将缓冲区设置为0时也可以正常工作。 但是,当我的buffer> 1时, Log4Net会推迟对属性的评估,直到在应用程序结束时刷新缓冲区或在buffer> bufferSize中的条目被刷新为止。

发生这种情况时,信息不再位于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更多最新详细信息,请参阅我的另一个问题的答案 。)

看来您必须将属性放在log4net线程上下文中:

log4net.ThreadContext.Properties["ORDER_ID"] = new LoggerPropertyProvider(ContextInformation.OrderId);

此上下文覆盖全局上下文中的所有属性,并由log4net自行管理:

log4net.ThreadContext

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM