Logstash 时区问题导至数据被写进错误的 ES 索引的解决

2018-08-18  本文已影响0人  gruan

在上篇: .NET 的 ELK 监控方案 里, 我们将 Logstash 的配置节点 output 这样写:

output {
  elasticsearch {
    hosts => ["10.89.70.70:9600"]
    index => "%{i}-%{+YYYY.MM.dd}"
  }
}

logstash 会自动从数据中找到 i 这个字段, 并结合 @timestamp 来指定这条数据到要写到哪个 index 下面去.
如果配置中没有指定 @timestamp 从哪里取值, logstash 会默认把第一次读到取这条数据时间做为 @timestamp.

DateTime plugin
In the absence of this filter, logstash will choose a timestamp based on the first time it sees the event (at input time), if the timestamp is not already set in the event. For example, with file input, the timestamp is set to the time of each read.

但是请注意, logstash 使用的是 UTC 时间. 这个地方将会引发标题所描述的问题.

比如, 当前时间是 2018-08-17T00:29:59.618+08:00, 转换为 UTC 时间就成了 2018-08-16T16:29:59.618Z
Logstash 把这个 UTC 时间用来确定数据该存到哪个 Index 里面, 这就导至了 本来是 8月17日的数据, 却被写到 8月16 日的索引下面去了.

QQ图片20180818151434.jpg

如果只是用 Kibana 做为可视化工具, 问题不大.
但是我们每天大概能收集到 100G的日志, 搜索条件多样化 , 在加上对语法不熟悉, Kibana 已经不能给我们提供便捷的使用体验了.
但是对自制的查询工具而言, 又不能跨 index 查询(有重复的日志), 所以这个问题被无限放大了.

要解决这个问题, 又不能作大规模的改动, 最好的办法就是看有什么方法把 @timestamp 用中国时间来表示.
从百度上找了两篇文章, 说用 date filter 来修改时区, 但是写到 es 里的 @timestamp 依然是 UTC 时间, 估计也是行不通, 就没有继续在上面尝试.

input{
    file {
        path => [
            "D:/xxx/logES/*.*",
            "D:/xxx/logES/*.*",
                        ...
                        ...
        ]
        
        codec => "json"       
        max_open_files => "186000"      
        
        #监听文件的起始位置,默认是end
        start_position => end

        #监听文件读取信息记录的位置
        sincedb_path => "D:/Logstash/logs/postion.txt"      
        
        # 忽略最后修改时间超过1天的旧文件
        ignore_older => 86400
        
        # 关闭1小时内没读更新的文件
        close_older => 3600
    }
}

filter { 
   ruby { 
       code => "event.set('index_day', event.timestamp.time.localtime.strftime('%Y.%m.%d'))" 
   } 
}

output {
  elasticsearch {
    hosts => ["10.89.70.70:9600"]
    index => "%{i}-%{index_day}"
  }
}

和之前的配置比起来, 这个新配置多了一个节点: filter
用 ruby 脚本把事件的 timestamp 的本地时间赋值给 index_day (这个 index_day 并不存在于原始的日志数据中),
然后在 output 节点的 index 中使用这个 index_day. 这样一来每天8点之前的日志就会写到正确的 index 中了.

不过, 每天结束的那几分钟产生的日志有可能会被写到下一天的索引里去..


TimeZone 配置参见 Date Filter , logstash 将日志北京时间保存成utc
Filter Ruby 参见, Logstash Filter Ruby , 不要问我, 我也不会
Output elashtic Index 配置参见 Elasticsearch output plugin

上一篇下一篇

猜你喜欢

热点阅读