Kibana連接ES查詢數據的時候,會有時差8小時的問題。先來描述一下問題的具體情況,我們先來看看Logstash默認寫入到ES的索引數據。timestamp是我們App上報日志的時間戳字段,這個字段是客戶端寫入日志的時間。@timestamp是使用Logstash寫入ES的時候默認自帶的時間戳(即Logstash生成ES索引的時間戳)。這里我們的這條日志是2016-10-08由App記錄的,由Logstash收集到ES服務器的時間是2016-12-05。但是我們發現@timestamp並不是我們系統的當前時間,而是比我們當前的系統時間小了8小時,這就是我們想要解決的8小時時差問題。
原因是Logstash中默認插入的@timestamp時間字段是按照UTC 00:00標准時區的時間轉換成long型的時間戳保存在ES中,而我們系統的時間是中國時區UTC +08:00,由ES查詢出來的long型的時間戳再按照UTC +08:00轉換成時間就正好相差了8小時。因為@timestamp的long型字段在ES中是不可取回的,所以我們在ES的返回值中是看不到這個long型字段的,只能看到@timestamp根據我們的時區轉換后的結果”2016-12-05T11:30:40.911Z”,這個結果正好和我們的系統時間相差了8小時。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
{
"_index": "api_logs_index_1",
"_type": "command",
"_id": "AVjOwAt_jL-eD07Ygku1",
"_version": 1,
"_score": 1,
"_source": {
"logs": {
"timestamp": "1475912701768",
"rpid": "65351516503932930",
"name": "rp.hb.ad.click_ad",
"bid": 0,
"uid": 0,
"did": 0,
"duid": 0,
"hb_uid": 0,
"ua": "",
"device_id": "",
"server_timestamp": 1475912715001
},
"level": "info",
"message": "logs",
"timestamp": "2016-10-08T07:45:15.001Z",
"@version": "1",
"@timestamp": "2016-12-05T11:30:40.911Z",
"path": "/home/yunyu/Downloads/track.log",
"host": "hadoop1",
"type": "command"
}
}
|
上面簡單的描述了一下問題。我們需要解決下面兩個問題:
- 如何讓Kibana查詢和統計使用的是App寫入日志的時間,而不是Logstash寫入ES的時間(因為Logstash寫入ES時間上會有延遲)
- 解決時差相差8小時問題
一般我們App上報日志都會帶有一個timestamp時間戳字段,這個字段是客戶端寫入日志的時間。當Logstash收集App上報日志的時候,會將timestamp字段保存到ES中,Kibana通過該字段當做統計的字段進行各種按日期統計的查詢。
這里Kibana要求所有ES的索引必須要有一個時間字段作為統計查詢的日期字段使用,如果沒有ES的索引沒有時間或者日期字段,是無法在Kibana中創建索引的。所以默認Kibana也會給一個默認的時間字段@timestamp,這樣當我們在Kibana創建api_logs_index索引的時候,就會出現有兩個時間字段,一個是timestamp,一個是@timestamp。
在Kibana創建索引時,設置索引使用@timestamp字段,但是需要在Logstash中配置@timestamp的值從timestamp取出來的。Logstash中可以指定@timestamp字段的值是從App上報日志的timestamp字段來的。
1
2
3
4
|
date {
match => ["timestamp", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"]
target => "@timestamp"
}
|
下面用我們這條日志舉例,下面的表格是系統時間和UTC時間戳根據北京時區的轉換對照表。這里的系統時間轉換程UTC時間戳是帶有北京時區的。
系統時間 | UTC時間戳 | ES返回(顯示)的時間 | ES存儲的時間(long) |
---|---|---|---|
2016/10/18 15:45:15.001Z | 1475912715001 | timestamp : 1475912715001 | |
2016/10/18 7:45:15.001Z | 1475883915001 | timestamp : 2016/10/18 7:45:15.001Z | @timestamp : 1475883915001 |
2016/10/17 23:45:15.001Z | @timestamp : 2016/10/17 23:45:15.001Z |
Logstash將timestamp的時間2016/10/18 7:45:15.001Z按照默認的標准時區UTC 00:00將timestamp轉換成long類型1475912715001存儲到ES,而對於@timestamp字段的值,是將timestamp的時間2016/10/18 7:45:15.001Z按照北京時區UTC +08:00將timestamp轉換成long類型1475883915001並且賦值給@timestamp並且存儲到ES。(為什么要加上北京時區UTC +08:00的原因不清楚,也嘗試過不帶有Z時區設置的時間格式,轉換成的時間戳結果一樣)
1
2
3
4
|
date {
match => ["timestamp", "yyyy-MM-dd HH:mm:ss"]
target => "@timestamp"
}
|
ES存儲的時間long型到ES返回(顯示)時間是按照UTC 00:00標准時間轉換的。下面是取回的結果。
- ES將timestamp的long類型1475912715001按照UTC 00:00標准時間轉換回時間2016/10/18 7:45:15.001Z
- ES將@timestamp的long類型1475883915001按照UTC 00:00標准時間轉換回時間2016-10-07T23:45:15.001Z
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
{
"_index": "api_logs_index_1",
"_type": "command",
"_id": "AVjOwAt_jL-eD07Ygku1",
"_version": 1,
"_score": 1,
"_source": {
"logs": {
"timestamp": "1475912701768",
"rpid": "65351516503932930",
"name": "rp.hb.ad.click_ad",
"bid": 0,
"uid": 0,
"did": 0,
"duid": 0,
"hb_uid": 0,
"ua": "",
"device_id": "",
"server_timestamp": 1475912715001
},
"level": "info",
"message": "logs",
"timestamp": "2016-10-08T07:45:15.001Z",
"@version": "1",
"@timestamp": "2016-10-07T23:45:15.001Z",
"path": "/home/yunyu/Downloads/track.log",
"host": "hadoop1",
"type": "command"
}
}
|
這里可以看到Kibana的查詢Request,下面是我選擇的時間區間條件
- 2016/10/8 7:30:0:按照北京時區UTC +08:00轉換為1475883000000
- 2016/10/8 8:0:0:按照北京時區UTC +08:00轉換為1475884800000
Kibana Request
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
{
"size": 500,
"sort": [
{
"@timestamp": {
"order": "desc",
"unmapped_type": "boolean"
}
}
],
"query": {
"filtered": {
"query": {
"query_string": {
"analyze_wildcard": true,
"query": "*"
}
},
"filter": {
"bool": {
"must": [
{
"range": {
"@timestamp": {
"gte": 1475883000000,
"lte": 1475884800000,
"format": "epoch_millis"
}
}
}
],
"must_not": []
}
}
}
},
"highlight": {
"pre_tags": [
"@kibana-highlighted-field@"
],
"post_tags": [
"@/kibana-highlighted-field@"
],
"fields": {
"*": {}
},
"require_field_match": false,
"fragment_size": 2147483647
},
"aggs": {
"2": {
"date_histogram": {
"field": "@timestamp",
"interval": "30s",
"time_zone": "Asia/Shanghai",
"min_doc_count": 0,
"extended_bounds": {
"min": 1475883000000,
"max": 1475884800000
}
}
}
},
"fields": [
"*",
"_source"
],
"script_fields": {},
"fielddata_fields": [
"timestamp",
"@timestamp"
]
}
|
上面的Request可以看出來我們Kibana Request是將查詢時間區間的條件先按照Browser的時區(北京時區UTC +08:00)轉換成long型時間戳,然后當成條件查詢的@timestamp字段。
這里的fields就是ES存儲的long類型數值。
- timestamp 1475912715001:按照標准時區UTC +00:00轉換為2016/10/8 7:45:15
- @timestamp 1475883915001:按照標准時區UTC +00:00轉換為2016/10/7 23:45:15
1
2
3
4
5
6
7
8
|
"fields": {
"timestamp": [
1475912715001
],
"@timestamp": [
1475883915001
]
}
|
Kibana Response
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
|
{
"took": 7,
"hits": {
"hits": [
{
"_index": "api_logs_index_1",
"_type": "command",
"_id": "AVjPhBGGUk8QUkLwTRVu",
"_score": null,
"_source": {
"logs": {
"timestamp": "1475912701768",
"rpid": "65351516503932930",
"name": "rp.hb.ad.click_ad",
"bid": 0,
"uid": 0,
"did": 0,
"duid": 0,
"hb_uid": 0,
"ua": "",
"device_id": "",
"server_timestamp": 1475912715001
},
"level": "info",
"message": "logs",
"timestamp": "2016-10-08T07:45:15.001Z",
"@version": "1",
"@timestamp": "2016-10-07T23:45:15.001Z",
"path": "/home/yunyu/Downloads/track.log",
"host": "hadoop1",
"type": "command"
},
"fields": {
"timestamp": [
1475912715001
],
"@timestamp": [
1475883915001
]
},
"sort": [
1475883915001
]
}
],
"total": 1,
"max_score": 0
},
"aggregations": {
"2": {
"buckets": [
{
"key_as_string": "2016-10-08T07:30:00.000+08:00",
"key": 1475883000000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:30:30.000+08:00",
"key": 1475883030000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:31:00.000+08:00",
"key": 1475883060000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:31:30.000+08:00",
"key": 1475883090000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:32:00.000+08:00",
"key": 1475883120000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:32:30.000+08:00",
"key": 1475883150000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:33:00.000+08:00",
"key": 1475883180000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:33:30.000+08:00",
"key": 1475883210000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:34:00.000+08:00",
"key": 1475883240000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:34:30.000+08:00",
"key": 1475883270000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:35:00.000+08:00",
"key": 1475883300000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:35:30.000+08:00",
"key": 1475883330000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:36:00.000+08:00",
"key": 1475883360000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:36:30.000+08:00",
"key": 1475883390000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:37:00.000+08:00",
"key": 1475883420000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:37:30.000+08:00",
"key": 1475883450000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:38:00.000+08:00",
"key": 1475883480000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:38:30.000+08:00",
"key": 1475883510000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:39:00.000+08:00",
"key": 1475883540000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:39:30.000+08:00",
"key": 1475883570000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:40:00.000+08:00",
"key": 1475883600000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:40:30.000+08:00",
"key": 1475883630000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:41:00.000+08:00",
"key": 1475883660000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:41:30.000+08:00",
"key": 1475883690000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:42:00.000+08:00",
"key": 1475883720000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:42:30.000+08:00",
"key": 1475883750000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:43:00.000+08:00",
"key": 1475883780000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:43:30.000+08:00",
"key": 1475883810000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:44:00.000+08:00",
"key": 1475883840000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:44:30.000+08:00",
"key": 1475883870000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:45:00.000+08:00",
"key": 1475883900000,
"doc_count": 1
},
{
"key_as_string": "2016-10-08T07:45:30.000+08:00",
"key": 1475883930000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:46:00.000+08:00",
"key": 1475883960000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:46:30.000+08:00",
"key": 1475883990000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:47:00.000+08:00",
"key": 1475884020000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:47:30.000+08:00",
"key": 1475884050000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:48:00.000+08:00",
"key": 1475884080000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:48:30.000+08:00",
"key": 1475884110000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:49:00.000+08:00",
"key": 1475884140000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:49:30.000+08:00",
"key": 1475884170000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:50:00.000+08:00",
"key": 1475884200000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:50:30.000+08:00",
"key": 1475884230000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:51:00.000+08:00",
"key": 1475884260000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:51:30.000+08:00",
"key": 1475884290000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:52:00.000+08:00",
"key": 1475884320000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:52:30.000+08:00",
"key": 1475884350000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:53:00.000+08:00",
"key": 1475884380000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:53:30.000+08:00",
"key": 1475884410000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:54:00.000+08:00",
"key": 1475884440000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:54:30.000+08:00",
"key": 1475884470000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:55:00.000+08:00",
"key": 1475884500000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:55:30.000+08:00",
"key": 1475884530000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:56:00.000+08:00",
"key": 1475884560000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:56:30.000+08:00",
"key": 1475884590000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:57:00.000+08:00",
"key": 1475884620000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:57:30.000+08:00",
"key": 1475884650000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:58:00.000+08:00",
"key": 1475884680000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:58:30.000+08:00",
"key": 1475884710000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:59:00.000+08:00",
"key": 1475884740000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T07:59:30.000+08:00",
"key": 1475884770000,
"doc_count": 0
},
{
"key_as_string": "2016-10-08T08:00:00.000+08:00",
"key": 1475884800000,
"doc_count": 0
}
]
}
}
}
|
ES返回的結果時間是按照標准時區UTC +00:00轉換的。這里Kibana還會根據創建索引所選擇的時間戳,再將@timestamp的結果轉換成Browser默認的時區(即:UTC +08:00)顯示出來,也就是在ES返回的@timestamp時間上再加8小時。
如果timestamp字段沒有帶有時區設置,我們可以在Logstash中指定locale和timezone屬性來設置timestamp的字段的時區,這樣就知道timestamp的時間應該按照指定的timezone時區解析成long型時間戳,這樣my_timestamp字段在ES中是一個使用+08:00中國時區的long類型時間戳,方便使用ES API直接查詢timestamp字段,因為一般人都使用+08:00中國時區將時間轉換為long類型的時間戳。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
date {
match => ["timestamp", "yyyy-MM-dd HH:mm:ss"]
target => "my_timestamp"
locale => "en"
timezone => "+08:00"
}
date {
# 如果日志中的timestamp時間戳帶有時區,而且是UTC標准時區,不是中國時區,我們可以使用指定timezone來轉換成long類型的@timestamp
match => ["timestamp", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"]
target => "@timestamp"
locale => "en"
timezone => "+00:00"
}
|
Logstash創建索引所使用的YYYY-MM-DD也是使用的@timestamp字段的時間
參考文章: