【问题标题】:log4net logging to multiple defined appenders using class name loggerslog4net 使用类名记录器记录到多个定义的附加程序
【发布时间】:2016-04-19 01:00:30
【问题描述】:

我想记录到多个文件(仅 2 个不同的文件),但将记录器名称与通常所做的类名保持相同:

private static readonly log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, isReadOnly);

我想保留类名,以便将其输出到记录器。

问题是,我需要根据被调用的 wcf 方法在附加程序之间动态切换(这是一个 wcf 服务)。我尝试了各种 log4net 配置设置,包括这个解决方案:

Configure Log4net to write to multiple files

但许多解决方案都有我不想要的预定义记录器名称。我也不想在 log4net 配置中硬编码我所有不同的类名并引用那些特定的记录器(维护噩梦)。

我正在寻找的是这样的:

public static ILog GetLogger(Type classType, bool shouldLogToFile2)
{
    if (shouldLogToFile2)
    {
        return LogManager.GetLogger(classType, file2Appender); // log to file2.log (this statement doesn't compile)
    }
    else
    {
        return LogManager.GetLogger(classType, file1Appender); // log to file1.log (this statement doesn't compile)
    }
}

然后这样称呼它:

ILog log = GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, true);
log.Info("This should log to file2.log");

【问题讨论】:

    标签: .net log4net


    【解决方案1】:

    如果您想拥有多个同名但使用不同附加程序的记录器,则必须设置多个存储库来包含它们。

    正如the (somewhat scanty) documentation on repositories中所说:

    可以使用LogManager.CreateRepository 方法创建命名日志存储库。可以使用LogManager.GetRepository 方法检索存储库。以这种方式创建的存储库需要以编程方式进行配置。

    然而,这并不意味着实际的配置必须在代码中,而是你应该这样做:

    // or wherever
    string configPath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; 
    
    var repository = log4net.LogManager.CreateRepository("file1repo");
    log4net.XmlConfigurator.ConfigureAndWatch(repository, new FileInfo(configPath));
    
    repository = log4net.LogManager.CreateRepository("file2repo");
    log4net.XmlConfigurator.ConfigureAndWatch(repository, new FileInfo(configPath));
    

    然后您将编写代码来修改“file2”附加程序以写入文件2:

    var appender = LogManager.GetRepository("file2repo").GetAppenders()
                             .OfType<RollingFileAppender>().Single();
    
    appender.File = "file2.log";
    appender.ActivateOptions(); 
    

    您的代码如下所示:

    public static ILog GetLogger(Type classType, bool shouldLogToFile2)
    {
        return LogManager.GetLogger(shouldLogToFile2 ? "file2repo" : "file1repo", classType);
    }
    

    【讨论】:

    • 不错。在我看到如何以编程方式创建存储库之前,它看起来很简单。它还有一个缺点是不能重用配置文件中的设置。这对 log4net 来说是一个很好的增强。
    【解决方案2】:

    在玩了几个小时之后,这就是我想出的。

    这个想法是为那些应该附加到 file2.log 的记录器在每个记录器名称前加上“File2”。然后根据传入的布尔值返回您要查找的相应记录器。

    为了防止将日志消息写入这两个文件,我决定将所有记录器从根记录器中提取出来(请参阅配置),并在代码中显式使用每个附加程序。

    配置:

    <log4net>       
        <appender name="File1Appender" type="log4net.Appender.RollingFileAppender">
          <file value="c:\file1.log" />
          <appendToFile value="true" />
          <rollingStyle value="Size" />
          <maxSizeRollBackups value="10" />
          <maximumFileSize value="50MB" />
          <staticLogFileName value="true" />
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date [%thread] %-5p %logger %message%newline" />
          </layout>
        </appender>
    
        <appender name="File2Appender" type="log4net.Appender.RollingFileAppender">
          <file value="c:\file2.log" />
          <appendToFile value="true" />
          <rollingStyle value="Size" />
          <maxSizeRollBackups value="10" />
          <maximumFileSize value="50MB" />
          <staticLogFileName value="true" />
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date [%thread] %-5p %logger %message%newline" />
          </layout>
        </appender>
    
        <root>
          <level value="ALL" />      
        </root>
        <logger name="LoggerF1">
          <appender-ref ref="File1Appender" />
        </logger>
        <logger name="LoggerF2">
          <appender-ref ref="File2Appender" />
        </logger>
    </log4net>
    

    还有代码:

    public static ILog GetLogger(Type classType, bool shouldLogToFile2 )
    {
        ILog newLogger = log4net.LogManager.GetLogger(shouldLogToFile2 ? "File2." + classType.ToString() : classType.ToString());
        Logger loggerInstance = (Logger) newLogger.Logger;
        // if the newLogger doesn't have an appender (which it won't the first time it's created) then add the appropriate appender
        if (loggerInstance.Appenders.Count == 0)
        {           
            IAppender[] appenders = LogManager.GetRepository().GetAppenders();
            IAppender appender = appenders.SingleOrDefault(a => a.Name == (shouldLogToFile2 ? "File2Appender" : "File1Appender"));
            loggerInstance.AddAppender(appender);           
        }
        return newLogger;
    }
    

    这种方式都是在配置中完成的,不会在代码中重复配置。我希望两个附加程序使用相同的日志级别,这就是为什么我将它放在根记录器而不是每个单独的记录器中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-11
      • 2017-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-03
      相关资源
      最近更新 更多