Logstash 时区问题导至数据被写进错误的 ES 索引的解决方法

Python09

Logstash 时区问题导至数据被写进错误的 ES 索引的解决方法,第1张

在上篇: .NET 的 ELK 监控方案 里, 我们将 Logstash 的配置节点 output 这样写:

logstash 会自动从数据中找到 i 这个字段, 并结合 @timestamp 来指定这条数据到要写到哪个 index 下面去.

如果配置中没有指定 @timestamp 从哪里取值, logstash 会默认把第一次读到取这条数据时间做为 @timestamp .

但是请注意, logstash 使用的是 UTC 时间. 这个地方将会引发标题所描述的问题.

比如, 当前时间是 2018-08-17T00:29:59.618+08:00 , 转换为 UTC 时间就成了 2018-08-16T16:29:59.618Z

Logstash 把这个 UTC 时间用来确定数据该存到哪个 Index 里面, 这就导至了 本来是 8月17日的数据, 却被写到 8月16 日的索引下面去了.

如果只是用 Kibana 做为可视化工具, 问题不大.

但是我们每天大概能收集到 100G的日志, 搜索条件多样化 , 在加上对语法不熟悉, Kibana 已经不能给我们提供便捷的使用体验了.

但是对自制的查询工具而言, 又不能跨 index 查询(有重复的日志), 所以这个问题被无限放大了.

要解决这个问题, 又不能作大规模的改动, 最好的办法就是看有什么方法把 @timestamp 用中国时间来表示.

从百度上找了两篇文章, 说用 date filter 来修改时区, 但是写到 es 里的 @timestamp 依然是 UTC 时间, 估计也是行不通, 就没有继续在上面尝试.

和之前的配置比起来, 这个新配置多了一个节点: filter

用 ruby 脚本把事件的 timestamp 的本地时间赋值给 index_day (这个 index_day 并不存在于原始的日志数据中),

然后在 output 节点的 index 中使用这个 index_day. 这样一来每天8点之前的日志就会写到正确的 index 中了.

不过, 每天结束的那几分钟产生的日志有可能会被写到下一天的索引里去..

TimeZone 配置参见 Date Filter , logstash 将日志北京时间保存成utc

Filter Ruby 参见, Logstash Filter Ruby , 不要问我, 我也不会

Output elashtic Index 配置参见 Elasticsearch output plugin

(这部分内容完全是选学的。它需要有一定程度的数学知识才可以,如果你对此没兴趣的话可以直接去下一章节,对于Ruby学习没任何影响。但是可以快速浏览一下这一章节中的 随机数 部分对以后的学习肯定会派上用场的)

关于数字方面使用的方法在数量上与字符串方法几乎一样多(同样的我脑子里也不记得所有的方法)。接下来我们将看到剩下的算术方法、随机数计算器和数学对象,会用到三角函数和超函数方法。 trigonometric and transcendental methods

其余的算术方法是 ** (乘方/取幂)和 % (模数/取余)。如果你想在Ruby中表示5的平方,可以写成5 ** 2。你也可以在乘方中用浮点数,比如你想对5开根号,可以写成5 ** 0.5。取余方法可以得到被一个数除以后的余数:比如我用7被3除,会得到2,余数是1。让我们看看在程序中是如何运行的:

从最后一行我们能够知道一年(非闰年)中有许多个星期外加1天。如果你的生日是今年的星期二,那么下一年生日将会是在周三。在取余中也可以用浮点数。基本上这些方法都会以它们定义的方式运行,稍后我会让你们熟悉这些方法。

在学习随机数之前最后需要提到的方法是 abs 绝对值。它会得到一个数的绝对数值:

Ruby天生就自带有一个相当不错的随机数生成器。得到一个随机数字的方法是 rand 。如果你直接调用 rand ,你会得到一个大于等于0.0至小于1.0之间的浮点数;如果你给 rand 一个整数(以5为例),你将会得到一个大于等于0至小于5的整数(也就是5个可能的数字,从0到4)。

下面让我们在例子中学习 rand :

有时你可能想在程序运行多次的情况下能在同一个位置返回相同的随机数(比如我有一次在一个电脑游戏中用随机数创建一个随机生成的副本,我会喜欢上某个副本,就像再玩一次这个副本或这把这个副本发给一个朋友)这种情况下你需要设置一个随机数种子,这里可以用 srand ,像下面这样:

最后让我们来了解一下数学中的对象。我们可以直接用下面的例子:

从上面可以知道:数学里面包含着你期望一个科学计算器拥有的所有东西。鉴于此,浮点数将会是解决问题的正确答案。

所以接下来我们来学习 流程控制 Flow Control 。

查询核心模块Kernel API可知:

如果是Float类型则通过Kernel.Float(字符串)判断,这里不能转为浮点数则会抛出异常。你只需再捕获一下输出自己的信息就行。