web-dev-qa-db-ja.com

NLogをロールオーバーファイルロガーとして使用する

可能であれば、NLogをロールオーバーファイルロガーとして使用するにはどうすればよいですか?かのように:

31日間で最大31個のファイルが欲しいのですが、新しい日が始まったときに、古い日のログファイル##。logがある場合は削除する必要がありますが、その日はすべてのログが追加され、少なくともそこにあります。 27日間。

20

最後に、 サイズベースのファイルアーカイブ で解決しました。私はトリックを使用して、月の日だけにちなんでファイルに名前を付けています。ログが数百メガバイトを超え始めたときに非常に役立つため、サイズベースのファイルアーカイブが必要でした。たとえば、20 MBのログのチャンクを作成するのに役立つため、Notepad ++などの軽量ツールを使用して簡単に簡単に確認できます。

それはもうほぼ1年の間働いています。これが私のNLog.configファイルの簡略版です。

<?xml version="1.0" encoding="utf-8" ?>
<nlog autoReload="true" throwExceptions="true"
      xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <variable name="LogDir" value="${specialfolder:folder=MyDocuments}/MyApp/Log"/>
  <variable name="LogDay" value="${date:format=dd}"/>
  <targets>
    <target name="LogTarget1" xsi:type="File" fileName="${LogDir}/${LogDay}.log" encoding="utf-8"
        maxArchiveFiles="10" archiveNumbering="Sequence" archiveAboveSize="1048576" archiveFileName="${LogDir}/{#######}.a" />
  </targets>
  <rules>
    <logger name="AppLog" writeTo="LogTarget1" />
  </rules>
</nlog>

この構成では、月の各日に1 MBのログファイルが作成され、アーカイブされた1MBのログチャンクが最大10個My Documents\MyApp\Logフォルダーに保持されます。 29.log30.log31.logのように。

編集:このNLog.configファイルを使用するのはしばらくの間であり、必要なほとんどすべてのケースをカバーしています。異なるクラスからの異なるレベルのロギングが別々のファイルにあり、それらが大きくなると、サイズに基づいて1時間ごとにアーカイブされます。

<?xml version="1.0" encoding="utf-8" ?>
<nlog autoReload="true" throwExceptions="true" internalLogFile="nlog-internals.log"
      xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <variable name="LogHome" value="${basedir}/Log"/>
  <variable name="DailyDir" value="${LogHome}/${date:format=yyyy}/${date:format=MM}/${date:format=dd}"/>
  <variable name="HourlyArchive" value="${DailyDir}/${date:format=HH}-Archive/${level}-${logger}-{#######}-archived.a"/>
  <variable name="AppLogPath" value="${DailyDir}/${level}-${logger}.log"/>
  <variable name="DataLogPath" value="${DailyDir}/_data/inouts-${shortdate}.log"/>
  <variable name="EventSource" value="Application" />
  <targets>
    <target name="AppAsyncTarget" xsi:type="AsyncWrapper">
      <target xsi:type="RetryingWrapper" retryDelayMilliseconds="3000" retryCount="10">
        <target xsi:type="File" fileName="${AppLogPath}" encoding="utf-8"
            maxArchiveFiles="50" archiveNumbering="Sequence" archiveAboveSize="1048576" archiveFileName="${HourlyArchive}"
            layout="`${longdate}`${level}`${message}" />
      </target>
    </target>
    <target name="DataAsyncTarget" xsi:type="AsyncWrapper">
      <target xsi:type="RetryingWrapper" retryDelayMilliseconds="1500" retryCount="300">
        <target xsi:type="File" fileName="${DataLogPath}" encoding="utf-8"
            layout="`${longdate}`${message}" />
      </target>
    </target>
    <target name="EventLogAsyncTarget" xsi:type="AsyncWrapper">
      <target xsi:type="RetryingWrapper">
        <target xsi:type="EventLog" source="${EventSource}" machineName="." />
      </target>
    </target>
  </targets>
  <rules>
    <logger name="Data" writeTo="DataAsyncTarget" final="true" />
    <logger name="Event" writeTo="EventLogAsyncTarget" final="true" />
    <logger name="*" writeTo="AppAsyncTarget" />
  </rules>
</nlog>

そして、ロギング機能が必要な各クラスに、次のように記述します。

static readonly Logger SlotClassLogger = LogManager.GetCurrentClassLogger();
static Logger ClassLogger { get { return SlotClassLogger; } }

2つの追加のロガーは、毎日いくつかのデータを積み上げ、Windowsイベントログに書き込むためのものです。アプリ全体のロガーです:

public static Logger DataLog { get; private set; }
public static Logger AppEventLog { get; private set; }

また、アプリの起動時に初期化する必要があります。

DataLog = LogManager.GetLogger("Data");
AppEventLog = LogManager.GetLogger("Event");

注:アプリの終了時に、NLogによって生成された例外が発生することがあります。初期化されていないものは処分できないからです!アプリの起動時にロガーに空のエントリを書き込んだだけです。

DataLog.Info(string.Empty);

このサイズ制限を追加したので、ログファイルをローエンドサーバーのメモ帳で表示してすばやく確認できます。必要に応じて変更する必要があります。

26

問題を2つの異なる側面に分けることをお勧めします。

  • 毎日新しいファイル名にローリングします(タイムゾーンを覚えておいてください;おそらくUTC日?)
  • 古いログファイルの削除

私の経験では、ログファイル名に日付を保持する価値があります。

debug-2010-06-08.log

ドキュメントの例 を考えると、その部分はNLogで簡単にできるはずです。

これで、2番目の部分は2番目のスレッドで、または場合によっては完全に異なるプロセスで簡単に実行できます。存在するファイルの数を確認し、必要に応じて最も古いファイルを削除するだけです。ファイルシステム情報を信頼したくない場合でも、ファイル名に日付が含まれていれば、「最も古い」ものを簡単に見つけることができます。

実際、NLogのドキュメントを見ると、 "時間ベースのファイルアーカイブ" ターゲットが希望どおりに機能する可能性があります...しかし、そうでない場合でも、通常の「1つのログ」 1日あたりのファイル数」のアプローチと独自のクリーンアップのローリングは簡単なはずです。

11
Jon Skeet