2010-03-28 71 views

回答

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" /> 

我与滚动文件appender一起使用。

第二种方法在链接中列出。我没有尝试过这种技术,但它在技术上似乎很合理。

+1

对于任何试图跟随的答案,我相信乔恩斯基特的回答实际上是对这个答案的注释。 – 2013-02-13 18:14:45

+1

可否请您描述第二种方法是什么,因为链接不起作用。当链接不再起作用时,链接上的方法是毫无意义的。 – 2015-06-01 19:02:02

+0

我使用这种技术来创建一个NoLock。我的情况是我在Web应用程序中使用日志文件配置,但实际上在具有类似配置的Windows服务中写入它。 Web应用程序正在锁定文件和不同的锁类型最小,InterProcess没有帮助。现在,Web应用程序使用log4net配置将所有日志文件显示为admin,但不锁定由windows服务实际使用的文件。非常感谢你的回答。我在这里浪费了大约5-6个小时。 – 2016-05-06 13:52:26

3

该方法的问题在于,如果文件存在但是只读,或者位于不存在的目录等,那么直到另一个错误已经导致问题才会发现。您确实希望确信在应用程序的其他部分启动之前日志记录正在运行。

还有可能无论如何是这样做的一种方式,但如果不是,我怀疑这是原因。

1

那是相当简单的另一种方法在this message of the mailing list archive

基本上被描述,与log4net的,记录器被配置成当创建日志文件。要配置它做别的是有点哈克。解决方案是推迟配置的执行。

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的,和一个简单的吸气剂为:上述消息设置记录器时建议执行以下操作日志:

[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); 

但删除,并添加上面的获取与额外的逻辑,而不是解决了我的问题。

注意:一般来说,我同意在大多数情况下最好在应用程序启动时配置记录器并创建文件(甚至写入文件)。

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类写入每个日志消息后,将释放上的日志文件锁的。

我们添加了额外的功能,如果在锁定释放后它仍然为空,它将删除日志文件。它可以防止应用程序在运行时退出空错误日志文件,并且无任何错误退出。

优点

  • 它仍然会创建期间log4net的的配置阶段的空日志文件,确保日志记录应用程序启动时的其余部分之前的工作。但是,日志文件会立即删除。
  • 它不要求您通过将阈值设置为“OFF”关闭日志配置文件,并且稍后会在编写第一个日志事件之前以编程方式打开日志记录。

缺点

  • 这是最有可能的管理你的日志文件,因为RELEASELOCK方法的缓慢方法,并且,将后,被称为是写入每个日志事件的文件长度检查到日志文件。只有在您希望有很少的错误时才使用它,并且这是一个业务要求,即在没有错误时日志文件不应存在。
  • 空白时创建并删除日志文件。如果您有其他工具监视日志目录中的文件系统更改,则可能会出现问题。但是,在我们的情况下这不是问题。
+0

我最喜欢这种方法,一旦文件包含数据,通过设置一个标志可以削弱第一个con,这样后续对'ReleaseLock'的调用将不再检查文件信息。 – ZoolWay 2016-06-18 11:21:23

-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; 
    } 
} 
+0

和?.....你的代码示例在这个问题上做了什么? – 2014-03-20 14:54:51

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 
3

以下工作了me.The第一次调用的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); 
    } 

}

而且在配置文件中,改变附加器

<log4net> 
<appender name="RollingFile" type="<your namespace>.CustomFileAppender"> 
... 
</log4net> 

从log4net的源的序列如下:


  • 第一次调用OpenFile()是因为从FileAp调用的ActivateOptions() Pender的构造函数。
  • 当生成日志消息时,AppenderSkeleton的DoAppend()调用PreAppendCheck()
  • PreAppendCheck()在FileWriterAppender(FileAppender的基础)中被覆盖。
  • 如果文件尚未打开,则重写的PreAppendCheck()会调用虚拟PrepareWriter 。 FileAppender的
  • PrepareWriter()调用SafeOpenFile(),它依次调用的OpenFile()
相关问题