2011-07-14 9 views
2

ロガーレベルで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. 

ようなものだ知っているが、そのようなことを行う方法はありますか?

答えて

2

私が知る限り、その能力はlog4net(またはそれに関してはNLog)には存在しません。私はうまくいくはずです。私はそれが "良い"アイディアかどうかわからないので、私はあなたに決定するために残しておきます...

簡単に、カスタムPatternLayoutConverter(see this post for one example of how to do this)を書くことができます。このコンバータは、あなた自身の静的辞書(log4netがすでに持っている静的辞書コンテキストに似ています)の中の「コンテキスト」を探します。 「コンテキスト」はロガー名で保存されます。辞書の値はの変数を保持する辞書になります。

私は今に入るために準備されたが、私はそれがうまくいくかもしれない方法を示すためにいくつかの良い擬似コードを与えることをしようとするよりも、これは少しより複雑...

UPDATE:私が持っている

(私がやった最小のテストでは)動作する実装を追加しました。私は、各ロガーのプロパティバッグを保持するための「コンテキスト」を定義しました。また、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); 
     } 
    } 
    } 
} 

設定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 

幸運!

+0

ありがとうございます。それを試してみましょう – iCode

関連する問題