【问题标题】:Is there a way parse log messages using rsyslog config and transform them to structured messages?有没有办法使用 rsyslog 配置解析日志消息并将它们转换为结构化消息?
【发布时间】:2018-10-05 02:47:06
【问题描述】:

我正在尝试解析日志消息并使用 rsyslog 将它们转换为结构化消息。有没有办法通过 rsyslog 配置支持这种操作?我还没有探索为此编写自定义解析器或消息修改插件的选项。

我发现template list properties 可以做到这一点。有没有办法做到以下几点?

  1. 将 2 个字段映射到单个输出名称。例如:“__ts”:“2018-09-20 10:18:56.363”(下面示例中的前 2 个字段)。不会在这里使用正则表达式,因为我正在寻找不依赖于字段值的解决方案。例如:这两个字段可以是两个字符串或其他一些值,而不仅仅是日期。
  2. 根据位置提取所有已知字段后,提取 msg 中剩余的内容。例如:“msg”:“使用 someOtherName 注销应用程序 nameOfAnApiHere,状态为 DOWN”。
  3. 有没有办法使用local variables 来保存msg 中的字段值并使用模板中的变量?

示例日志消息:

2018-09-20 10:18:56.363 INFO --- [Thread-68] x.y.z.key1Value 取消注册应用程序 nameOfAnApiHere with someOtherName with status DOWN

1. rsyslog 配置模板定义

template(name="structure-log-format" type="list") {
  constant(value="{")

  # This only extracts the first field with value 2018-09-20.
  # TODO: What is a way to map first 2 fields to map to __ts field? 
  property(outname="__ts" name="msg" field.number="1" field.delimiter="32" format="jsonf") constant(value=", ")

  constant(value="\"event\":[{")
    constant(value="\"payload\":{")
        property(outname="_log_" name="syslogtag" format="jsonf") constant(value=", ")
        property(outname="__loglvl" name="msg" field.number="4" field.delimiter="32" format="jsonf") constant(value=", ")
        property(outname="__thread" name="msg" field.number="7" field.delimiter="32" format="jsonf") constant(value=", ")
        property(outname="__key1" name="msg" field.number="8" field.delimiter="32" format="jsonf") constant(value=", ")
        # The following setting will include full message value starting from "2018-09-20 ... DOWN"
        # TODO: What is a way to only include message starting from "Unregistering ... DOWN"?
        property(name="msg" format="jsonf" droplastlf="on" )
    constant(value="}")
constant(value="}]} \n")

}

2。预期结果:

{
   "__ts": "2018-09-20 10:18:56.363",
   "event": [
       {
          "payload": {
             "_log_": "catalina",
             "__loglvl": "INFO",
             "__thread": "Thread-68",
             "__key1": "x.y.z.key1Value",
             "msg": "Unregistering application nameOfAnApiHere with someOtherName with status DOWN"
          }
       }
     ]
}

3。实际结果:

{
   "__ts": "2018-09-20",
   "event": [
       {
          "payload": {
             "_log_": "catalina",
             "__loglvl": "INFO",
             "__thread": "Thread-68",
             "__key1": "x.y.z.key1Value",
             "msg": "2018-09-20 10:18:56.363  INFO 2144 --- [Thread-68] x.y.z.key1Value Unregistering application nameOfAnApiHere with someOtherName with status DOWN"
          }
       }
     ]
}

谢谢。

【问题讨论】:

    标签: rsyslog


    【解决方案1】:

    您还可以使用正则表达式来匹配消息的各个部分。例如,将您的 outname="__ts" 属性替换为:

     property(outname="__ts" name="msg" 
      regex.expression="([^ ]+ +[^ ]+)" 
      regex.type="ERE" 
      regex.submatch="1" format="jsonf")
    

    这里扩展正则表达式 (ERE) 查找非空格 ([^ ]) 其中一个或多个 (+),后跟一个或多个空格,以及另一个非空格。这 2 个词被 () 捕获为子匹配项,您选择这一个,从 1 开始计数。结果应该是您想要的。

    您可以类似地使用正则表达式来满足第二个要求,或者再次计算“单词”和空格,或者更精确的其他匹配。在这里,正则表达式通过在单词和空格模式后放置重复计数{6} 来跳过 6 个单词,然后捕获其余单词 (.*)。由于有 2 组 (),因此要保留的子匹配现在是 2,而不是 1:

     property(name="msg" 
      regex.expression="([^ ]+ +){6}(.*)" 
      regex.type="ERE" 
      regex.submatch="2" format="jsonf" droplastlf="on" )
    

    【讨论】:

    • 问题 1:如果这两个字段是日期,Regex 将解决问题。但是,我正在寻找一个不依赖于字段值的通用解决方案。我正在尝试使用 rsyslog 支持类似消息映射功能 (elastic.co/guide/en/logstash/current/field-extraction.html) 的 logstash。您知道将 2 个字段映射到同一个标记的方法吗?在 logstash 中,该功能将等同于 {ts} {+ts} {+ts} ...我修改了我的问题以澄清这一点。
    • 问题 2:用于提取其余消息的正则表达式将起作用。我会试试。我有点担心使用正则表达式时对性能的影响。一旦我尝试它就会有一个想法。谢谢。
    猜你喜欢
    • 2015-07-28
    • 1970-01-01
    • 1970-01-01
    • 2012-03-26
    • 1970-01-01
    • 2018-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多