ELK技术栈 - logstash学习笔记(五)

简介: 这在导入旧数据的时候固然非常有用,而在实时数据处理的时候同样有效,因为一般情况下数据流程中我们都会有缓冲区,导致最终的实际处理时间跟事件产生时间略有偏差。

时间处理(Date)


之前章节已经提过,filters/date 插件可以用来转换你的日志记录中的时间字符串,变成 LogStash::Timestamp对象,然后转存到 @timestamp 字段里。


注意:因为在稍后的 outputs/elasticsearch 中常用的 %{+YYYY.MM.dd} 这种写法必须读取 @timestamp 数据,所以一定不要直接删掉这个字段保留自己的字段,而是应该用 filters/date 转换后删除自己的字段!


这在导入旧数据的时候固然非常有用,而在实时数据处理的时候同样有效,因为一般情况下数据流程中我们都会有缓冲区,导致最终的实际处理时间跟事件产生时间略有偏差。


小贴士:个人强烈建议打开 Nginx 的 access_log 配置项的 buffer 参数,对极限响应性能有极大提升!


配置示例


filters/date 插件支持五种时间格式:


ISO8601


类似 "2011-04-19T03:44:01.103Z" 这样的格式。具体Z后面可以有 "08:00"也可以没有,".103"这个也可以没有。常用场景里来说,Nginx 的 log_format 配置里就可以使用 $time_iso8601 变量来记录请求时间成这种格式。


UNIX


UNIX 时间戳格式,记录的是从 1970 年起始至今的总秒数。Squid 的默认日志格式中就使用了这种格式。


UNIX_MS


这个时间戳则是从 1970 年起始至今的总毫秒数。据我所知,JavaScript 里经常使用这个时间格式。


TAI64N


TAI64N 格式比较少见,是这个样子的:@4000000052f88ea32489532c。我目前只知道常见应用中, qmail 会用这个格式。


Joda-Time 库


Logstash 内部使用了 Java 的 Joda 时间库来作时间处理。所以我们可以使用 Joda 库所支持的时间格式来作具体定义。Joda 时间格式定义见下表:


时间格式


Symbol Meaning Presentation Examples
G era text AD
C century of era (>=0) number 20
Y year of era (>=0) year 1996
x weekyear year 1996
w week of weekyear number 27
e day of week number 2
E day of week text Tuesday; Tue
y year year 1996
D day of year number 189
M month of year month July; Jul; 07
d day of month number 10
a halfday of day text PM
K hour of halfday (0~11) number 0
h clockhour of halfday (1~12) number 12
H hour of day (0~23) number 0
k clockhour of day (1~24) number 24
m minute of hour number 30
s second of minute number 55
S fraction of second number 978
z time zone text Pacific Standard Time; PST
Z time zone offset/id zone -0800; -08:00; America/Los_Angeles
' escape for text delimiter
'' single quote literal '


joda-time.sourceforge.net/apidocs/org…


下面我们写一个 Joda 时间格式的配置作为示例:


filter {
    grok {
        match => ["message", "%{HTTPDATE:logdate}"]
    }
    date {
        match => ["logdate", "dd/MMM/yyyy:HH:mm:ss Z"]
    }
}

注意:时区偏移量只需要用一个字母 Z 即可。


时区问题的解释


很多中国用户经常提一个问题:为什么 @timestamp 比我们早了 8 个小时?怎么修改成北京时间?


其实,Elasticsearch 内部,对时间类型字段,是统一采用 UTC 时间,存成 long 长整形数据的!对日志统一采用 UTC 时间存储,是国际安全/运维界的一个通识——欧美公司的服务器普遍广泛分布在多个时区里——不像中国,地域横跨五个时区却只用北京时间。


对于页面查看,ELK 的解决方案是在 Kibana 上,读取浏览器的当前时区,然后在页面上转换时间内容的显示


所以,建议大家接受这种设定。否则,即便你用 .getLocalTime 修改,也还要面临在 Kibana 上反过去修改,以及 Elasticsearch 原有的 ["now-1h" TO "now"] 这种方便的搜索语句无法正常使用的尴尬。


以上,请读者自行斟酌。


数据修改(Mutate)


filters/mutate 插件是 Logstash 另一个重要插件。它提供了丰富的基础类型数据处理能力。包括类型转换,字符串处理和字段处理等。


类型转换


类型转换是 filters/mutate 插件最初诞生时的唯一功能。其应用场景在之前 Codec/JSON 小节已经提到。


可以设置的转换类型包括:"integer","float" 和 "string"。示例如下:


filter {
    mutate {
        convert => ["request_time", "float"]
    }
}

注意:mutate 除了转换简单的字符值,还支持对数组类型的字段进行转换,即将 ["1","2"] 转换成 [1,2]。但不支持对哈希类型的字段做类似处理。有这方面需求的可以采用稍后讲述的 filters/ruby 插件完成。


字符串处理


  • gsub


仅对字符串类型字段有效


filter {
    mutate {
        convert => ["request_time", "float"]
    }
}

  • split


filter {
    mutate {
        split => ["message", "|"]
    }
}

随意输入一串以|分割的字符,比如 "123|321|adfd|dfjld*=123",可以看到如下输出:


{
    "message" => [
        [0] "123",
        [1] "321",
        [2] "adfd",
        [3] "dfjld*=123"
    ],
    "@version" => "1",
    "@timestamp" => "2014-08-20T15:58:23.120Z",
    "host" => "raochenlindeMacBook-Air.local"
}

  • join


仅对数组类型字段有效


我们在之前已经用 split 割切的基础再 join 回去。配置改成:


filter {
    mutate {
        split => ["message", "|"]
    }
    mutate {
        join => ["message", ","]
    }
}

filter 区段之内,是顺序执行的。所以我们最后看到的输出结果是:


{
    "message" => "123,321,adfd,dfjld*=123",
    "@version" => "1",
    "@timestamp" => "2014-08-20T16:01:33.972Z",
    "host" => "raochenlindeMacBook-Air.local"
}

  • merge


合并两个数组或者哈希字段。依然在之前 split 的基础上继续:


filter {
    mutate {
        split => ["message", "|"]
    }
    mutate {
        merge => ["message", "message"]
    }
}

我们会看到输出:


{
       "message" => [
        [0] "123",
        [1] "321",
        [2] "adfd",
        [3] "dfjld*=123",
        [4] "123",
        [5] "321",
        [6] "adfd",
        [7] "dfjld*=123"
    ],
      "@version" => "1",
    "@timestamp" => "2014-08-20T16:05:53.711Z",
          "host" => "raochenlindeMacBook-Air.local"
}

如果 src 字段是字符串,会自动先转换成一个单元素的数组再合并。把上一示例中的来源字段改成 "host":


filter {
    mutate {
        split => ["message", "|"]
    }
    mutate {
        merge => ["message", "host"]
    }
}

结果变成:


{
       "message" => [
        [0] "123",
        [1] "321",
        [2] "adfd",
        [3] "dfjld*=123",
        [4] "raochenlindeMacBook-Air.local"
    ],
      "@version" => "1",
    "@timestamp" => "2014-08-20T16:07:53.533Z",
          "host" => [
        [0] "raochenlindeMacBook-Air.local"
    ]
}

看,目的字段 "message" 确实多了一个元素,但是来源字段 "host" 本身也由字符串类型变成数组类型了!


下面你猜,如果来源位置写的不是字段名而是直接一个字符串,会产生什么奇特的效果呢?


  • strip
  • lowercase
  • uppercase


字段处理


  • rename


重命名某个字段,如果目的字段已经存在,会被覆盖掉:


filter {
    mutate {
        rename => ["syslog_host", "host"]
    }
}

  • update


更新某个字段的内容。如果字段不存在,不会新建。


  • replace


作用和 update 类似,但是当字段不存在的时候,它会起到 add_field 参数一样的效果,自动添加新的字段。


执行次序


需要注意的是,filter/mutate 内部是有执行次序的。其次序如下:


    rename(event) if @rename
    update(event) if @update
    replace(event) if @replace
    convert(event) if @convert
    gsub(event) if @gsub
    uppercase(event) if @uppercase
    lowercase(event) if @lowercase
    strip(event) if @strip
    remove(event) if @remove
    split(event) if @split
    join(event) if @join
    merge(event) if @merge
    filter_matched(event)

filter_matched 这个 filters/base.rb 里继承的方法也是有次序的。


  @add_field.each do |field, value|
  end
  @remove_field.each do |field|
  end
  @add_tag.each do |tag|
  end
  @remove_tag.each do |tag|
  end
相关文章
|
19天前
|
消息中间件 缓存 Java
ELK技术栈 - logstash学习笔记(九)
ELK技术栈 - logstash学习笔记(九)
37 0
|
19天前
|
SQL JSON API
ELK技术栈 - Elasticsearch 学习笔记(三)
ELK技术栈 - Elasticsearch 学习笔记(三)
48 0
|
10天前
|
监控 应用服务中间件 nginx
使用 Docker Compose V2 快速搭建日志分析平台 ELK (Elasticsearch、Logstash 和 Kibana)
ELK的架构有多种,本篇分享使用的架构如图所示: Beats(Filebeat) -> -> Elasticsearch -> Kibana,目前生产环境一天几千万的日志,内存占用大概 10G
43 4
|
19天前
|
JSON 数据可视化 应用服务中间件
ELK技术栈 - Kibana 学习笔记
ELK技术栈 - Kibana 学习笔记
44 0
|
19天前
|
存储 JSON API
ELK技术栈 - Elasticsearch 学习笔记(二)
ELK技术栈 - Elasticsearch 学习笔记(二)
209 0
|
19天前
|
存储 SQL JSON
ELK技术栈 - Elasticsearch 学习笔记(一)
ELK技术栈 - Elasticsearch 学习笔记(一)
189 0
|
19天前
|
存储 监控 数据可视化
日志分析对决:揭示 ELK 与 GrayLog 的优势和差异
日志分析对决:揭示 ELK 与 GrayLog 的优势和差异
368 0
|
19天前
|
存储 Prometheus 监控
Prometheus vs. ELK Stack:容器监控与日志管理工具的较量
随着容器化技术的广泛应用,容器监控与日志管理成为了关键任务。本文将对两种常用工具进行比较与选择,分别是Prometheus和ELK Stack。Prometheus是一款开源的监控系统,专注于时序数据的收集和告警。而ELK Stack则是一套完整的日志管理解决方案,由Elasticsearch、Logstash和Kibana三个组件组成。通过比较它们的特点、优势和适用场景,读者可以更好地了解如何选择适合自己需求的工具。
|
19天前
|
Go 数据处理 Docker
elk stack部署自动化日志收集分析平台
elk stack部署自动化日志收集分析平台
94 0
|
19天前
|
存储 监控 安全
ELK7.x日志系统搭建 1. elk基础搭建
ELK7.x日志系统搭建 1. elk基础搭建
84 0