zoukankan      html  css  js  c++  java
  • NLog Zip 压缩 日志

    使用NLog作为我开发的项目的日志引擎已经好几年了,前一段,某个系统需要大量的输出日志,每天大约20MB,所以打算把每天生成的日志文件压缩一下,然后只保存2个月的。

    可是NLog提供的archive不提供压缩功能,所以,自己动手,丰衣足食。

    0 下载源代码,准备压缩library

    NLog的源代码在这里

    https://github.com/jkowalski/NLog/archives/master

    下载 .zip,解压缩。 我下载的版本是2.0.0.2007。

     然后使用的压缩library 是DotNetZip Library

    在这里下载 http://dotnetzip.codeplex.com/ ,我使用的版本是 1.9.1.8

    1 扩展?

     最初的想法是继承FileTarget类,写一个FileExTarget类实现压缩功能,可是尝试了一下,FileTarget没有为扩展提供函数,这种方式几乎不可能实现,所以放弃了。

    2 改造

    本次改造只涉及文件日志,所以目标文件只有一个:FileTarget.cs

    添加下面的函数到 类的末尾

    复制代码
      1 #if !SILVERLIGHT  && !NET_CF
      2         private void CompressFile(string fileSource, string fileDest)
      3         {
      4 
      5             try
      6             {
      7                 Type type = Type.GetType("Ionic.Zip.ZipFile,Ionic.Zip");
      8                 if (type != null)
      9                 {
     10                     object obj2 = Activator.CreateInstance(type);
     11                     Type[] types = new Type[] { typeof(string), typeof(string) };
     12                     type.GetMethod("AddFile", types).Invoke(obj2, new object[] { fileSource, "" });
     13                     types = new Type[] { typeof(string) };
     14                     type.GetMethod("Save", types).Invoke(obj2, new object[] { fileDest });
     15                     File.Delete(fileSource);
     16                 }
     17                 else
     18                 {
     19                     File.Move(fileSource, fileDest);
     20                 }
     21             }
     22             catch
     23             {
     24                 File.Move(fileSource, fileDest);
     25             }
     26         }
     27 
     28         private string ReplaceSeq(string pattern, object value)
     29         {
     30             int firstPart = pattern.IndexOf("{#");
     31             int lastPart = pattern.IndexOf("#}") + 2;
     32             int numDigits = lastPart - firstPart - 2;
     33 
     34             if (value is int)
     35             {
     36                 return pattern.Substring(0, firstPart) + Convert.ToString((int)value, 10).PadLeft(numDigits, '0') + pattern.Substring(lastPart);
     37             }
     38             else
     39             {
     40                 return pattern.Substring(0, firstPart) + value.ToString() + pattern.Substring(lastPart);
     41             }
     42         }
     43 
     44         private DateTime GetArchiveDateTime(int value)
     45         {
     46             switch (this.ArchiveEvery)
     47             {
     48                 case FileArchivePeriod.Year:
     49                     return DateTime.Now.AddYears(-1 * value);
     50                 case FileArchivePeriod.Month:
     51                     return DateTime.Now.AddMonths(-1 * value);
     52                 case FileArchivePeriod.Day:
     53                     return DateTime.Now.AddDays(-1 * value);
     54                 case FileArchivePeriod.Hour:
     55                     return DateTime.Now.AddHours(-1 * value);
     56                 case FileArchivePeriod.Minute:
     57                     return DateTime.Now.AddMinutes(-1 * value);
     58                 default:
     59                     return DateTime.MinValue;
     60             }
     61         }
     62 
     63         private string GetDateTimeFormat()
     64         {
     65             switch (this.ArchiveEvery)
     66             {
     67                 case FileArchivePeriod.Year:
     68                     return "yyyy";
     69                 case FileArchivePeriod.Month:
     70                     return "yyyyMM";
     71                 case FileArchivePeriod.Day:
     72                     return "yyyyMMdd";
     73                 case FileArchivePeriod.Hour:
     74                     return "yyyyMMddHH";
     75                 case FileArchivePeriod.Minute:
     76                     return "yyyyMMddHHmm";
     77                 default:
     78                     return string.Empty;
     79             }
     80         }
     81 
     82 
     83         private void DatetimeArchive(string fileName, string pattern)
     84         {
     85             string baseNamePattern = Path.GetFileName(pattern);
     86 
     87             int firstPart = baseNamePattern.IndexOf("{#", StringComparison.Ordinal);
     88             int lastPart = baseNamePattern.IndexOf("#}", StringComparison.Ordinal) + 2;
     89             int trailerLength = baseNamePattern.Length - lastPart;
     90 
     91             string fileNameMask = baseNamePattern.Substring(0, firstPart) + "*" + baseNamePattern.Substring(lastPart);
     92 
     93             string dirName = Path.GetDirectoryName(Path.GetFullPath(pattern));
     94             DateTime archiveTime = this.GetArchiveDateTime(1);
     95             DateTime checkTime = this.GetArchiveDateTime(this.MaxArchiveFiles);
     96             string dateFormat = this.GetDateTimeFormat();
     97 
     98             var file2Delete = new List<string>();
     99 
    100             try
    101             {
    102 
    103 
    104                 foreach (string s in Directory.GetFiles(dirName, fileNameMask))
    105                 {
    106                     string baseName = Path.GetFileName(s);
    107                     string strFileTime = baseName.Substring(firstPart, baseName.Length - trailerLength - firstPart);
    108                     DateTime fileDate;
    109 
    110                     try
    111                     {
    112                         fileDate = DateTime.ParseExact(strFileTime, dateFormat, null);
    113                     }
    114                     catch (FormatException)
    115                     {
    116                         continue;
    117                     }
    118 
    119                     if (fileDate < checkTime)
    120                     {
    121                         file2Delete.Add(s);
    122                     }
    123                 }
    124             }
    125             catch (DirectoryNotFoundException)
    126             {
    127                 Directory.CreateDirectory(dirName);
    128             }
    129 
    130             if (file2Delete.Count > 0)
    131             {
    132                 foreach (string file in file2Delete)
    133                 {
    134                     File.Delete(file);
    135                 }
    136             }
    137 
    138             string newFileName = this.ReplaceSeq(pattern, archiveTime.ToString(dateFormat));
    139             this.CompressFile(fileName, newFileName);
    140         }
    141 #endif
    复制代码

    然后修改DoAutoArchive函数
    把 下面的代码

    1                 case ArchiveNumberingMode.Sequence:
    2                         this.SequentialArchive(fi.FullName, fileNamePattern);
    3                     break;

    改成

    复制代码
                    case ArchiveNumberingMode.Sequence:
    #if !SILVERLIGHT  && !NET_CF
                        if (this.ArchiveEvery != FileArchivePeriod.None)
                        {
                            this.DatetimeArchive(fi.FullName, fileNamePattern);
                        }
                        else
                        {
    #endif
                            this.SequentialArchive(fi.FullName, fileNamePattern);
    #if !SILVERLIGHT  && !NET_CF
                        }
    #endif
                        break;
    复制代码

    因为本次改造不对应sliverlight和net CF版,所以把编译器开关关掉。

    退到上层目录,执行build.cmd, 编译成功,改造完成。

    3 使用

    首先把 Ionic.Zip.dll放到NLog.dll的同样目录下,然后在Nog的target 里指定archiveEvery,archiveFileName, maxArchiveFiles 属性就可以了。

     archiveEvery 是归档期间,可以是 Year,  Month,   Day,    Hour,   Minute

    archiveFileName 是归档文件名的格式,基本是这样:{your log file path}/archive/log_{#}.zip

    maxArchiveFiles ,归档文件数,如果超过了,会被删除。

    最后典型的app.config里关于NLog的部分大约是这样的:

    复制代码
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <configSections>
        <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog"/>
      </configSections>
      <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <targets>
    
          <target name="file"
                                xsi:type="File"
                                layout="[${date:format=yyyyMMdd_HHmmss}]:${message} ${exception:format=message,stacktrace,innerException:separator=&#xD;&#xA;}"
                                 archiveEvery="Minute"
                                 archiveFileName ="./log/archive/log_{#}.zip"
                                 maxArchiveFiles ="6"
                                 lineEnding="CRLF"
                                concurrentWrites="false"
                                fileName="./log/log.txt" />
        </targets>
    
        <rules>
          <logger name="*" minlevel="Debug" writeTo="file" />
        </rules>
      </nlog>
    </configuration>
    复制代码

    只有NLog的用法,很简单,有需要的话,回复一下,俺再给大家讲。

    最后 俺修改后的FileTarget.cs 文件和编译后的dll,以及Ionic.Zip.dll在这里可以下载

    本修改遵守新BSD协议。

     
     
  • 相关阅读:
    python基础(常量,数据类型,if)
    c字符串操作函数
    磁盘读写,合并排序字符串
    5个学生,3门成绩,输入信息,保存到文件
    关于MQTT、HTTP、WebService
    循环队列Circular Queue
    ISR中断服务程序
    PID控制
    Linux定时器接口
    Embedded Agent
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2554971.html
Copyright © 2011-2022 走看看