如何使用Log4Net实现日志文件的自动存档

时间:2014-10-09 10:37:57

标签: c# logging log4net

我想以这样一种方式配置log4net,即所有前一天的日志都应该自动存档。是否有可能在Log4Net中自动存档以前的日志。我想使用配置而不使用任何第三方库(如sharplibzip)编写任何代码来创建存档。

通过归档添加的另一件事是指压缩zip / rar格式的文件以节省磁盘空间。

6 个答案:

答案 0 :(得分:6)

抱歉,无法在不编写代码的情况下归档文件。但是代码不会很复杂。

您可以创建继承自RollingFileAppender的自定义appender,并覆盖AdjustFileBeforeAppend方法,以便为滚动文件添加行为。以下是滚动RollingFileAppender文件的现有方法,您可以覆盖该文件以添加存档。

使用File属性查找文件名处理

// log4net.Appender.RollingFileAppender
protected virtual void AdjustFileBeforeAppend()
{
    var fileToZip = File; // save the current file
    if (this.m_rollDate)
    {
        DateTime now = this.m_dateTime.Now;
        if (now >= this.m_nextCheck)
        {
            this.m_now = now;
            this.m_nextCheck = this.NextCheckDate(this.m_now, this.m_rollPoint);
            this.RollOverTime(true);
            // zip the file if roll occurs here
        }
    }
    if (this.m_rollSize)
    {
        if (this.File != null && ((CountingQuietTextWriter)base.QuietWriter).Count >= this.m_maxFileSize)
        {
            this.RollOverSize();
            // zip the file if roll occurs here
        }
    }
}

或者你可以找到一个现有的appender来做你想要的,但我不知道。


我冒昧地将@stuartd的评论提升到答案,因为他提出的建议非常优雅。您只需以这种方式覆盖AdjustFileBeforeAppend

protected override void AdjustFileBeforeAppend() {
    var previousFile = File;
    base.AdjustFileBeforeAppend();
    if (File != previousFile) { // zip the file }
}

这是一种非常简洁的方法,但您可能希望能够区分两种卷(即日期和大小)。例如,仅压缩日期滚动以保持日期范围的文件。

答案 1 :(得分:2)

log4net不包含任何压缩日志文件的功能。但是压缩是在.Net框架中(从4.5开始),或者您可以使用the Windows Shell API来压缩文件,因此您可以使用代码定期获取所有不是当前日志文件的日志文件并将其压缩:

-- assuming you don't have more that one appender
appender = LogManager.GetRepository().GetAppenders()
                     .OfType<RollingFileAppender>().FirstOrDefault();

if (appender == null) return; // no appenders found

var currentFile = appender.File;

-- dropping to pseudocode:
var files = Get_all_files_in_log_directory_which_match_log_file_pattern 
         but_aren't_the_current_file(current file);

if (ZipFiles(files...))
    (DeleteFiles(files); // presumably

答案 2 :(得分:0)

这是我使用DotNetZip减少的解决方案。

public class CustomRollingFileAppender : RollingFileAppender
    {
        protected override void AdjustFileBeforeAppend()
        {
            var currentFile = File;

            FileInfo fa = new System.IO.FileInfo(currentFile);

            if (fa.Length >= 10000000)
            {
                using (ZipFile zip = new ZipFile(File + ".zip"))
                {
                    string newFile =  DateTime.Now.ToString("HHmmss") + fa.Name;
                    zip.AddFile(File).FileName = newFile;
                    zip.Save(File + ".zip");
                }
            }

            base.AdjustFileBeforeAppend();
        }
    }

答案 3 :(得分:0)

我想指出,正确实现这一点的唯一方法是完全复制FileAppender源代码并从中创建adjustFileBeforeAppend()的子类。在此代码中,您可以在 await Dispatcher.RunAsync( Windows.UI.Core.CoreDispatcherPriority.Normal, () => { NavView.SelectedItem = null; NavView.Header = "myHeader; }); 中添加压缩部分。

以上samy的建议不起作用

  1. 因为第一个代码段使用私有成员(您无法在子类中访问)
  2. 因为第二个代码段假定当前日志文件名包含日期左右。但实际上,日期模式仅适用于所有旧文件,而不适用于当前文件。因此,您无法确定文件是否以代码段中显示的方式滚动。

答案 4 :(得分:0)

这是一个建议。这是一个工作代码。 它还避免在每次日志追加时读取文件信息。 相反,它将在第一个文件翻转时起作用。基于时间或基于大小。都。 一旦正在压缩当前文件。它也会gzip退出较旧的文件。在应用程序停止后剩下的。 不需要重新编码所有RollingFileAppender类。

public class CustomRollingFileAppender : RollingFileAppender
{
   
    override protected void AdjustFileBeforeAppend()
    {
        var currentFile = this.File;
        base.AdjustFileBeforeAppend();

        if (!currentFile.Equals(this.File))
        {
            CompressFileGzip(currentFile);
            var dirName = Path.GetDirectoryName(this.File);
            var files = Directory.GetFiles(dirName);
            var fileExtension = Path.GetExtension(this.File);
            foreach (var file in files)
            {
                if (!file.EndsWith(this.File) && file.EndsWith(fileExtension))
                {
                    CompressFileGzip(file.ToString());
                }
            }
        }
    }
    private void CompressFileGzip(string fileToGzip)
    {
        if (!FileExists(fileToGzip))
        {
            return;
        }
        FileInfo fileToBeGZipped = new FileInfo(fileToGzip);
        FileInfo gzipFileName = new FileInfo(string.Concat(fileToBeGZipped.FullName, ".gz"));

        using (FileStream fileToBeZippedAsStream = fileToBeGZipped.OpenRead())
        {
            using (FileStream gzipTargetAsStream = gzipFileName.Create())
            {
                using (GZipStream gzipStream = new GZipStream(gzipTargetAsStream, CompressionMode.Compress))
                {
                    fileToBeZippedAsStream.CopyTo(gzipStream);
                }
            }
        }
        System.IO.File.Delete(fileToGzip);
    }
}

答案 5 :(得分:0)

我已经修改了Masood的实现,但是我没有使用File属性(似乎没有改变),而是阅读了“从[移动]-> [至]移动”事件的LogLog消息。

为gz添加了文件时间,以避免多个“ myLog.xml.1.gz”冲突。 不想对文件名进行更好的处理。

public class CompressedRollingFileAppender : RollingFileAppender {
        private readonly Regex _moveRegex;
        private string _moveToFile = null;

        public CompressedRollingFileAppender() : base() {
            LogLog.LogReceived += LogReceived;
            _moveRegex = new Regex(@"^Moving \[(.+)\] -> \[(.+)\]$");
        }

        private void LogReceived(object source, LogReceivedEventArgs e) {
            var match = _moveRegex.Match(e.LogLog.Message);

            if (match.Groups[1].Value == this.File) {
                _moveToFile = match.Groups[2].Value;
            }
        }

        protected override void AdjustFileBeforeAppend() {
            var currentFile = this.File;
            base.AdjustFileBeforeAppend();

            if (_moveToFile != null) {
                CompressFileGzip(_moveToFile);
                _moveToFile = null;
            }
        }

        private void CompressFileGzip(string fileToGzip) {
            if (!FileExists(fileToGzip)) {
                return;
            }

            FileInfo fileToBeGZipped = new FileInfo(fileToGzip);
            // filetime 
            var filetime = DateTime.Now.ToFileTimeUtc().ToString(System.Globalization.CultureInfo.InvariantCulture);
            FileInfo gzipFileName = new FileInfo(string.Concat(fileToBeGZipped.FullName, "." + filetime + ".gz"));

            using (FileStream fileToBeZippedAsStream = fileToBeGZipped.OpenRead())
            using (FileStream gzipTargetAsStream = gzipFileName.Create())
            using (GZipStream gzipStream = new GZipStream(gzipTargetAsStream, CompressionMode.Compress))
                fileToBeZippedAsStream.CopyTo(gzipStream);

            System.IO.File.Delete(fileToGzip);
        }
    }