如何以编程方式强制 log4net 释放日志文件以便可以访问它?

Posted

技术标签:

【中文标题】如何以编程方式强制 log4net 释放日志文件以便可以访问它?【英文标题】:How to programmatically force log4net to release log file so it can be accessed? 【发布时间】:2019-10-09 05:27:49 【问题描述】:

我需要在大型流程执行后发送一封电子邮件,并将日志文件作为附件,以便用户可以识别任何问题。我们使用 log4net 来处理我们所有的日志记录,但我无法让 log4net 释放文件,因此可以将其添加为附件。

到目前为止,我关注了这个问题的结果:How to stop log4net from logging and release the last file about setting the appender threshold to "Off",但由于 DLL 没有释放日志文件,我继续收到异常。我可以在调试器中验证 appender 实际上处于“关闭”状态,但进程资源管理器确认我的 exe 仍然锁定文件。

这是我从链接问题中得到的方法:

 private static void SetThreshold(string appenderName, log4net.Core.Level threshold)
        
            foreach (log4net.Appender.AppenderSkeleton appender in log4net.LogManager.GetRepository().GetAppenders())
            
                if (appender.Name == appenderName)
                
                    appender.Threshold = threshold;
                    break;
                
            
        

任何如何强制发布此日志的想法都会非常有帮助。谢谢

【问题讨论】:

【参考方案1】:

使用我从一位同事那里获得的以下代码块,我可以获得对日志的只读访问权限(需要写入权限才能用作电子邮件中的附件):

 var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            var lines = new List<string>();
            using (var sr = new StreamReader(fs))
            
                while(!sr.EndOfStream)
                
                    lines.Add(sr.ReadLine());
                
            

我能够获取这个列表并写入一个临时文件并使用它来发送我们的附件,而不必担心修改 log4net 和危及针对同一 log4net DLL 的其他程序集的任何依赖关系。

感谢分享想法的两个人!

【讨论】:

【参考方案2】:

日志已打开以供写入,因此释放锁的唯一方法是停止应用程序。您确实有选择:1)使用 maximumFileSize 设置将日志文件分成块,以便只有最近的日志不可用; 2) 将消息记录到数据库(log4net 提供了这样的接口,参见https://www.c-sharpcorner.com/article/configure-log4net-with-database-tutorial-for-beginners/)。

【讨论】:

【参考方案3】:

当使用FileAppenderRollingFileAppender时,可以配置日志文件LockingModel。使用适当的LockingModel 应该允许所需的文件访问权限。 来自 log4net 文档 (https://logging.apache.org/log4net/release/sdk/index.html)

共有三种内置锁定模型:

FileAppender.ExclusiveLock FileAppender.MinimalLock FileAppender.InterProcessLock

第一个从记录开始到结束锁定文件,第二个在记录每条消息时仅锁定最短时间,最后一个使用命名的系统范围互斥锁同步进程。

默认锁定模型是 FileAppender.ExclusiveLock。

以下配置示例来自https://logging.apache.org/log4net/release/config-examples.html

<appender name="FileAppender" type="log4net.Appender.FileAppender">
    <file value="$TMP\log-file.txt" />
    <appendToFile value="true" />
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
    <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger [%propertyNDC] - %message%newline" />
    </layout>
</appender>

编辑: LockingModel 公开了一个 ReleaseLock 方法,它将强制文件被进程释放。要继续记录,您必须拨打AcquireLock

【讨论】:

这似乎很有用,但我能够获得对文件的只读访问权限,所以我只是将内容复制到临时文件并将其用作附件。

以上是关于如何以编程方式强制 log4net 释放日志文件以便可以访问它?的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式配置 log4net,但额外的日志记录到控制台

有没有办法以可编程方式刷新 log4net 中的缓冲区

有啥方法可以监控 log4net 日志文件以获取应用程序洞察力

有没有办法以编程方式判断 FastMM 是不是没有释放特定的内存块?

我可以强制生成 JVM 崩溃日志文件吗?

log4net日志系统使用详解