使用包含Log4net的包装类时如何记录方法名称

时间:2009-07-19 12:57:32

标签: .net log4net

我正在为log4.net实现自定义XML格式化程序

public class ISDSApplicationEventsLayout : XmlLayoutBase
{
    protected override void FormatXml(...)
    {
        //Location Info 
        writer.WriteStartElement("Method");
        writer.WriteString(**loggingEvent.LocationInformation.MethodName * *);
        writer.WriteEndElement();
    }
}

问题是......现在当我从日志包装器类调用log方法时...称为日志记录

public static void logEvent(string message)
{
    log.Info(isdsLog); 
}

我得到输出....

  <Method>logEvent</Method>

如何使用名为logEvent的方法名称而不是logEvent作为方法名称?

谢谢

问题更新:

如果以上看起来有点复杂 - 我真正要问的是:如何保留在log4net中调用包装日志功能的方法的上下文...

示例...方法doWork()...调用 - &gt;日志包装器 - &gt;调用log4net ....

如何制作methodname = doWork和NOT logging wrapper function ....

3 个答案:

答案 0 :(得分:16)

实际上,您可以使用开箱即用的log4net轻松解决此问题。您的包装器可以调用Logger.Log并将包装类的类型作为第一个参数传递。所以,你的包装器可能看起来像这样:

public class MyLog4NetWrapper
{
  ILog log = LogManager.GetLogger("WhateverYourLoggerNameIs");

  public void logEvent(string message) 
  {     
    log.Logger.Log(typeof(MyLog4NetWrapper), LogLevel.Info, message, null);
  } 
}

当log4net记录消息时,它遍历调用堆栈,直到它到达其声明类型等于作为Log方法的第一个参数传入的类型的方法。堆栈的下一个方法是实际的呼叫站点。

至于包装log4net记录器,我不确定我是否会建议创建一个静态包装器类。主要问题是您的app.config文件中只能有一个可配置的记录器。换句话说,您将无法独立控制代码不同部分的日志记录。如果你有A类和B类,并且都使用静态包装的记录器,那么这两个类将记录在同一级别。如果你想为A类开启登录,对B班开关,你将无法这样做。

答案 1 :(得分:1)

我认为您不能通过开箱即用的log4net轻松解决这个问题。如果我们看一下the LogImpl class中的ILog.Info方法,那你要调用:

    virtual public void Info(object message) 
    {
        Logger.Log(ThisDeclaringType, m_levelInfo, message, null);
    }

当记录消息时,log4net将遍历当前调用的堆栈跟踪,以便找到启动日志操作的方法。为此,Log4net使用“ThisDeclaringType”类型作为搜索的边界,选择该类型中的第一个“上方”调用作为启动方法。

在您的情况下,遇到的第一个方法是logEvent方法。如果删除了logEvent包装器并直接使用了日志记录方法,那么您将获得所需的信息。

答案 2 :(得分:0)

用于log4net记录器的包装器,分3个步骤:

添加对log4net软件包(NugetPackage)的引用

添加您的包装器类,确保调用log4net.Config.XmlConfigurator.Configure();在包装器类的静态构造函数中。这将从app.config加载所有配置。

在您的app.config中添加log4net配置

请参见下面的示例包装器类。

  public class Logger : ILogger
{
    private static readonly log4net.ILog log;


    static Logger()
    {
        log = log4net.LogManager.GetLogger(System.Reflection.MethodInfo.GetCurrentMethod().DeclaringType);
        log4net.Config.XmlConfigurator.Configure();
    }

    public void Log(LogLevel logLevel, string message, params object[] args)
    {
        switch (logLevel)
        {
            case LogLevel.DEBUG: {
                    // log.Logger.Log helps logging actual method and the class which has called this method (Log(LogLevel logLevel, string message, params object[] args))
                    log.Logger.Log(typeof(Logger), log4net.Core.Level.Debug, string.Format(message, args), null);
                    break;
                }
            case LogLevel.INFO:
                {                       
                    log.Logger.Log(typeof(Logger), log4net.Core.Level.Info, string.Format( message, args) , null);
                    break;
                }
            case LogLevel.ERROR:
                {
                    log.Logger.Log(typeof(Logger), log4net.Core.Level.Error, string.Format(message, args), null);
                    break;
                }
            case LogLevel.WARN:
                {
                    log.Logger.Log(typeof(Logger), log4net.Core.Level.Warn, string.Format(message, args), null);
                    break;
                }
        }

    }

    public void LogException(LogLevel logLevel, Exception exception)
    {
        Log(logLevel, exception.ToString());
    }
}