web-dev-qa-db-ja.com

NLogのカスタムフィールドをデータベースに記録するにはどうすればよいですか?

私は現在、多くのプロジェクトでNLogを使用しています。一部では、データベースにログインします。

これが私がやりたいことです:

CREATE TABLE [dbo].[NLogEntries](
  [Id] [bigint] IDENTITY(1,1) NOT NULL,
  [Origin] [nvarchar](100) NOT NULL,
  [LogLevel] [nvarchar](20) NOT NULL,
  [Message] [nvarchar](3600) NOT NULL,
  [CreatedOn] [datetime] NOT NULL,
  [OrderId] [int] NULL --Custom field!
)

このターゲットを使用したNLog.config:

<target type="Database" name="database" connectionstring="Server=localhost;Database=NLog;Trusted_Connection=True;">
  <commandText>
    INSERT INTO NLogEntries ([Origin], [Message], [LogLevel],[CreatedOn],[OrderId]) VALUES (@Origin,@Message,@LogLevel,@Date, @OrderId);
  </commandText>
  <parameter name="@Date" layout="${date}"/>
  <parameter name="@Origin" layout="${callsite}"/>
  <parameter name="@LogLevel" layout="${level}"/>
  <parameter name="@message" layout="${message}"/>
  <parameter name="@OrderId" layout="${orderId}"/> <!-- custom field! -->
</target>

そして、次のようなログを記録します。

var logger = LogManager.GetCurrentClassLogger();
var orderId = 123;
logger.Debug("What is going on here", orderId);

これを行い、NLogを使い続ける良い方法はありますか?または、これらの要件がある場合、独自のロガーをロールしてNLogをスキップする必要がありますか?

41
Kjensen

グローバルな静的データ用であり、同時ログに失敗するGDCを使用するよりも、 EventProperties-Layout-Renderer を使用して、イベント固有のカスタムpropertiesを渡すことができます

LogEventInfo theEvent = new LogEventInfo(logLevel, "", message);
theEvent.Properties["OrderId"] =orderId;`

log.Log(theEvent);

... and in your NLog.config file: 
${event-context:item=OrderId}  -- obsolete
${event-properties:item=OrderId} -- renders OrderId
80

GlobalContextを使用する1つのアプローチを次に示します。

構成:

<target type="Database" name="database" connectionstring="Server=localhost;Database=NLog;Trusted_Connection=True;">
  <commandText>
    INSERT INTO NLogEntries ([Origin], [Message], [LogLevel],[CreatedOn],[OrderId]) VALUES (@Origin,@Message,@LogLevel,@Date, @OrderId);
  </commandText>
  <parameter name="@Date" layout="${date}"/>
  <parameter name="@Origin" layout="${callsite}"/>
  <parameter name="@LogLevel" layout="${level}"/>
  <parameter name="@message" layout="${message}"/>
  <parameter name="@OrderId" layout="${gdc:OrderId}"/> <!-- custom field! -->
</target>

呼び出しサイト:

var logger = LogManager.GetCurrentClassLogger();
GlobalDiagnosticsContext.Set("OrderId",123);
logger.Debug("What is going on here"); //If you use the logging configuration above, 123 will be logged to the OrderId column in your database

もう少し努力すれば、 here に示すテクニックのいずれかを使用してNLogロガーをラップできます。

または、独自の「コンテキスト」オブジェクトを作成し、カスタムLayoutRendererを記述して、そこから値を取得し、ログに書き込みます。カスタムLayourRendererは簡単に記述できます。 この質問 に対する最初の回答で例を見ることができます。そこで、System.Diagnostics.Trace.CorrelationManager.ActivityIdの現在の値をログメッセージに追加する独自のLayoutRendererの作成方法を示します。

36
wageoghe

それだけで十分な場合は、NLogバージョン4.3.3以降、カスタム変数を宣言してアクセスする簡単な方法があります。 注意:これらのソリューションはいずれもスレッドセーフではありません。

以下をNLog.configに追加します

<nlog ...
    <!-- optional, add some variables -->  
    ...
    <variable name="myvarone" value="myvalue"/>
    <variable name="myvartwo" value=2/>
     ...
</nlog>

コード内の変数は、次の方法で変更/アクセスできます。

LogManager.Configuration.Variables["myvarone"] = "New Value"
LogManager.Configuration.Variables["myvartwo"] = 2

値はNLog.configで参照できます。

"${var:myvarone}"  -- renders "New Value"
"${var:myvartwo}"  -- renders 2

前述したように、varおよびLogEventInfoオブジェクトはグローバルです。したがって、複数のインスタンスが定義されている場合、値を変更すると、すべてのインスタンスの値が変更されます。 NLogのインスタンスごとのカスタム変数を宣言する方法を誰かが知っている場合、私は非常に興味があります。

9
Balash

MDCコードを使用できます。

var logger = LogManager.GetCurrentClassLogger();

MDC.Set("OrderId", 123);
MDC.Set("user", HttpContext.Current.User.Identity.Name);
// ... and so on

これも確認してください http://weblogs.asp.net/drnetjes/archive/2005/02/16/374780.aspx

2
Eldar

NLog 4.6.3では、これがより簡単になり、スレッドセーフになりました!

コール

int orderId = 123; 
logger.WithProperty("MyOrderId", orderId).Info("This is my message!"); 

構成:

<target type="Database" name="database" connectionstring="Server=localhost;Database=NLog;Trusted_Connection=True;">
  <commandText>
    INSERT INTO NLogEntries ([Origin], [Message], [LogLevel],[CreatedOn],[OrderId]) VALUES (@Origin,@Message,@LogLevel,@Date, @OrderId);
  </commandText>
  <parameter name="@Date" layout="${date}" dbType="DbType.Date"/>
  <parameter name="@Origin" layout="${callsite}"/>
  <parameter name="@LogLevel" layout="${level}"/>
  <parameter name="@message" layout="${message}"/>
  <parameter name="@OrderId" layout="${event-properties:MyOrderId}" dbType="DbType.Int32"/> <!-- custom field! Note also the DB Type -->
</target>

NLog 4.6はDbTypeもサポートしていることに注意してください- https://nlog-project.org/2019/03/20/nlog-4-6-is-live.html を参照してください

2
Julian