【问题标题】:NLog not printing object from properties?NLog不从属性打印对象?
【发布时间】:2020-08-28 07:10:13
【问题描述】:

我有以下课程:

[DataContract]
public class CallInformation
{
    [DataMember]
    public string Address { get; set; }
    [DataMember]
    public Boolean IsEmpty { get; set; }
    [DataMember]
    public Boolean IsFaulted { get; set; }
    [DataMember]
    public string Action { get; set; }
    [DataMember]
    public CallOrder CallDirection { get; set; }
    [DataMember]
    public DateTime EventTime { get; set; }
    [DataMember]
    public TimeSpan Duration { get; set; }
    [DataMember]
    public Boolean IsCallback { get; set; }
    [DataMember]
    public string LogSource { get; set; } = "Unknown";

    [DataMember]
    public string Soap { get; set; }
    public string EventTimeDisplay
    {
        get { return EventTime.ToString("HH:mm:ss.fffffff"); }
        set { }
    }
}

这填充了有关客户端服务器应用程序中通信的数据,并发送到 NLog:

public void LogCommunication(CallInformation callInfo)
        {
            var logEvent = new LogEventInfo(LogLevel.Trace, "CommunicationLogger", "CommunicationLogger is logging");
            logEvent.Properties["CallInformation"] = callInfo;
            _comLogger.Log(logEvent);
        }

如果把它放在属性中是正确的还是应该放在参数中?

我需要 NLog 将其记录到文件中,以便以后可以被 Filebeat、ElasticSearch 和 Kibana 拾取和搜索。我已经尝试过这个 NLog 配置:

<logger name="CommunicationLogger" minlevel="Trace" writeto="f"></logger>

<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
            layout="${event-properties:item=CallInformation} ${message}" />

但它打印的只是 CommunicationLogger 正在记录吗?我怀疑我需要它以某种方式序列化整个对象?

问候

编辑 1 我试图改变这样的布局:

<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
            layout="${event-properties:item=CallInformation:jsonEncode=true} ${message}" />

这仍然不起作用,但如果我更改此代码,它会起作用:

logEvent.Properties["CallInformation"] = "test"; //callInfo;

test 已按原样写入文件,因此将简单类 CallInformation 解析为文件可能存在问题。

我已经检查了 NLog 的内部日志,但在那里我找不到任何错误。

编辑 2

我尝试像这样更改代码:

//var logEvent = new LogEventInfo(LogLevel.Trace, "CommunicationLogger", "ComLog writing.");
            //logEvent.Properties["CallInformation"] = callInfo;
            _comLogger.Log(LogLevel.Trace, "Test to log {@CallInformation}", callInfo);

nlog.config

<target xsi:type="File" 
            name="communicationFileLog" 
            fileName="${basedir}/logs/${shortdate}.log"
            maxArchiveDays="5" 
            maxArchiveFiles="10"
            layout="${event-properties:item=CallInformation:format@} ${message}"  />

日志文件中的结果是这样的:

 Test to log {@CallInformation}
 Test to log {@CallInformation}
 Test to log {@CallInformation}
 Test to log {@CallInformation}
...

【问题讨论】:

  • 这能回答你的问题吗? Why do I get FormatException with NLog?
  • "如果把它放在属性中是正确的,还是应该放在参数中?"这是在这里回答的吗? stackoverflow.com/questions/61713960/…。这取决于您的消息中是否需要它。我会选择属性。
  • 你也需要这样的东西${event-properties:item=LogData:jsonEncode=true},同样在stackoverflow.com/questions/61713960/…
  • 谢谢,我试过这个:layout="${event-properties:item=CallInformation:jsonEncode=true} ${message}" /> 但我仍然只在日志文件中得到消息. _comLogger.Log(logEvent) 的结果将使用 FileTarget 和 CustomTarget 进行配置。 CustomTarget 解包 objekt 并将其发送给应用程序中的 vewier,File 目标将尝试在文件中以文本形式表达对象。
  • 如果我将 logEvent.Properties["CallInformation"] 更改为 logEvent.Properties["CallInformation"] = "test" 它可以正常工作,因此将简单类解析为文件似乎存在问题.我在 nlog 内部日志文件中看不到任何错误。

标签: c# elasticsearch config nlog


【解决方案1】:

需要告知 NLog,LogEvent 属性对于反射和序列化是安全的。正常的做法是这样的:

_compLogger.Trace("CommunicationLogger is logging {@CallInformation}", callInfo);

NLog 将知道 LogEvent 属性 "CallInformation" 可以安全序列化,因为 @。

如果您有一种异国情调,并且不希望 LogEvent 消息中包含该属性,那么您可以这样做:

var logEvent = new LogEventInfo(LogLevel.Trace, _comLogger.Name, "CommunicationLogger is logging");
logEvent.Properties["CallInformation"] = callInfo;
_comLogger.Log(logEvent);

然后在Format-option中指定特殊属性:

<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
            layout="${event-properties:item=CallInformation:format=@}" />

另请参阅:https://github.com/NLog/NLog/wiki/How-to-use-structured-logging#output-captured-properties

附:除了使用@(激活NLog 自己的序列化程序)之外,您还可以为您的callInfo-object 覆盖ToString(),然后在那里执行自定义序列化。另一种选择是让callInfo-object 实现IFormattable,并提供带有LogEventInfo 的自定义IFormatProvider。

【讨论】:

  • 我将布局更改为 layout="${event-properties:item=CallInformation:format=@}" 但我根本没有得到任何输出。 nlog-internal.log 中也没有错误。
  • 是的,我也认为 ToString 解决方案是最后的手段,但这意味着我无法通过 nlog.config 控制要显示的内容,CallInformation 对象将是全部或全部。从我解开的内容中,我将能够指出我想将 CallInformation 的哪一部分打印到目标。
  • 请参阅编辑 2。它似乎根本不想序列化这个简单的对象。
  • @Banshee 看起来您已禁用消息模板解析。还要注意你写的是${event-properties:item=CallInformation:format@}而不是指定的${event-properties:item=CallInformation:format=@}(缺少=)
  • @Banshee 这个日志语句对我有用:logger.Log(NLog.LogLevel.Warn, "Test to log {@CallInformation}", new { Hello = "World" }); 所以我猜你已经用抛出异常(或禁用 MessageTemplateParsing)的东西覆盖了 IValueFormatter 或 IJsonConverter
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-09
  • 2023-01-11
相关资源
最近更新 更多