[关闭]
@StrGlee 2018-06-18T12:43:07.000000Z 字数 4320 阅读 10334

logstash 时间戳时区问题

logstash 时区 时间戳 timestamp


logstash 时区和时间问题让很多人头疼,今天就说说它吧。

Date Filter 插件

日期过滤器用于分析字段中的日期,然后使用该日期或时间戳作为事件的logstash时间戳。

配置项

该插件支持以下配置选项

Setting Input type Required Default
locale string No No
match array No []
tag_on_failure array No ["_dateparsefailure"]
target string No "@timestamp"
timezone string No No

locate

使用IETF-BCP47或POSIX语言标记指定用于日期分析的语言环境。en,en-US用于BCP47或者en_US用于POSIX。
当解析月份名称(MMM模式)和星期几名称(EEE模式)时,如果默认语言环境不是english,需要设置

  1. date {
  2. locale => "en"
  3. ...
  4. }

match

对于非格式化语法,您需要在值的周围放置单引号字符。例如,如果你解析ISO8601时间,“2018-06-01T01:12:23”,你需要这样写:

  1. date {
  2. match => ["log_timestamp", "yyyy-MM-dd'T'HH:mm:ss"]
  3. }

如果你需要匹配多种时间格式,如 "2018-06-01T01:23:05Z", "1529122935988", "1529122935",你需要这样写:

  1. date {
  2. match => ["log_timestamp", "ISO8601", "UNIX", "UNIX_MS"]
  3. }

date插件支持五种时间格式

Symbol Meaning Presentation Examples
G era text AD
C century of era (>=0) number 20
Y year of era (>=0) year 1996
x weekyear year 1996
w week of weekyear number 27
e day of week number 2
E day of week text Tuesday; Tue
y year year 1996
D day of year number 189
M month of year month July; Jul; 07
d day of month number 10
a halfday of day text PM
K hour of halfday (0~11) number 0
h clockhour of halfday (1~12) number 12
H hour of day (0~23) number 0
k clockhour of day (1~24) number 24
m minute of hour number 30
s second of minute number 55
S fraction of second number 978
z time zone text Pacific Standard Time; PST
Z time zone offset/id zone -0800; -08:00; America/Los_Angeles
' escape for text delimiter
'' single quote literal '

举例

example match
2018-06-01T01:23:05+08:00 yyyy-MM-dd'T'HH:mm:ss+08:00 或 ISO8601
2018-06-01T01:23:05Z yyyy-MM-dd'T'HH:mm:ssZ 或 ISO8601
Jun 07 2018 01:23:05 MMM dd yyyy HH:mm:ss (注: locale => "en")
Jun 7 2018 01:23:05 MMM d yyyy HH:mm:ss (注: locale => "en")
1529122935988 UNIX_MS
1529122935 UNIX

tag_on_failure

如果匹配失败,将值附加到tag字段

target

将匹配的时间戳存储到给定的目标字段中。如果未提供,则默认更新事件的@timestamp字段

timezone

当需要配置的date里面没有时区信息,而且不是UTC时间,需要设置timezone参数。
比如匹配北京时间 "2018-06-18 11:10:00",则需要设置

  1. date {
  2. match => ["logdate", "yyyy-MM-dd HH:mm:ss"]
  3. timezone => "Asia/Chongqing"
  4. }
Standard Offset Canonical ID Aliases
+08:00 Asia/Chongqing Asia/Chungking
+08:00 Asia/Hong_Kong Hongkong
+08:00 Asia/Shanghai PRC

附: timezone列表

logstash @timestamp自定义

在ELK组合中我们在outputs/elasticsearch中常用的%{+YYYY.MM.dd}来创建索引,而这种写法是必须要读@timestamp这个字段的。默认情况下@timestamp字段显示的是当前时间,但我们可能需要记录的是日志中的字符串类型的时间,所以我们需要把日志中字符串类型的时间覆盖掉@timestamp中的当前时间。

  1. input {
  2. stdin{}
  3. }
  4. filter {
  5. grok {
  6. match => ["message", "%{TIMESTAMP_ISO8601:logdate}"]
  7. }
  8. date {
  9. match => ["logdate", "yyyy-MM-dd HH:mm:ss.SSS"]
  10. target => "@timestamp"
  11. }
  12. mutate {
  13. remove => ["logdate"]
  14. }
  15. }
  16. output{
  17. stdout{
  18. codec=>rubydebug{}
  19. }
  20. }

附: logstash自带的正则 logstash-patterns

@timestamp时间少8小时

处理逻辑如下

5.0以下版本

  1. input { stdin {} }
  2. output { stdout { codec => rubydebug } }
  3. filter {
  4. date {
  5. match => ["message","UNIX_MS"] # message在实际应用中修改为自己的字段
  6. target => "@timestamp"
  7. }
  8. ruby {
  9. code => "event['timestamp'] = LogStash::Timestamp.new(event['@timestamp']+ 8*60*60)"
  10. }
  11. ruby {
  12. code => "event['@timestamp']= event['timestamp']"
  13. }
  14. mutate {
  15. remove_field => ["timestamp"]
  16. }
  17. }

5.x以上版本

  1. input { stdin {} }
  2. output { stdout { codec => rubydebug } }
  3. filter {
  4. date {
  5. match => ["message","UNIX_MS"]
  6. target => "@timestamp"
  7. }
  8. ruby {
  9. code => "event.set('timestamp', event.get('@timestamp').time.localtime + 8*60*60)"
  10. }
  11. ruby {
  12. code => "event.set('@timestamp',event.get('timestamp'))"
  13. }
  14. mutate {
  15. remove_field => ["timestamp"]
  16. }
  17. }

index索引名称少8小时

  1. # 1. 增加一个字段,计算timestamp+8小时
  2. ruby {
  3. code => "event.set('index_date', event.get('@timestamp').time.localtime + 8*60*60)"
  4. }
  5. # 2. 用mutate插件先转换为string类型,gsub只处理string类型的数据,在用正则匹配,最终得到想要的日期
  6. mutate {
  7. convert => ["index_date", "string"]
  8. gsub => ["index_date", "T([\S\s]*?)Z", ""]
  9. gsub => ["index_date", "-", "."]
  10. }
  11. # 3.output配置
  12. elasticsearch {
  13. hosts => ["localhost:9200"]
  14. index => "myindex_%{index_date}"
  15. }

时区问题的解释

很多中国用户经常提一个问题:为什么 @timestamp 比我们早了 8 个小时?怎么修改成北京时间?

其实,Elasticsearch 内部,对时间类型字段,是统一采用 UTC 时间,存成 long 长整形数据的!对日志统一采用 UTC 时间存储,是国际安全/运维界的一个通识——欧美公司的服务器普遍广泛分布在多个时区里——不像中国,地域横跨五个时区却只用北京时间。

对于页面查看,ELK 的解决方案是在 Kibana 上,读取浏览器的当前时区,然后在页面上转换时间内容的显示。

所以,建议大家接受这种设定。否则,即便你用 .getLocalTime 修改,也还要面临在 Kibana 上反过去修改,以及 Elasticsearch 原有的 ["now-1h" TO "now"] 这种方便的搜索语句无法正常使用的尴尬。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注