我已经在我的应用程序中成功配置了log4net,但有一件事对我来说有点烦人。
即使没有错误发生,我的应用程序启动后也会创建(空)日志文件。我想在出现一些错误后才创建日志文件。
答案 0 :(得分:14)
我实际上在这个帖子中找到了一种方法:
http://www.l4ndash.com/Log4NetMailArchive/tabid/70/forumid/1/postid/18271/view/topic/Default.aspx
我测试了第一种方法,但它确实有效。为了防止链接不再好,我将在这里重现代码。基本上,作者声称有两种方法可以做到这一点。
第一种方式:
如果该记录器的适当阈值有效,则创建一个仅获取锁定(并创建文件)的新锁定模型。
public class MyLock : log4net.Appender.FileAppender.MinimalLock
{
public override Stream AcquireLock()
{
if (CurrentAppender.Threshold == log4net.Core.Level.Off)
return null;
return base.AcquireLock();
}
}
现在在配置文件中,将阈值设置为:
<threshold value="OFF" />
并确保在建模时设置这个新的LockingModel:
<lockingModel type="Namespace.MyLock" />
我正在使用滚动文件追加器。
第二种方法列在链接中。我没有尝试过这种技术,但它在技术上似乎是合理的。
答案 1 :(得分:7)
我知道这是一个老问题,但我认为这对其他人有用。
我们遇到了类似的情况,即如果没有发生错误,应用程序不应该留下空的日志文件。
我们通过创建以下自定义LockingModel类来解决它:
public class MinimalLockDeleteEmpty : FileAppender.MinimalLock
{
public override void ReleaseLock()
{
base.ReleaseLock();
var logFile = new FileInfo(CurrentAppender.File);
if (logFile.Exists && logFile.Length <= 0)
{
logFile.Delete();
}
}
}
它派生自FileAppender.MinimalLock类,它将在写入每条日志消息后释放对日志文件的锁定。
我们添加了额外的功能,如果日志文件在锁定释放后仍为空,则会删除日志文件。如果应用程序运行并退出而没有任何错误,它会阻止应用程序留下空的错误日志文件。
赞成
缺点
答案 2 :(得分:4)
以下对我有用。首次调用OpenFile()会在配置记录器时发生。后续调用是在生成实际日志消息时。
class CustomFileAppender : RollingFileAppender
{
private bool isFirstTime = true;
protected override void OpenFile(string fileName, bool append)
{
if (isFirstTime)
{
isFirstTime = false;
return;
}
base.OpenFile(fileName, append);
}
}
在配置文件中,更改appender
<log4net>
<appender name="RollingFile" type="<your namespace>.CustomFileAppender">
...
</log4net>
来自log4Net源的序列如下:
答案 3 :(得分:3)
该方法的问题在于,如果文件存在但是只读,或者存在于不存在的目录中,则在另一个错误已经导致问题之前,您将不会发现。您真的希望确保在应用程序的其余部分开始之前日志记录正在运行。
无论如何可能会这样做,但如果不是,我怀疑这就是原因。
答案 4 :(得分:2)
this message of the mailing list archive
中描述了另一种非常简单的方法基本上,使用log4net,在配置记录器时会创建日志文件。配置它做其他方面有点hacky。解决方案是推迟配置的执行。上面的消息建议在设置记录器时执行以下操作:
private static ILog _log = LogManager.GetLogger(typeof(Program));
public static ILog Log
{
get
{
if(!log4net.LogManager.GetRepository().Configured)
log4net.Config.XmlConfigurator.Configure(new FileInfo(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile));
return _log;
}
}
我通常使用程序集属性配置log4net,该属性自动配置记录器(从而创建日志文件),以及日志的简单getter:
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
...
public static log4net.ILog Log { get { return _log; } }
private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
但是删除它并使用附加逻辑添加上面的getter代替我解决了这个问题。
注意:总的来说,我同意在大多数情况下,最好在应用程序启动时配置记录器并创建文件(甚至写入它)。
答案 5 :(得分:0)
AcquireLock和ReleaseLock方法对我有用,但是很多次创建/删除了该文件让我感到困扰。这是另一个类似的选项,它关闭记录器并在程序完成时删除空的日志文件。完成日志记录后,只需调用RemoveEmptyLogFile即可。
/// <summary>
/// Sets the logging level for log4net.
/// </summary>
private static void RemoveEmptyLogFile()
{
//Get the logfilename before we shut it down
log4net.Appender.FileAppender rootAppender = (log4net.Appender.FileAppender)((log4net.Repository.Hierarchy.Hierarchy)log4net.LogManager.GetRepository()).Root.Appenders[0];
string filename = rootAppender.File;
//Shut down all of the repositories to release lock on logfile
log4net.Repository.ILoggerRepository[] repositories = log4net.LogManager.GetAllRepositories();
foreach (log4net.Repository.ILoggerRepository repository in repositories)
{
repository.Shutdown();
}
//Delete log file if it's empty
var f = new FileInfo(filename);
if (f.Exists && f.Length <= 0)
{
f.Delete();
}
} // RemoveEmptyLogFile
答案 6 :(得分:-2)
private static ILog _log = LogManager.GetLogger(typeof(Program));
public static ILog Log
{
get
{
if(!log4net.LogManager.GetRepository().Configured)
log4net.Config.XmlConfigurator.Configure(new FileInfo(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile));
return _log;
}
}