logstash工作中相关笔记

1,293 阅读3分钟

时区问题

其实这个问题是最难受的,记得刚开始研究elk的时候,就发现时间在logstash里比北京时间慢8小时,写入es后,es里的时间也同样是比北京时间慢8小时

我们也用了kibana,开始奇怪的是在kibana中,时间又显示正常了。后来发现一篇帖子logstash最佳实践中有一段话

很多中国用户经常提一个问题:为什么 @timestamp 比我们早了 8 个小时?怎么修改成北京时间?
其实,Elasticsearch 内部,对时间类型字段,是统一采用 UTC 时间,存成 long 长整形数据的!对日志统一采用 UTC 时间存储,是国际安全/运维界的一个通识——欧美公司的服务器普遍广泛分布在多个时区里——不像中国,地域横跨五个时区却只用北京时间。
对于页面查看,ELK 的解决方案是在 Kibana 上,读取浏览器的当前时区,然后在页面上转换时间内容的显示。
所以,建议大家接受这种设定。否则,即便你用 .getLocalTime 修改,也还要面临在 Kibana 上反过去修改,以及 Elasticsearch 原有的 ["now-1h" TO "now"] 这种方便的搜索语句无法正常使用的尴尬。
以上,请读者自行斟酌。

最后发现如果时间串是带时区的,例如这样2020-04-29T09:39:15.000+0800这个串的含义是UTC+8,也就是2020-04-29T09:39:15.000这个时间已经是加过8小时的。这样在es的mapping中这样设置

"xxx_time" : {
  "format" : [
    "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
  ],
  "type" : "date"
}

这样es能够识别时区,且kibana显示正常。

分为两种情况,一种是读jdbc时间是timestamp类型,另一种是字符串形式

读jdbc

个人经验,在filter|ruby中,一条数据被封装成了一个event对象。如果是input|jdbc,那么在logstash中的做法如下:

filter{
  ruby {
    # event.get('time')这个类型在ruby中是timestamp。
    # event.get('time').time这是ruby中timestamp类型转换成time类型
    # event.get('time').time.localtime这是转换成操作系统本地的时区
    # 最后就是输出我们想要的字符串 注意后面的小写z
    # 输出效果为2020-05-28T11:15:24.000+0800
    code => "event.set('time', event.get('time').time.localtime.strftime('%Y-%m-%dT%H:%M:%S.%3N%z'))"
  }
} 

读文本

input是kafka的话,数据就是字符串,这时候就想办法把时间字符串后面补上+0800即可

# 例如kafka中的数据是json:{"time":"2020-05-28T13:25:31.774"}
filter {
  ruby {
    code => " 
      # 直接在后面跟上+0800 凑齐这个格式就OK
      event.set('time',event.get('message')+'+0800')
    "
  }
}

convert转换数据类型

今天在公司有个需求,数据是一条条\t分割的结构化数据。需要做成json数据吐到kafka。正好对logstash比较熟,打算拿logstash

  • logstash默认吐出来的数据都是String类型的,同事被吐槽了我一顿。
  • 使用filter里的mutute#convert可以自定义数据类型。
  • 自己测试的数据如1 张三 96.9
mutate {
    convert => {
        "score" => "float"
        "id" => "integer"
    }
    remove_field => ["@timestamp","@version","message"]
}

得到的结果为

{
     "name" => "张三",
    "score" => 96.9,
       "id" => 1
}
  • 解决需求!