我正在为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 ....
答案 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());
}
}