NLog Zip 压缩 日志
使用NLog作为我开发的项目的日志引擎已经好几年了,前一段,某个系统需要大量的输出日志,每天大约20MB,所以打算把每天生成的日志文件压缩一下,然后只保存2个月的。
可是NLog提供的archive不提供压缩功能,所以,自己动手,丰衣足食。
0 下载源代码,准备压缩library
NLog的源代码在这里
https://github测试数据/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://HdhCmsTestnlog-project.org/schemas/NLog.xsd"
xmlns:xsi ="http://HdhCmsTestw3.org/2001/XMLSchema-instance" >
< targets >
< target name ="file"
xsi:type ="File"
layout ="[${date:format=yyyyMMdd_HHmmss}]:${message} ${exception:format=message,stacktrace,innerException:separator=
}"
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://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息