好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

NLog Zip 压缩 日志

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

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协议。

 

 

标签:  NLog Zip 压缩 日志

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于NLog Zip 压缩 日志的详细内容...

  阅读:45次