使用 NLog 事件上下文布局渲染器以毫秒精度记录日期时间

Posted

技术标签:

【中文标题】使用 NLog 事件上下文布局渲染器以毫秒精度记录日期时间【英文标题】:Logging datetime with ms precision using NLog event context layout renderer 【发布时间】:2014-03-19 04:57:19 【问题描述】:

我正在尝试使用 NLog 2 将一些审计信息记录到 SQL Server 2008 表中。为了能够将参数传递给 SQL 插入查询,我正在使用 LogEventInfo 和 Event Context Layout Renderer。

日志记录本身有效,但日期时间仅以秒精度存储。我希望能够以毫秒精度进行存储,但没有找到任何可以告诉我如何做到这一点的东西。

这是我记录事件的 C# 代码:

private void LogMessage(DateTime requestDateTime)

    LogEventInfo theEvent = new LogEventInfo(LogLevel.Debug, "", "Pass my custom value");
    theEvent.Properties["RequestDate"] = requestDateTime;

这是我在 NLog.config 配置中的目标:

<target xsi:type="Database"
      name="SqlLog"
      dbProvider="sqlserver"
      connectionString="server=localhost;database=Test;integrated security=sspi">
  <commandText>
    INSERT [dbo].[ApiLog]
    (
        [ServerName], [RequestDate]
    )
    VALUES (@ServerName, @RequestDate);
  </commandText>
  <parameter name="@ServerName" layout="$machinename"/>
  <parameter name="@RequestDate" layout="$event-context:item=RequestDate"/>
</target>

我使用theEvent.Properties["RequestDate"] = requestDateTime.ToString("yyyy-MM-dd HH:mm:ss.fff") 找到了一种解决方法,但我不希望这样做,因为那样您可能会遇到日期时间格式和文化问题。

有谁知道我可以通过 NLog.config 中的配置更改精度的方法吗?

【问题讨论】:

【参考方案1】:

看起来 EventContextLayoutRenderer 使用了Convert.ToString,这将失去您正在寻找的精度:

public class EventContextLayoutRenderer : LayoutRenderer

    //....

    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    
        object value;

        if (logEvent.Properties.TryGetValue(this.Item, out value))
        
            builder.Append(Convert.ToString(value, CultureInfo.InvariantCulture));
        
    

您可能知道(我不确定它是否对您的情况有帮助),但是有一个日期布局,您可以在其中指定格式和/或 LongDate 格式,它会提供类似2014-01-01 12:12:12.1234

编辑

不管怎样,您可以非常轻松地添加客户布局渲染器

[LayoutRenderer("event-context-dateTime")]
public class DateTimeContextLayoutRenderer : EventContextLayoutRenderer

    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    
        object value;

        if (logEvent.Properties.TryGetValue(this.Item, out value))
        
            //Your code here
        
    

在你的配置中

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <extensions>
    <add assembly="YourAssembly"/>
  </extensions>
  <targets>
    <target xsi:type="File" name="file"  fileName="c:\temp\NlogLayout.txt" 
     layout="$longdate $event-context-dateTime:item=RequestDate" />
   ...
</nlog>

【讨论】:

谢谢乔。如果我实现自己的 LayoutRenderer,那么它仍然使用 StringBuilder 将 DateTime 构建为字符串。所以没有办法通过 NLog 将实际的 DateTime 传递给 SQL。我已将您的答案标记为答案,因为它至少提供了一个比在调用代码中执行格式化更简洁的解决方案。

以上是关于使用 NLog 事件上下文布局渲染器以毫秒精度记录日期时间的主要内容,如果未能解决你的问题,请参考以下文章

NLog时间格式化

如何为 Application Insights NLog 目标设置上下文

NLog的介绍使用

在windows / c ++上使用多进程应用程序进行高精度定时操作

ASP.NET Core 使用NLog打印html格式日志

NLog 通过http保存日志