【问题标题】:When using wrapper, how to preserve class and method name for Log4Net to log?使用包装器时,如何保留 Log4Net 记录的类和方法名称?
【发布时间】:2010-01-12 15:20:40
【问题描述】:

我需要一个 Log4net 包装器 - 以便在大型应用程序中暴露于许多不同的组件。我显然想在记录时保留类和方法名称,但我会避免将类型等传递给我的包装器。

我查看了this question,它与我的非常相似,但没有帮助。

我已经看到它在this other question 中使用 smt 完成,如下所示:

MethodBase methodBase = new StackTrace().GetFrame(1).GetMethod();
this.log.Debug(methodBase.Name + " : " + message);

这并不理想,因为它没有使用开箱即用的 Log4Net 功能。

我想先了解一下人们是如何做到这一点的,然后再去切线并想出一些非常复杂的东西。任何指针(链接/资源/示例)表示赞赏!

【问题讨论】:

    标签: logging log4net wrapper


    【解决方案1】:

    Log4net 允许您访问方法名称,例如 %method。这不是最快的操作,但如果您需要调试某些东西,您可以很好地使用它。我相信您的问题是,如果您使用包装器,log4net 将不会输出正确的方法名称。

    要解决这个问题,您必须查看 log4net 如何编写 ILog 实现。这基本上是内部 log4net Logger 的包装器,因此同样的问题也适用于 ILog 实现。我基本上做了以下事情:

    // define a field such as this
    private static readonly Type ThisDeclaringType = typeof(MyLogWrapper);
    
    // in constructor. Note: I use the internal Logger!
    this.Logger = LogManager.GetLogger(name).Logger;
    
    // I created a WriteLog method that calls the internal logger like this
    // you will need to translate to the internal log levels
    // message and ex are the items I want to log (ex can be null)
    this.Logger.Log(MyLogWrapper.ThisDeclaringType, log4netLevel, message, ex);
    

    显然还有一些事情要做,但重点已经提到了。

    【讨论】:

    • 嗨,这在发布模式下失败。它只是保存“?”在类名和方法名中。你遇到过这样的问题吗?如果是这样,有什么想法吗?
    • 从来没有这个问题。我可以想象编译器正在内联您的方法?
    • 是的,Log4Net 文档也提出了相同的建议,即它使用 System.Diagnostics.StackTrace 在发布模式下的工作方式不同:-(
    【解决方案2】:

    像这样创建你的包装类...

    public static class LogFourNet
        {
            // Define a static logger variable so that it references the
            private static readonly ILog Log = LogManager.GetLogger(typeof(LogFourNet));
    
            static LogFourNet()
            {
                XmlConfigurator.Configure(
                       new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "log4net.config"));
                Log.Info("Log4net is configured.");
            }
    
            public static void Info(object currentObj, string msg, [CallerLineNumber] int lineNumber = 0,
                [CallerFilePath] string caller = "", [CallerMemberName] string memberName = "")
            {
                Log.Info("[" + currentObj.GetType().Namespace + "." +
                         Path.GetFileNameWithoutExtension(caller) + "." + memberName + ":" + lineNumber + "] - " + msg);
            }
    
            public static void Debug(object currentObj, string msg, [CallerLineNumber] int lineNumber = 0,
                [CallerFilePath] string caller = "", [CallerMemberName] string memberName = "")
            {
                Log.Debug("[" + currentObj.GetType().Namespace + "." +
                          Path.GetFileNameWithoutExtension(caller) + "." + memberName + ":" + lineNumber + "] - " + msg);
            }
    
            public static void Error(object currentObj, string msg, [CallerLineNumber] int lineNumber = 0,
                [CallerFilePath] string caller = "", [CallerMemberName] string memberName = "")
            {
                Log.Error("[" + currentObj.GetType().Namespace + "." +
                          Path.GetFileNameWithoutExtension(caller) + "." + memberName + ":" + lineNumber + "] - " + msg);
            }
        }
    

    按以下方式配置您的 log4net.config 文件...

    <configuration>
      <configSections>
        <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
      </configSections>
      <log4net>
        <appender name="FileAppender" type="log4net.Appender.FileAppender">
          <file value="logfile.log" />
          <appendToFile value="true" />
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%d [%t] %-5p - %m%n" />
          </layout>
        </appender>
        <root>
          <!--LogLevel: OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL -->
          <level value="ALL" />
          <appender-ref ref="FileAppender" />
        </root>
      </log4net>
    </configuration>
    

    现在只需像这样使用上面这些方法...

    // need to pass this(current obj) as we want to log full class name
    LogFourNet.Debug(this, "started something from wrapper");
    
    output:
    -------
    2017-02-04 15:38:37,549 [1] DEBUG [WebAPI_DI.Startup.Configuration:25] - started something from wrapper
    

    【讨论】:

    • 我喜欢这个解决方案,但它不适用于静态方法。有什么建议吗?
    【解决方案3】:

    我通常会添加一些东西......(这是我需要的所有功能)

    MethodBase.GetCurrentMethod().Name
    

    您总是可以为 Log4Net 创建一个包装器,它接受您需要的任何参数(如 MethodBase)?

    【讨论】:

    • 谢谢 - 我想避免传递类型和方法名。
    猜你喜欢
    • 1970-01-01
    • 2019-04-20
    • 1970-01-01
    • 1970-01-01
    • 2015-06-17
    • 2010-09-14
    • 2010-09-14
    • 1970-01-01
    相关资源
    最近更新 更多