2023年4月7日金曜日

archiveEvery="Day"でローテート!ーNLogでログを出力する③

 

こんにちは、せんです。

NLogを使ったログ出力まとめの3回目です。

第1回:インストールから出力まで

第2回:出力フォーマットのカスタマイズ



アーカイブを残すには



ログを出力するときに合わせて考えるのが、アーカイブとローテートです。

前回までの内容で、App.configのターゲット要素は以下のようになっています。
<target name="logFile"
	xsi:type="File"
	encoding="UTF-8"
	fileName="logs/${processname}.log"
	layout="${date} ${level:uppercase=true:padding=-5} -${message} ${exception:format=tostring}" />

この状態でプログラムを数回実行すると、


と、こんな感じで内容が追記されていきます。

ログ出力の日時が書かかれているとはいえ、延々と一つのファイルに書き込まれるのでは、確認が大変ですよね。

というわけで今回は

①区切りのいいところでログファイルを分ける。
②古いログファイルを保存する。
③一定のアーカイブファイルがたまったら、それを削除する。

の3つの作業を行うことで、ログファイルを管理していきたいと思います。



① 区切りのいいところでログファイルを分ける

サイズか日時を設定して、ログを「ローテート」します。
archiveEveryや、archiveAboveSizeというプロパティを使用します。


②古いログファイルを保存する

ローテート後の古いログファイルは、ファイル名を変更しアーカイブフォルダに移動させるなどして保存することができます。
使用するプロパティはarchiveFileName、archiveNumbering、archiveDateFormatです。


③一定のアーカイブファイルがたまったら、それを削除する。

ファイルの保存数、もしくはファイルの保存日数を指定することで、それを超過した場合はファイルが自動で削除されます。
maxArchiveFiles、maxArchiveDaysプロパティを使用します。



ターゲットプロパティまとめ



NLog公式の説明から、ローテートとアーカイブに関するターゲットプロパティをまとめます。

archiveEvery:指定した時間が経過するたびにログファイルを自動アーカイブするかどうか。
       年月日時分のほか、毎週〇曜日という指定ができる。
archiveAboveSize:ログファイルが自動的にアーカイブされるサイズをバイト単位で取得、設定。
         archiveNumbering="Date"との併用は不可。
archiveOldFileOnStartup:起動時に古いログファイルをアーカイブするかどうか。
archiveFileName:アーカイブに使用するファイルの名前を取得、設定。
         方法ごとに一連の数字に置き換えられるプレースホルダ{#####}を含められる。
archiveDateFormat:ファイルアーカイブに使用する日付形式を指定。
          archiveNumbering="Date"または”DateAndSequence”の場合にのみ機能する。
archiveNumbering:ファイルアーカイブに番号を付ける方法。
          archiveNumberingMode
           ・Sequence:シーケンススタイル。最新のアーカイブに最大値。
           ・Rolling:ローリングスタイル。最新は常に#0、#1、…、#Nと続く。
           ・Date:日付スタイル。前回の日時を記載する。
           ・DateAndSequence:日付とシーケンススタイル。
maxArchiveFiles:保持するアーカイブファイルの最大数。
maxArchiveDays:保持するアーカイブファイルの最大日数。



組み合わせて使ってみましょう!



まずはこんな組み合わせで実行します。

 archiveEvery="Minute"
 archiveFileName="logs/archives/${processname}_{#}.log"
 archiveNumbering="Date"
 archiveDateFormat="yyyyMMddHHmmss"
 maxArchiveFiles="3"

ついでにプログラムも変更します。

using System;
using NLog;

namespace UseNLogSample
{
    public class Program
    {
        private static Logger logger = LogManager.GetCurrentClassLogger();

        static void Main(string[] args)
        {
            var timer = new System.Threading.Timer(x => GivenMilletDumplings(), null, 1000, 10000);
            Console.ReadKey();
        }

        private static void GivenMilletDumplings()
{ var companions = new string[] { "犬", "猿", "雉" }; foreach (var companion in companions) { logger.Info($"{companion}は桃太郎からきびだんごをもらいました。"); } } } }

プログラムを実行してlogsフォルダを確認します。
archivesフォルダが生成され、その中にアーカイブファイルが三件追加されます。







分単位でローテートしますが、もっとも古いファイルが削除されているので、フォルダ内のファイル数は三件のままです。




次に、内容を少し変えてみます。

 archiveAboveSize="2000"
 archiveFileName="logs/archives/${processname}_{#}.log"
 archiveNumbering="Sequence"
 maxArchiveFiles="5"

archivesフォルダを確認すると、アーカイブファイルには0から始まるシーケンシャルな番号が振られています。



少し後にもう一度覗いてみると、これまた古いファイルが自動削除されました。
maxArchiveFilesの変更が反映されていることも確認できます。




それでは次はこんな感じで。

 archiveAboveSize="2000"
 archiveFileName="logs/archives/${processname}_{#####}.log"
 archiveNumbering="Rolling"
 maxArchiveFiles="10"

アーカイブファイルに割り振られた番号は、指定の通り五桁になっています。



しばらくしてから覗くと、新しいファイルに置き換わっていますが、ファイル名は同じです。





ここからが本題



 archiveEvery="Day"
 archiveFileName="logs/archives/${processname}_{#}.log"
 archiveNumbering="Date"
 archiveDateFormat="yyyyMMdd"
 maxArchiveFiles="10"

上の設定でプログラムを実行します。
(※メモ:archiveDateFormatの値はarchiveNumbering="Date"に対応するデフォルト値と同じなので、ここではarchiveDateFormatプロパティはなくてもよい。)
次の日にもう一度実行すると、前日のファイルがアーカイブフォルダに移されました!!!


うれしいけど...
あれ、前にやったときはarchiveEvery="Day"だとarchiveフォルダすら作られなかったんだけど、なにか設定が違ったかしら???と思い、調べてみたところ、fileNameを固定の値にしないとアーカイブできないという記事を拝見しました。
(参考記事):https://qiita.com/mak_in/items/b64899b27b5fcf472daa

たしかに、前作った設定ファイルは
fileName="logs/NLogSample_${date:format=yyyyMMdd}.log"
という名前にしている...

でもarchiveEvery="Minute"にすると、ローテートできたんですよね...
まだよくわからない...


さらに調べているとこんな記事も。
最初からログファイル名に日付があれば、archiveEvery="Day"もarchiveFileName="○○"もいらないんじゃない?ということが読み取れます。
ファイル名に日付を指定していれば、別日に実行した時点で別のファイルに書き込まざるを得ないからです。

というわけで、以下の設定で実行します。

<target name="logFile"
xsi:type="File"
encoding="UTF-8"
fileName="logs/${processname}_${date:format=yyyyMMddHHmm}.log"
layout="${date} ${level:uppercase=true:padding=-5} -${message} ${exception:format=tostring}"
maxArchiveFiles="5"/>

※時間の都合上、分まで指定しています。

logsフォルダにmaxArchiveFilesの値+1のファイルが保存されます。



わあ、やっぱりできるんだ...
この辺はケースバイケースですが、どちらも頭に置いておきたいです。



まとめ


ということで、全3回でNLogについてまとめてまいりました。
これまでarchiveEvery="Day"でローテートできたことがなかったので、
日付ローテートすることが裏テーマだったのですが、
なんとかひと段落できてよかったです。


0 件のコメント:

コメントを投稿