gpt4 book ai didi

log4net - 记录器级别的上下文范围

转载 作者:行者123 更新时间:2023-12-04 14:42:17 25 4
gpt4 key购买 nike

有没有办法在记录器级别的 log4net 中设置上下文属性值?我们在线程上下文和全局上下文等处有作用域。我想知道是否有办法在记录器实例级别设置上下文变量?

我知道这样的事情不存在,但为了说明我的观点,它就像

 private static ILog _Log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

_Log.LoggerContext.Properties["myVar"] = "someValue";
//now every log with this logger will use somevalue for the myVar property.

有没有办法做这样的事情?

最佳答案

据我所知,log4net(或 NLog)中不存在该功能。我确实有一个应该可行的想法。我不知道这是不是一个“好”主意,我会把它留给你决定...

简而言之,您可以编写自定义 PatternLayoutConverter ( see this post for one example of how to do this )。该转换器将在您自己的静态字典中查找“上下文”(类似于 log4net 已有的静态字典上下文)。 “上下文”将按记录器名称存储。字典中的值将是保存变量的另一个字典。

这比我现在准备进入的要复杂一些,但我会尝试提供一些好的伪代码来展示它是如何工作的......

更新:

我添加了一个有效的实现(至少在我所做的最小测试中)。我已经定义了一个“上下文”来为每个记录器保存一个属性包。我还实现了一个 PatternLayoutConverter 来检索给定记录器的属性。

(代码格式似乎不支持缩进)。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using log4net;
using log4net.Util;
using log4net.Layout.Pattern;

using log4net.Core;

namespace Log4NetTest
{
//
// Context container for loggers.
// Indexable by logger or logger name.
//
public interface IContext
{
IContextProperties this [ILog logger] { get; }
IContextProperties this [string name] { get; }
}

//
// Context properties for a specific logger.
//
public interface IContextProperties
{
object this [string key] { get; set; }
void Remove( string key );
void Clear( );
}

//
// Static class exposing the logger context container.
//
public static class LoggerProperties
{
private static readonly IContext context = new LoggerContext();

public static IContext Properties { get { return context; } }
}

internal class LoggerContext : IContext
{
private readonly IDictionary<string, IContextProperties> dict = new Dictionary<string, IContextProperties>();

#region IContext Members

//
// Get the properties asociated with this logger instance.
//
public IContextProperties this [ILog logger]
{
get
{
ILoggerWrapper w = logger as ILoggerWrapper;
ILogger i = w.Logger;

return this[i.Name];
}
}

//
// Get the properties associated with this logger name.
//
public IContextProperties this [string name]
{
get
{
lock (dict)
{
IContextProperties props;
if ( dict.TryGetValue( name, out props ) ) return props;
props = new LoggerContextProperties();
dict [name] = props;
return props;
}
}
}

#endregion
}

//
// Implementation of the logger instance properties.
//
internal class LoggerContextProperties : IContextProperties
{
private readonly IDictionary<string, object> loggerProperties = new Dictionary<string, object>();

#region IContextProperties Members

public object this [string key]
{
get
{
lock ( loggerProperties )
{
object value;
if ( loggerProperties.TryGetValue( key, out value ) ) return value;
return null;
}
}
set
{
lock ( loggerProperties )
{
loggerProperties [key] = value;
}
}
}

public void Remove( string key )
{
lock ( loggerProperties )
{
loggerProperties.Remove( key );
}
}

public void Clear( )
{
lock ( loggerProperties )
{
loggerProperties.Clear();
}
}

#endregion
}

public class LoggerContextPropertiesPatternConverter : PatternLayoutConverter
{
protected override void Convert( System.IO.TextWriter writer, LoggingEvent loggingEvent )
{
IContextProperties props = LoggerProperties.Properties[loggingEvent.LoggerName];
object value = props[Option];
if (value != null)
{
writer.Write(value);
}
else
{
writer.Write("{0}.{1} has no value", loggingEvent.LoggerName, Option);
}
}
}
}

配置 appender 以使用 PatternLayoutConverter:

<appender name="debug" type="log4net.Appender.DebugAppender">
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %logger %-5p [LOGPROP = %LOGPROP{test}] %m%n"/>
<converter>
<name value="LOGPROP" />
<type value="Log4NetTest.LoggerContextPropertiesPatternConverter" />
</converter>
</layout>
</appender>

如何设置记录器的属性:

  ILog loga = LogManager.GetLogger("A");
ILog logb = LogManager.GetLogger("B");
ILog logc = LogManager.GetLogger("C");

LoggerProperties.Properties[loga]["test"] = "abc";
LoggerProperties.Properties[logb]["test"] = "def";
LoggerProperties.Properties[logc]["test"] = "ghi";

loga.Debug("Hello from A");
logb.Debug("Hello from B");
logc.Debug("Hello from C");

输出:

A: 2011-07-19 10:17:07,932 [1] A DEBUG [LOGPROP = abc] Hello from A
B: 2011-07-19 10:17:07,963 [1] B DEBUG [LOGPROP = def] Hello from B
C: 2011-07-19 10:17:07,963 [1] C DEBUG [LOGPROP = ghi] Hello from C

祝你好运!

关于log4net - 记录器级别的上下文范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6688893/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com