NLogによるデータベースログ記録の実践ガイド

NLogは、.NETアプリケーション向けの堅牢で高機能なログライブラリです。コンソール、ファイル、クラウドサービスなど、様々な出力先(ターゲット)にログを記録する機能を提供しますが、特にデータベースへのログ記録は、集中的なログ管理において非常に有用です。本記事では、NLogを使用してログをSQL Serverデータベースに記録するための設定と実装方法を解説します。

NLogのインストールと初期設定

まず、新しい.NETプロジェクト(例えば、コンソールアプリケーション)を作成し、NuGetパッケージマネージャーを使用してNLogをインストールします。

Install-Package NLog

NLogパッケージがインストールされると、プロジェクトにNLog.configというXML設定ファイルが自動的に追加されます。このファイルがNLogの動作を制御する中心となります。

データベースターゲットの構成

NLog.configファイルを開き、<targets>セクション内にデータベースへのログ記録を設定するターゲットを追加します。

<target xsi:type="Database"
        name="databaseLog"
        connectionString="Data Source=.;Initial Catalog=LogDB;Integrated Security=True">
  <commandText>
    INSERT INTO ApplicationLogs ([Timestamp], [OriginCaller], [LogLevel], [MessageText], [StackTraceInfo])
    VALUES (@timestamp, @originCaller, @logLevel, @messageText, @stackTraceInfo);
  </commandText>
  <parameter name="@timestamp"      layout="${longdate}" />      <!-- ログ発生時刻 -->
  <parameter name="@originCaller"  layout="${callsite}" />      <!-- ログ呼び出し元 -->
  <parameter name="@logLevel"      layout="${level}" />         <!-- ログレベル -->
  <parameter name="@messageText"   layout="${message}" />      <!-- ログメッセージ -->
  <parameter name="@stackTraceInfo" layout="${stacktrace}" /> <!-- スタックトレース情報 -->
</target>

上記の構成では、以下の点を設定しています:

  • xsi:type="Database": ターゲットがデータベースであることを指定します。
  • name="databaseLog": このターゲットを一意に識別する名前です。
  • connectionString: データベースへの接続文字列です。ここではSQL ServerのローカルインスタンスにあるLogDBデータベースを指定しています。
  • commandText: ログをデータベースに挿入するためのSQL INSERT文です。
  • <parameter>: SQL文の各パラメータと、NLogのレイアウトレンダラをマッピングします。例えば、${longdate}は現在の日時、${level}はログレベルに置き換えられます。

ログを記録する前に、指定したデータベースにログ情報を格納するためのテーブルを作成しておく必要があります。以下にApplicationLogsテーブルの作成例を示します。

CREATE TABLE ApplicationLogs (
    LogID INT IDENTITY(1,1) PRIMARY KEY,
    Timestamp DATETIME NOT NULL,
    OriginCaller NVARCHAR(500),
    LogLevel NVARCHAR(10) NOT NULL,
    MessageText NVARCHAR(MAX),
    StackTraceInfo NVARCHAR(MAX)
);

ロギングルールの定義

次に、どのログメッセージをどのターゲットに送るかを指定するルールを<rules>セクションに追加します。

<rules>
  <logger name="*" minlevel="Info" writeTo="databaseLog" />
</rules>

このルールは、「すべてのロガー(name="*")からのInfoレベル以上のログを、databaseLogという名前のターゲットに書き込む」ことを意味します。

C#コードからのログ記録

NLogの設定が完了したら、C#コードからログを記録します。以下は簡単なコンソールアプリケーションの例です。

using NLog;
using System;

public class Program
{
    private static readonly Logger appLogger = LogManager.GetCurrentClassLogger();

    public static void Main(string[] args)
    {
        // ログレベルFatalのメッセージを記録
        appLogger.Fatal("アプリケーションで致命的なエラーが発生しました。詳細はログを確認してください。");

        // ログレベルErrorのメッセージを記録
        appLogger.Error(new Exception("Null参照エラー"), "ユーザー情報の取得中に予期せぬ問題が発生しました。");

        Console.WriteLine("ログメッセージをデータベースに送信しました。");
        Console.ReadKey();
    }
}

このコードを実行すると、設定に応じてデータベースにログエントリが追加されます。

複数のターゲットへのログ記録とデバッグ設定

NLogでは、ログレベルに応じて異なるターゲットにログを振り分けることができます。例えば、すべてのログをファイルに、エラーレベル以上のログをデータベースに記録するといった設定が可能です。

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      throwExceptions="true" internalLogFile="c:\nlog_internal_errors.txt" internalLogLevel="Debug">

  <targets>
    <target name="fileLog" xsi:type="File"
            fileName="${basedir}/logs/application-${shortdate}.txt"
            layout="${longdate} | ${level:uppercase=true} | ${callsite} | ${message} ${exception:format=tostring}" />

    <target name="databaseLog" xsi:type="Database"
            connectionString="Data Source=.;Initial Catalog=LogDB;Integrated Security=True">
      <commandText>
        INSERT INTO ApplicationLogs ([Timestamp], [OriginCaller], [LogLevel], [MessageText], [StackTraceInfo])
        VALUES (@timestamp, @originCaller, @logLevel, @messageText, @stackTraceInfo);
      </commandText>
      <parameter name="@timestamp"       layout="${longdate}" />
      <parameter name="@originCaller"   layout="${callsite}" />
      <parameter name="@logLevel"       layout="${level}" />
      <parameter name="@messageText"    layout="${message}" />
      <parameter name="@stackTraceInfo" layout="${stacktrace}" />
    </target>
  </targets>

  <rules>
    <logger name="*" minlevel="Trace" writeTo="fileLog" /> <!-- 全てのログをファイルに -->
    <logger name="*" minlevel="Error" writeTo="databaseLog" /> <!-- エラー以上のログをデータベースに -->
  </rules>
</nlog>

<nlog>ルート要素のthrowExceptions="true"internalLogFileinternalLogLevel属性は、NLog自身の内部エラーやデバッグ情報を指定したファイルに出力するためのもので、ログ設定の問題を診断する際に非常に役立ちます。

カスタムプロパティの利用

NLogが提供する標準のログ情報だけではなく、アプリケーション固有の追加情報をログに含めたい場合があります。NLogでは、event-contextレイアウトレンダラを使用してカスタムプロパティを定義し、ログに含めることができます。

まず、データベーステーブルに新しいカスタムカラムを追加します。例えば、AppNameModuleNameCorrelationIDなどです。

CREATE TABLE ExtendedApplicationLogs (
    LogID INT IDENTITY(1,1) PRIMARY KEY,
    AppName NVARCHAR(100),
    ModuleName NVARCHAR(100),
    CorrelationID NVARCHAR(50),
    Timestamp DATETIME NOT NULL,
    LogLevel NVARCHAR(10) NOT NULL,
    MessageText NVARCHAR(MAX),
    StackTraceInfo NVARCHAR(MAX)
);

次に、NLog.configを更新してこれらのカスタムプロパティをデータベースターゲットにマッピングします。

<target name="customDatabaseLog" xsi:type="Database"
        connectionString="Data Source=.;Initial Catalog=LogDB;Integrated Security=True">
  <commandText>
    INSERT INTO ExtendedApplicationLogs ([AppName], [ModuleName], [CorrelationID], [Timestamp], [LogLevel], [MessageText], [StackTraceInfo])
    VALUES (@appName, @moduleName, @correlationId, @timestamp, @logLevel, @messageText, @stackTraceInfo);
  </commandText>
  <parameter name="@appName"       layout="${event-context:item=AppName}" />
  <parameter name="@moduleName"    layout="${event-context:item=ModuleName}" />
  <parameter name="@correlationId" layout="${event-context:item=CorrelationID}" />
  <parameter name="@timestamp"     layout="${longdate}" />
  <parameter name="@logLevel"      layout="${level}" />
  <parameter name="@messageText"   layout="${message}" />
  <parameter name="@stackTraceInfo" layout="${stacktrace}" />
</target>

そして、C#コードからこれらのカスタムプロパティを設定してログを記録します。LogEventInfoクラスを使用し、Propertiesディクショナリを介して値を渡します。

using NLog;
using System;

public class Program
{
    private static readonly Logger customLogger = LogManager.GetLogger("CustomLog"); // 新しいロガー名

    // カスタムプロパティを含むログを記録するメソッド
    public static void LogCustomEvent(LogLevel level, string appName, string moduleName, string correlationId, string message)
    {
        LogEventInfo logEvent = new LogEventInfo(level, customLogger.Name, message);
        logEvent.Properties["AppName"] = appName;
        logEvent.Properties["ModuleName"] = moduleName;
        logEvent.Properties["CorrelationID"] = correlationId;
        
        customLogger.Log(logEvent);
    }

    public static void Main(string[] args)
    {
        LogCustomEvent(LogLevel.Info, "OrderProcessingApp", "PaymentModule", Guid.NewGuid().ToString(), "支払い処理が正常に完了しました。");
        LogCustomEvent(LogLevel.Warn, "OrderProcessingApp", "InventoryModule", Guid.NewGuid().ToString(), "在庫レベルが閾値を下回りました。");

        Console.WriteLine("カスタムログメッセージをデータベースに送信しました。");
        Console.ReadKey();
    }
}

このアプローチにより、アプリケーションのニーズに合わせて柔軟にログデータを拡張し、データベースに保存することが可能になります。

タグ: NLog C# .NET SQL Server logging

6月1日 06:10 投稿