使用Logstash构建数据

考虑到微服务的趋势,必须能够跨多个微服务跟踪事务。 Spring Cloud Sleuth是一种完全集成到Spring Boot生态系统中的分布式跟踪系统。 通过将spring-cloud-starter-sleuth到项目的POM中,它会立即启用Sleuth,并且每个标准日志调用都会自动将其他数据(例如spanIdtraceId到常规数据中。

2016-11-25 19:05:53.221  INFO [demo-app,b4d33156bc6a49ec,432b43172c958450,false] 25305 ---\n
[nio-8080-exec-1] ch.frankel.blog.SleuthDemoApplication      : this is an example message
折断2行以提高可读性

现在,不是将数据发送到Zipkin,而是说我需要将其存储到Elasticsearch中。 产品与使用方式一样好。 索引非结构化日志消息不是很有用。 Logstash配置允许预先解析非结构化数据并发送结构化数据。

格罗克

填充数据是使用模式匹配来构造数据的常用方法。

上周,我写了一些有关配置的提示 。 不幸的是,困难的部分在于编写匹配模式本身,而这些提示无济于事。 尽管有可能在初稿上写出完美的Grok模式,但上述日志非常复杂,以至于无法确定,并且在使用不合适的Grok过滤器启动Logstash时,很可能偶然发现此类消息:

"tags" => [
    [0] "_grokparsefailure"
]

但是,有一个“专用的应用程序 ”(听起来很熟悉?)。 它提供三个字段:

  1. 第一个字段接受一个(或多个)日志行
  2. 第二个骗子模式
  3. 第三是由第二滤波1 的结果

Grok调试器

现在的过程是从左到右一对一地匹配字段。 第一个数据字段.eg 2016-11-25 19:05:53.221显然是一个时间戳。 在常见的grok模式中 ,似乎TIMESTAMP_ISO8601模式最合适。

在模式字段中输入%{TIMESTAMP_ISO8601:timestamp} 。 结果是:

{
  "timestamp": [
    [
      "2016-11-25 17:05:53.221"
    ]
  ]
}

下一个要处理的字段看起来像日志级别。 在这些模式中,有一个LOGLEVEL 。 模式现在变为%{TIMESTAMP_ISO8601:timestamp} *%{LOGLEVEL:level} ,结果为:

{
  "timestamp": [
    [
      "2016-11-25 17:05:53.221"
    ]
  ],
  "level": [
    [
      "INFO"
    ]
  ]
}

冲洗并重复直到所有字段都已构造好。 给定初始日志行,最终模式应类似于这些行:

%{TIMESTAMP_ISO8601:timestamp} *%{LOGLEVEL:level} \[%{DATA:application},%{DATA:traceId},%{DATA:spanId},%{DATA:zipkin}]\n
%{DATA:pid} --- *\[%{DATA:thread}] %{JAVACLASS:class} *: %{GREEDYDATA:log}
折断2行以提高可读性

以及相关的结果:

{
        "traceId" => "b4d33156bc6a49ec",
         "zipkin" => "false",
          "level" => "INFO",
            "log" => "this is an example message",
            "pid" => "25305",
         "thread" => "nio-8080-exec-1",
           "tags" => [],
         "spanId" => "432b43172c958450",
           "path" => "/tmp/logstash.log",
     "@timestamp" => 2016-11-26T13:41:07.599Z,
    "application" => "demo-app",
       "@version" => "1",
           "host" => "LSNM33795267A",
          "class" => "ch.frankel.blog.SleuthDemoApplication",
      "timestamp" => "2016-11-25 17:05:53.221"
}

解剖

Grok过滤器可以完成工作。 但这似乎会遇到性能问题,特别是如果模式不匹配时。 一种替代方法是改为使用基于分隔符dissect过滤

不幸的是,没有适用于此的应用程序-但是编写基于分隔符的过滤器比基于正则表达式的过滤器要容易得多。 与上述等效的映射为:

%{timestamp} %{+timestamp} %{level}[%{application},%{traceId},%{spanId},%{zipkin}]\n
%{pid} %{}[%{thread}] %{class}:%{log}
折断2行以提高可读性

输出以下内容:

{
        "traceId" => "b4d33156bc6a49ec",
         "zipkin" => "false",
            "log" => " this is an example message",
          "level" => "INFO ",
            "pid" => "25305",
         "thread" => "nio-8080-exec-1",
           "tags" => [],
         "spanId" => "432b43172c958450",
           "path" => "/tmp/logstash.log",
     "@timestamp" => 2016-11-26T13:36:47.165Z,
    "application" => "demo-app",
       "@version" => "1",
           "host" => "LSNM33795267A",
          "class" => "ch.frankel.blog.SleuthDemoApplication      ",
      "timestamp" => "2016-11-25 17:05:53.221"
}

注意这些细微的差别:通过从基于正则表达式的过滤器移至基于分隔符的过滤器,一些字符串最终会填充空格。 有两种处理方法:

  • 更改应用程序中的日志记录模式-这可能会使直接日志读取更加困难
  • 使用Logstash删除其他空格

使用第二个选项,最终的过滤器配置代码段是:

filter {
  dissect {
	mapping => { "message" => ... }
  }
  mutate {
    strip => [ "log", "class" ]
  }
}

结论

为了构造数据, grok过滤器功能强大且被许多人使用。 但是,根据要解析的特定日志格式,编写过滤器表达式可能是一项非常复杂的任务。 基于分隔符的dissect过滤器是一种替代方法,它使其变得更容易-以一些额外的处理为代价。 如果出现性能问题,这也是一种选择。

翻译自: https://blog.frankel.ch/structuring-data-with-logstash/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值