Logstash进阶指南

1. 万能的ruby filter

“Logstash 是开源的服务器端数据处理管道,能够同时 从多个来源采集数据、转换数据,然后将数据发送到您最喜欢的存储库中。”这是elastic官方对Logstash的定义。Logstash提供了大量的组件,使得我们可以用组件搭积木的形式,通过配置文件,轻松完成常见的数据基本处理工作。今天要讨论的ruby filter就是其中的数据处理组件。不过,既然是讨论进阶话题,我们假设你已对Logstash有一定了解。

 

1. 为什么要讨论ruby filter

 

工作中我们常常会发现,凡事总有例外。说好的utf8字符串总会混入gbk,说好的“20180618”的日期格式总有人写成“06-18-2018”,这一点相信搞数据治理的人都深有体会。总之,总会遇到各种奇形怪状的问题,这时ruby filter的灵活性就体现出来。

 

Logstash的各种插件功能非常丰富强大,并且仍在不断扩展。但计划赶不上变化,面向通用性设计的Logstash不可能涵盖我们所有的特殊需求。举个例子,Logstash的条件判断是不支持算术运算的,也就是说“if [x] > [y]+1”这样简单的表达式都不能支持。Logstash的不少插件也存在bug,比如xml filter。要满足自己的定制化需求,依然要用到ruby filter。

 

既然如此,我们为什么不用Python?写一个繁琐的配置文件,和写一个Python脚本的工作量也差不到哪去。或者为什么不自己写一个插件?我的经验是:

  a. 不要重复造*,同时要保持代码的统一性,所以Logstash现有的组件为何不用?

  b. Logstash本身提供了多线程、日志、错误控制、内存控制、监控等保证稳定高效运行的特性,这些简单一个python脚本不能提供的。

  c. 自己写一个插件,门槛较高,而且代码量较大。好处是写出来之后大家都可以复用。不过自己写一个插件能实现的,其实ruby filter基本也能实现……

所以ruby filter其实是能最小化我们工作量的一个方案。

 

2. 打造ruby filter开发环境

 

工欲善其事必先利其器,这一部分我们可以不做。但做了一方面可以用的更爽,另一方面也可以熟悉一下Logstash的Ruby环境。我们假设你的Logstash是用rpm或deb安装,目录位于/usr/share/logstash。这里以6.2.0版本为例。

 

2.1 熟悉jruby环境

 

Logstash是用Ruby写的,而Ruby是脚本语言,因此需要解释器,这里是jruby,即用Java写的Ruby解释器。所以你会发现以下所有Ruby命令之前都带上了“j”。

Logstash的Ruby环境与操作系统本身的Ruby环境(如果有)是隔离的,位于/usr/share/logstash/vendor/jruby。

 

作为脚本语言,Ruby也提供了自己的REPL(Read Eval Print Loop)工具。就像python、node一样,可以非常方便地边试边写。为了不用每次都切换目录,我们建个软连接就可以直接用了:

 

Logstash进阶指南

 

2.2  什么?我还要学一门ruby?

 

是的,想想ElasticStack是多么坑爹:Elasticsearch是Java写的,Kibana是Javascript写的,Logstash是Ruby写的,Beats是Go写的……从入门到放弃。

但实际上也没想象中那么可怕,因为其实我们只用到了Ruby最基本的语法:字符串、数值、时间、正则、数组、字典、条件、循环,这些学完了差不多就OK了!也就学半天熟悉半天足矣。

 

2.3   配置使用阿里云镜像源

 

和Python的pip类似,Ruby也有自己的包安装命令gem。不得不说阿里大法好,一个镜像站点把yum、apt、pypi、maven、rubygems……基本你能想到的全都提供了。对于企业的内网环境,开放一个mirrors.aliyun.com一次性解决所有问题。这里我们也介绍一下配置方法,然后安装两个包试试。

 

Logstash进阶指南

 

3. Logstash event API

 

Logstash中,每条事件被称为一个event,使用ruby filter对事件进行处理必须要调用event API。然而蛋疼的是,Elastic的官方文档 https://www.elastic.co/guide/en/logstash/current/event-api.html  竟然只给出了get和set两个方法的介绍。这是在逗我么?不过由于这两个方法是最常用的,我们先举个例子:将输入中的字母转为小写字母。

 

Logstash进阶指南

 

除此之外,其实还有丰富的API,看源码 https://github.com/elastic/logstash/blob/master/logstash-core/src/main/java/org/logstash/ext/JrubyEventExtLibrary.java  即可,很清楚。除get和set外,还包括:

 - 删除事件:cancel
 - 取消删除事件:uncancel
 - 是否删除:cancelled?
 - 是否包含字段:include?
 - 删除字段:remove
 - 事件转字符串:to_s
 - 事件转hash字典(不含metadata字段):to_hash
 - 事件转hash字典(含metadata字段):to_hash_with_metadata
 - 事件转json字符串:to_json
 - 增加tag:tag
 - 取事件时间戳:timestamp

 

这里举一个稍微复杂的例子:遍历所有字段,删除值大于1的字段。注意,Logstash的事件中以“@”开头的字段是系统自动添加的,这些字段不要修改。

Logstash进阶指南

 

4.  ruby filter实战应用

 

4.1  xml字段解析器

 

Logstash自带的xml filter,要求xml字段只能有一个根节点,也就是形如

“<lon>114</lon><lat>22</lat>”的字段解析会报错,但“<gps><lon>114</lon><lat>22</lat></gps>”就可以。我们测试一下:

 

 

Logstash进阶指南

 

如图,第一次的输入报错了,第二次才正常解析。但问题是,xml的语法并未强制要求只能有一个根节点,所以很多xml字段Logstash自带的插件是解析不了的。我们看看ruby filter如何解决这个问题:简单地加一层节点将目标字段括起来即可。

Logstash进阶指南

 

4.2  通过接口丰富字段

 

Logstash做数据处理时,免不了要去各种外部接口进行查询,然后将结果丰富到事件中。但是,数据丰富发生在数据处理阶段(filter 阶段),而Logstash本身不提供HTTP插件实现这一功能,我们看看用ruby filter怎么做。举个例子:根据输入的经纬度字段, 我们到百度地图API上去查该经纬度对应的地址名。

 

Logstash进阶指南

 

这个例子中也解答了以下问题:

 - 如何在ruby filter中引入一些包

 - 如何在ruby filter中定义一个函数并调用


小结

 

ruby filter的各种骚操作还有很多,其实就是嵌入一段代码。用熟之后,甚至可以省得你记一些比较鸡肋的插件的配置项。所以将其称之为万能的ruby filter。

 

###################################################

转自:https://mp.weixin.qq.com/s?__biz=MzI2NjM5OTMwNA==&idx=1&mid=2247483671&sn=ba356e9761e75db9f90fc9f9f0dabf16