使用包装器时,如何保留Log4Net的类和方法名称以进行记录?

时间:2010-01-12 15:20:40

标签: logging log4net wrapper

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

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

我已经在this other question中看到过这样的事情,其中​​包含以下内容:

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

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

我想知道人们在做切线之前是如何做到的,然后想出一些非常复杂的东西。任何指针(链接/资源/样本)都赞赏!

3 个答案:

答案 0 :(得分:4)

Log4net允许您访问方法名称,例如此%方法。这不是最快的操作,但如果你需要调试一些东西,你很可能会使用它。我相信你的问题是如果使用包装器,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);

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

答案 1 :(得分:3)

  

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

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

答案 2 :(得分:2)

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

MethodBase.GetCurrentMethod().Name

你总是可以为Log4Net创建一个包装器来获取你需要的任何参数(比如MethodBase)吗?