ES中:

日期时间字段在json中以字符串形式存在,但是在es中有专门的date类型来表示日期时间,并且,es中是以0时区来存储date类型的值。

这就引出了一个问题:
如果原始内容中的日期时间字段有时区信息,那么es会将其转换为0时区并转换为时间戳以long类型存储在es中;
如果原始内容日期时间字段没有时区信息的话,例如2018-10-30 11:10:45,那么es会将其视为0时区的时间,即实际在es中存储2018-10-30 11:10:45 +0000的时刻。

kibana中

kibana从es中获取到date类型的字段后,会通过js获取本机/本地时区,并将时间字段从es的0时区转换为本地时区之后展示出来。

所以遇到的问题如下:

比如日志中日期时间值为2018-10-30 11:10:45,然后自定义mapping为

                "accountTime": {
                    "type": "date",
                    "format" : "yyyy-MM-dd HH:mm:ss"
                },

那么我们日志中东8区的时间2018-10-30 11:10:45在es中会存储2018-10-30 11:10:45 +0000的时间戳,然后kibana读取的时候再做一次转换,在kibana中该时刻就变成了2018-10-30 19:10:45 +0800,比正常时间晚了8小时

解决方法

关于时区问题一个最优解是原始内容里的日期时间字段就带上时区信息
我们通过logstash的filter模块来对原始数据做修改,为其增加时区信息:

说明:type是input插件中为不同日志文件指定的类型,方便在output插件中自动生成索引前缀
三种日志文件中有两种日期时间字段,名为accountTime和time,格式均为2018-10-30 19:10:45
filter {
    if [type] == "few" {
        mutate {
            update => { "accountTime" => "%{accountTime} +0800" }
        }
    }
    else if [type] == "key" or [type] == "bar" {
        mutate {
            update => { "time" => "%{time} +0800" }
        }
    }
}

然后修改mappings

                "accountTime": {
                    "type": "date",
                    "format" : "yyyy-MM-dd HH:mm:ss Z"
                },
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。