我想记录多个文件(仅限2个不同的文件),但保留记录器名称与类名称相同,如通常所做的那样:
private static readonly log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, isReadOnly);
我想保留类名,以便将其输出到记录器。
问题是,我需要根据被调用的wcf方法在appender之间动态切换(这是一个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");
答案 0 :(得分:1)
如果您想拥有多个具有相同名称但使用不同appender的记录器,则必须设置多个存储库以包含它们。
正如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'写入file2的appender:
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);
}
答案 1 :(得分:0)
玩了几个小时之后,这就是我想出来的。
这个想法是为每个记录器名称添加“File2”作为应该附加到file2.log的记录器的前缀。然后根据传入的布尔值返回您正在查找的相应记录器。
为了防止将日志消息写入这两个文件,我决定将所有记录器从根记录器中取出(参见config)并在代码中明确使用每个appender。
配置:
<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;
}
这种方式都是在配置中完成的,并且代码中没有重复配置。我想要两个appender使用相同的日志级别,这就是为什么我把它放在根记录器而不是每个单独的记录器中。