zoukankan      html  css  js  c++  java
  • elastic date时区问题解决办法

    之前介绍filter date插件时就谈到时区问题,但是没有说明白。最近在使用range查询时间范围内的数据时出现了数据量不一致的情况。特地了解了下ELK Stack中关于时区的问题。

    问题:

    使用kibana discovery界面搜索时,数据量一致。使用curl 搜索时少了数据。

    再说时间问题前,简单了解下UTC:

    UTC(Universal Time Coordinated) 叫做世界统一时间,中国大陆和 UTC 的时差是 + 8 ,也就是 UTC+8。
    UTC时区参考文档

    查看官方文档后得到的结论:

    ELK Stack集群各服务对时间处理的介绍:
    logstash :根据所在机器的时区并对date类型数据进行处理,整理成UTC时间
    elastic :所有date类型数据都存储为GMT(毫秒级)
    kibana :根据kibana配置的时区,从elastic取出的timestamp时间转换为相应时区的时间。

    问题原因:

    logstash处理后以UTC时间存储进elastic,kibana取出来后,在恢复成相应时区的时间。因为我机器都是CST的时间,所以使用kibana搜索没有问题,但是curl命令不会对所取出来的时间进行时区转换,所以就少了8小时数据。


    解决方法:

    一:

    logstash 过滤字段信息时,删除或分开匹配时间和时区信息,timestamp只匹配具体时间,timezone则匹配+0800这样的时区信息,并同时定义timezone为UTC,这样从根本上就得到原始的时间。

    UTC时间的示例:

    $ bin/logstash -f text.conf 
    [26/Mar/2019:00:00:08 +0800]      #这里以nginx日志中的时间为例
    {
         "timestamp" => "26/Mar/2019:00:00:08",
           "message" => "[26/Mar/2019:00:00:08 +0800]",
        "@timestamp" => 2019-03-26T00:00:08.000Z,        #@timestamp的时间和输入的时间一致
          "@version" => "1",
          "timezone" => "+0800",
              "host" => "node2007"
    }
    
    $ cat text.conf
    input {
      stdin {}
    }
    filter {
      grok {
        match => {
          "message" => "[%{NOTSPACE:timestamp} %{INT:timezone}]"
        }
      }
      date {
        match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss" ]
        timezone => "UTC"      #无法从timestamp中提取时区。设置时区为UTC时间,忽略系统时区,如果date插件中的match匹配到了时区,则此处的时区不生效。所以在grok插件中将timezone和timestamp分隔开
      }
    }
    output {
        stdout{
            codec => rubydebug
        }
    }
    
    

    正常时间处理:

    $ bin/logstash -f text.conf 
    [26/Mar/2019:00:00:08 +0800]     
    {
          "@version" => "1",
        "@timestamp" => 2019-03-25T16:00:08.000Z,       #转换成UTC时间,减少8小时,
           "message" => "[26/Mar/2019:00:00:08 +0800]",
              "host" => "node2007",
         "timestamp" => "26/Mar/2019:00:00:08 +0800"
    }
    
    $ cat text.conf
    input {
      stdin {}
    }
    filter {
      grok {
        match => {
          "message" => "[%{HTTPDATE:timestamp}]"
        }
      }
      date {
        match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
        timezone => "UTC"     
      }
    }
    output {
        stdout{
            codec => rubydebug
        }
    }
    

    系统日志中不带有时区信息,则可以直接在配置文件中指定timezone => "UTC"即可。无需要做匹配工作。


    二:

    匹配到时区时间没有关系,可以在过滤时,在把时间补回来。

    ...
    	date {
    		match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
    		target => "time"
    	}
    	ruby { 
    	  code => "event.set('timestamp', event.get('time').time.localtime + 8*60*60)"   #处理时将logstash自动减少的时间在给加回来
    	}
    	ruby {
    		code => "event.set('@timestamp',event.get('timestamp'))"
    	}
    ...
    

    以上代码经过我测试,可以正常使用。这里使用ruby插件,我不懂,time -> timestamp -> @timestamp需要经由两个变量才能最后赋值给@timestamp,为什么不能直接使用@timestamp处理并赋值,如果有懂得的人,还请留言告知。


    对时间进行处理后,我们可以使用curl命令随意进行查询啦,但是使用kibana时,还需要设置一下默认的时区: Management -> kibana(高级设置) -> Timezone for date formatting 并选择UTC时间展示。 ![](https://img2018.cnblogs.com/blog/1202606/201903/1202606-20190328154358262-1829927564.png)

    总结:

    ELK Stack一整套组合拳的时区特性特别好用,但是在国内还是统一时区吧。统一时区还是再数据存储前做调整,否则后期查询会流泪的。

  • 相关阅读:
    2015.2.27 UltraEdit中显示XML结构
    2015.1.31 DataGridView自动滚动到某行
    2015.1.15 利用函数实现将一行记录拆分成多行记录 (多年想要的效果)
    2015.1.15 利用Oracle函数返回表结果 重大技术进步!
    2015.1.15 利用Oracle函数插入表结构 Bulk collect into 不用循环,简洁高效
    2015.1.8 Left join 左连接
    2015.1.10 解决DataGridView SelectionChanged事件自动触发问题
    delphi 遍历窗口
    delphi 访问 protected 属性 哈哈
    clientdataset 读取excel 如果excel 文件不存在的时候 相应的gird 会不显示数据, 鼠标掠过 gird 格子 才会显示数据。 这是一个bug 哈哈
  • 原文地址:https://www.cnblogs.com/dance-walter/p/10615480.html
Copyright © 2011-2022 走看看