如何将NLog中的自定义字段记录到数据库中?

时间:2012-09-14 12:11:55

标签: c# 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?

5 个答案:

答案 0 :(得分:77)

不是使用GDC(全局静态数据并且并发日志记录失败),最好使用允许传递特定于事件的自定义属性的EventProperties-Layout-Renderer

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

答案 1 :(得分:34)

以下是使用GlobalContext的一种方法。

配置:

<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以从中提取值并将其写入日志。自定义LayourRenderers易于编写。您可以在我对this question的第一个答案中看到一个示例。在那里,我展示了如何编写自己的LayoutRenderer,它将System.Diagnostics.Trace.CorrelationManager.ActivityId的当前值附加到日志消息中。

答案 2 :(得分:7)

如果这是所有人的需要,从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声明每个实例自定义变量的方法,我会很感兴趣。

答案 3 :(得分:1)

您可以使用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

答案 4 :(得分:0)

使用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