環境
- C# 2017
- .NET Framework 3.5
- NLog 4.5.7
- DotNetZip 1.11.0
経緯
昔作られていた自前のログ出力の仕組みを刷新してNLogを利用することにした。
ファイルローテートされ、そのアーカイブは圧縮してほしかった。
.NET Frameworkは3.5でなければならない。
.NET 3.5 だと素直に圧縮できない
調べたら、NLogのenableArchiveFileCompressionを指定すれば圧縮できると思ったけど、よくよく調べたら説明のenableArchiveFileCompressionにこんな記述が・・・!!
Supported in:
NLog v4.0 for .NET 4.5
散々調べてたら、たまたまIFileCompressorなるインターフェースを見つけた。
APIのIFileCompressor Interfaceを見たら、どうもenableArchiveFileCompressionによって圧縮動作をしようとした時に動作するインターフェースっぽい予感。
そこで、DotNetZipを組み合わせて、このインターフェースのCompressFile()メソッド内でやればできるんじゃないかと思ってやったら出来た。
DotNetZipを組み合わせる
- ローテートするファイル名をzipとする。
- FileTarget.FileCompressorに、ZipFileCompressorを指定する。
- ZipFileCompressorで、DotNetZipを利用してローテートされたファイルを圧縮する。
これをやったらできた。
NLog.config
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="false"
internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">
<targets>
<target xsi:type="File"
name="file"
fileName="${basedir}/logs/${var:bhtid}_${shortdate}.log"
layout="${longdate} [${uppercase:${level}}] ${message}"
archiveFileName="${basedir}/logs/archives/archive_rolling.{#}.zip"
archiveEvery="Day"
archiveAboveSize="200"
archiveNumbering="Rolling"
maxArchiveFiles="7"
enableArchiveFileCompression="true" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="file" />
</rules>
</nlog>
ZipFileCompressor.cs
internal class ZipFileCompressor : IFileCompressor
{
internal ZipFileCompressor() { }
public void CompressFile(string fileName, string archiveFileName)
{
var zip = new Ionic.Zip.ZipFile(Encoding.UTF8);
var entry = zip.AddFile(fileName);
entry.FileName = Path.GetFileName(fileName);
zip.Save(archiveFileName);
}
}
Test.cs
var logger = NLog.LogManager.GetCurrentClassLogger();
NLog.Targets.FileTarget.FileCompressor = new ZipFileCompressor();
logger.Info("これはテストです。" + DateTime.Now.ToLongTimeString());