首页 > 解决方案 > 无法让 NLog 从代码中以数字/整数/长整数形式发送字段

问题描述

我们的策略是通过 NLog 库将 c# .net 4.7 记录到“Graylog”GELF 输入,这当然是将它们存储在弹性搜索集群中。

该应用程序大量使用日志记录,但所有内容都作为字符串发送 - 无论它是否不是代码中的字符串。

我希望能够将我的自定义记录器属性作为它们的真实数据类型发送,以便我可以汇总我的统计数字字段。

我不想限制我的开发人员并使用脚本字段来执行此操作,或者在 elasticsearch 中预先映射索引 - 事实上,graylog 为我管理我的索引。我也不想使用 graylog 管道处理器——我可怜的 graylog 做的工作已经够多了。我希望他们能够将统计数据作为真实数据类型发送,并将它们映射为“long”或“number”。

我的东西的代码片段:

public void InfoExtended2(String Message, Dictionary<string, int> extrafields, [CallerMemberName] string callerMethodName = "", [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
        {
            var fileName = callerFilePath.Substring(callerFilePath.LastIndexOf(@"\") + 1).Replace(".cs", "");
            var caller = $"{fileName}.{callerMethodName}()Line:{sourceLineNumber}";
            var logger = LogManager.GetLogger(caller);

            if (!(extrafields.Count == 0))
            {
                foreach (var field in extrafields)
                {
                    string mykey = field.Key.ToString();
                    extrafields.TryGetValue(field.Key, out int myvalue);
                    //be careful whats in object! 
                    if (!logger.Properties.ContainsKey(mykey)) { logger.Properties.Add(mykey, "{@myvalue}"); } else { logger.Properties[mykey] = "{@myvalue}"; }
                }
            }

            logger.Info()
                .Message(Message)
                .Property("ComeOnNow3", 87)

                .Write();

            // Create the LogEventInfo object
            //LogEventInfo logEvent = new LogEventInfo();

            // Now add the event characteristics
            //logEvent.Properties["EventCode"] = 2222;
            //logEvent.Level = NLog.LogLevel.Info;
            //logEvent.Properties["EventCode]."]
            //logEvent.Message = "My Message";
            ////logEvent.Exception = ex;
            //logger.Log(logEvent);

            //logger.Info("{@Message}", new Dictionary<string, int> { { "key1", 1 }, { "key2", 2 } }); // dict. Result:  Test "key1"=1, "key2"=2

        }

我在那里尝试了几种不同的方法,但都没有运气。

如果我使用表示整数而不是字符串的 JSON 字段来调用自己的 POST GELF,它会起作用。我的字段对索引来说是全新的,当我去检查映射时,它会很长。我希望我的代码能够做到这一点。

测试 GELF 调用:

{
  "version": "1.1",
  "host": "example.org",
  "short_message": "A short message that helps you identify what is going on",
  "full_message": "Backtrace here\n\nmore stuff",
  "timestamp": 1385053862.3072,
  "level": 1,
  "_user_id": 9001,
  "_some_info": "foo",
  "_some_env_var": "bar"
}

用户 ID 的结果映射:

          "user_id" : {
            "type" : "long"

我们的 nlog 目标当前的样子:

<targets>
      <target name="gelftcp"
      type="gelftcp"
      facility="Custom Facility"
      remoteaddress="192.168.95.15"
      remoteport="12201"
      layout="${longdate}${newline}type: ${level:uppercase=true}${newline}class: ${logger}${newline}stacktrace: ${stacktrace}${newline}error message: ${message}${newline}exception: ${exception:format=tostring,data:maxinnerexceptionlevel=10}">
        <parameter name="logged_at" layout="${longdate}" />
        <parameter name="type" layout="${level:uppercase=true}" />
            <parameter name="class" layout="${logger}" />
        <parameter name="CustomInt" layout="${event-properties:item=CustomInt}" as="number" />
            <parameter name="stacktrace" layout="${stacktrace}" />
            <parameter name="error_message" layout="${message}" />
        <parameter name="ComeOnNow3" layout="${event-properties:item=ComeOnNow3} " />
            <parameter name="exception" layout="${exception:format=tostring,data:maxinnerexceptionlevel=10}" />
        <attribute name="eventProperties" encode="false" >
          <layout type='JsonLayout' includeAllProperties="true"  maxRecursionLimit="2"/>
        </attribute>
          <variable name="ComeOnNow2" value ="${event-context:ComeOnNow2}" />

      </target>

放轻松,我不是这段代码的原作者。只是一个负责在当前状态下弥补松弛和部署的人。

更新: 尝试了第一个建议。甚至添加了我正在测试的字段:

<field name="ComeOnNow3" layout="${threadid}" type="System.Int32" />

尝试了这个日志条目:

logger.Info()
                .Message(Message)
                .Property("ComeOnNow3", 87)
                .Write();

我的映射仍然作为“关键字”返回。

解决了:

诀窍是切换到 Http 而不是 Tcp。

标签: c#.netelasticsearchnloggraylog

解决方案


而不是使用“gelftcp”。然后你可以试试 GelfLayout:

https://www.nuget.org/packages/NLog.GelfLayout

您可以将其与 TCP 网络目标结合使用:

<nlog>
  <extensions>
    <add assembly="NLog.Layouts.GelfLayout" />
  </extensions>

  <targets async="true">
    <target type="Network" name="gelftcp" address="tcp://192.168.95.15:12201" newLine="true" lineEnding="Null">
        <layout type="GelfLayout" facility="MyFacility">
            <field name="threadid" layout="${threadid}" type="System.Int32" />
        </layout>
    </target>
  </targets>

  <rules>
    <logger name="*" minlevel="Debug" writeTo="gelftcp" />
  </rules>
</nlog>

它也有一些简单的 NLog LogEventInfo.Properties (Decimal + Double + Integer + Boolean) 的自动转换逻辑

更多示例可以在这里找到:https ://github.com/farzadpanahi/NLog.GelfLayout


推荐阅读