logstash @timestamp 日期及时区问题通用的解决方案
logstash @timestamp 日期及时区问题通用的解决方案
elk生态不少组件都会碰到时区问题,logstash也不例外
改系统时区都解决不了
官方的[Date filter plugin | Logstash Reference 7.16] | Elastic
虽然在时间转换时有zone设置时区设置的部分,但个人测试使用并不生效
使用插件没办法,那就用ruby插件改
例如时间字段为pdate,同时以这个字段做为@timestamp
在数值转换时自已pdate以用+8*60*60
更改时区没有问题,使用时以pdate查询
但是有个问题是@timestamp和pdate不一致
而logstash相关生态,例如写es,通过时间按 月/天/小时,划分索引时是以@timestamp计算的,会出现8小时的偏差
其实如果是大范围的日志类查询(实际查询条件使用的是pdate),@timestamp 导致index 数据滚动后延的偏差可以忽略
但毕竟不完美,线上当然要尽可能保持没有偏差
以 event.set('@timestamp',pdate) 启动logstash却报异常
Ruby exception occurred: wrong argument type Timestamp (expected LogStash::Timestamp)
大意是pdate和期望的Timestamp类型不匹配,这种错在java里也挺常见了
以为是哪里小细节搞错了,多试几次,还是解决不了
那就是说,pdate和@timestamp
的类型确实不一致
要把pdate转为LogStash::Timestamp
查logstash代码,找找LogStash::Timestamp
这个类相关信息
logstash/event_spec.rb at 7.10 · elastic/logstash (github.com)
logstash/JrubyTimestampExtLibrary.java at 7.10 · elastic/logstash (github.com)
it "should set timestamp" do
e = LogStash::Event.new
now = Time.now
e.set("@timestamp", LogStash::Timestamp.at(now.to_i))
expect(e.timestamp.to_i).to eq(now.to_i)
expect(e.get("@timestamp").to_i).to eq(now.to_i)
end
果然是类型不对,标准的Time和LogStash::Timestamp 需要一道转换
因此变更为如下结果,这样可能省掉pdate这一列
pdate 使用date filter string转为LogStash::Timestamp,由于timezone 不生效,通过ruby计算重新set
这种方法不是最优的,但应该是最通用的
date {
match => [ "pdate", "ISO8601" ]
timezone => "Asia/Shanghai"
target => "@timestamp"
}
ruby {
code => "
event.set('@timestamp', LogStash::Timestamp.at(event.get('@timestamp').time.localtime + 8*60*60))
"
}