Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用NLog将未指定的对象记录到文件中,以保持ELK堆栈的兼容性?_C#_Logging_Elastic Stack_Nlog_Serilog - Fatal编程技术网

C# 如何使用NLog将未指定的对象记录到文件中,以保持ELK堆栈的兼容性?

C# 如何使用NLog将未指定的对象记录到文件中,以保持ELK堆栈的兼容性?,c#,logging,elastic-stack,nlog,serilog,C#,Logging,Elastic Stack,Nlog,Serilog,几周来,我一直在努力让NLog记录我的通信数据,包括非特定(DataContracts)参数,并以与ELK堆栈兼容的格式归档。如果输出参数可以限制为MAX chars或depth,则需要在运行时对其进行配置 NLog有一个内置的JSON序列化程序,但它只读取没有默认值的属性,正如您所看到的,字段将被忽略。调整我的数据模型将是一项艰巨的工作,我并不认为这是正确的方法,NLog不应该影响数据模型的外观 有几种方法可以添加: 我可以在每个类(Datacontract)上使用SetupSerializa

几周来,我一直在努力让NLog记录我的通信数据,包括非特定(DataContracts)参数,并以与ELK堆栈兼容的格式归档。如果输出参数可以限制为MAX chars或depth,则需要在运行时对其进行配置

NLog有一个内置的JSON序列化程序,但它只读取没有默认值的属性,正如您所看到的,字段将被忽略。调整我的数据模型将是一项艰巨的工作,我并不认为这是正确的方法,NLog不应该影响数据模型的外观

有几种方法可以添加:

  • 我可以在每个类(Datacontract)上使用SetupSerialization,如下所示:

    LogManager.Setup().SetupSerialization(s =>
       s.RegisterObjectTransformation<GetEntityViewRequest>(obj => 
           return Newtonsoft.Json.Linq.JToken.FromObject(obj)
       )
    );
    
    _comLogger.Log(LogLevel.Info, "ComLogger : {@callInfo}", callInfo);
    
  • 因此,
    IValueFormatter
    需要进行过滤,以便只处理来自通信记录器的数据。我可能需要用一个标志将数据包装在一个类中,该标志告诉
    IValueFormatter
    数据来自何处,但它并不是一个最佳的解决方案

    如您所见,让NLog实际输出
    ValueFormatter
    过滤的数据也存在问题。
    ValueFormatter
    仍在运行,但它是将在文件中结束的常规NLog JSON数据

    我从NLog需要的是:

    • 将所有通信数据(包括参数)从对象转换为字符串格式,以便ELK stack读取
    • 参数上的序列化深度或字符串最大长度,以避免数据溢出
    • 可在运行时从NLog.config进行配置(与NLog相同)
    • 仅影响特定的NLogger实例
    我的数据是通过IParameterInspector输入的,它被编译成一个特殊的CallInformation类,该类也保存参数(类型对象)。这些参数可能因多个图层而异。整个CallInfo功能对象被发送到NLog,如下所示:

    LogManager.Setup().SetupSerialization(s =>
       s.RegisterObjectTransformation<GetEntityViewRequest>(obj => 
           return Newtonsoft.Json.Linq.JToken.FromObject(obj)
       )
    );
    
    _comLogger.Log(LogLevel.Info, "ComLogger : {@callInfo}", callInfo);
    
    Nlog.config现在看起来像这样:

    
    

    我错过了什么?是否还有其他日志库可以更好地支持我的需求?

    我认为Rolf的建议是最好的-创建一个使用JSON.NET的布局。这个人可以做所有花哨的事情,比如序列化字段和处理
    [JsonIgnore]

    基本版本如下所示:

    使用System.Collections.Generic;
    使用Newtonsoft.Json;
    使用NLog;
    使用NLog.Config;
    使用NLog.布局;
    名称空间MyNamespace
    {
    /// 
    ///使用Json.NET将所有属性呈现为Json,还包括消息和异常
    /// 
    [布局(“JsonNetLayout”)]
    [线程不可知]//不同的线程,相同的结果
    [线程安全]
    公共类JSONNETLAOUT:布局
    {
    公共格式化格式化{get;set;}=Formatting.Indented;//可以从XML配置中设置此选项
    /// 
    受保护的重写字符串GetFormattedMessage(LogEventInfo logEvent)
    {
    var allProperties=logEvent.Properties??新建字典();
    allProperties[“message”]=logEvent.FormattedMessage;
    if(logEvent.Exception!=null)
    {
    allProperties[“exception”]=logEvent.exception.ToString();//ToString以防止数据属性过多
    }
    返回JsonConvert.SerializeObject(所有属性、格式);
    }
    }
    }
    
    我将使用:

    Layout.Register<JsonNetLayout>("JsonNetLayout"); // namespace NLog.Layouts
    
    这个记录器调用:

    logger
        .WithProperty("prop1", "value1")
        .WithProperty("prop2", objectWithFieldsAndJsonStuff)
        .Info("Hi");
    
    这将导致:

    {
      "prop1": "value1",
      "prop2": {
        "_myField": "value1",
        "newname": "value2"
      },
      "message": "Hi"
    }
    
    单元测试 所有这些都在单元测试中实现——使用xUnit

    [事实]
    public void JsonNetLayoutTest()
    {
    //安排
    布局。寄存器(“JSONNETLAOUT”);
    var xmlConfig=@”
    ";
    LogManager.Configuration=XmlLoggingConfiguration.CreateFromXmlString(xmlConfig);
    var logger=LogManager.GetLogger(“logger1”);
    var memoryTarget=LogManager.Configuration.FindTargetByName(“target1”);
    //表演
    var objectwithfieldsandjsonstaff=新对象withfieldsandjsonstaff();
    记录器
    .WithProperty(“prop1”、“value1”)
    .WithProperty(“prop2”,ObjectWithFields和JsonStuff)
    .Info(“Hi”);
    //断言
    var actual=memoryTarget.Logs.Single();
    预期风险值=
    @"{
    “prop1”:“value1”,
    “第2项建议”:{
    “”我的字段“”:“”值1“”,
    “新名称”:“值2”
    },
    “消息”:“嗨”
    }";
    断言。相等(预期、实际);
    }        
    
    为什么要登录到文件,而不是直接使用类似的方式将日志发送到ES。如果你有额外的属性,需要做一些重新构造/转换,你也可以将日志发送到Logstash,让它来完成所有这些…我认为该文件是这种日志记录的一个很好的缓冲区?我们也许可以做更少但更大的日志传输。但感谢您的建议,我将对此进行研究:)可能会创建一个名为NewtonsoftLayout的自定义NLog布局,允许您配置NewtonSoft JsonSerializer的操作方式。在Thankls可以找到灵感,这解决了我的问题!我需要更改为DataContractJSONSerializer,但这没关系:)