一、前言
该方式是利用已有的数据,自定义提取其中的部分内容生成新字段,其好处是可以动态适应导入的数据,针对需求变化进行处理,而不用重新定义pipeline或用logstash重新过滤。并且,它可以说是专门为了可视化而设计,生成的字段是无法通过搜索等操作处理,但是生成DashBoard等可视化界面时有效
这是Kibana自带的功能,针对已经创建的Index Pattern,我们可以生成一个脚本化字段,利用ES专门的painless语言来处理,处理过程可以使用函数调用获取内容,也可以正则表达式匹配内容。
不过,正则表达式匹配很消耗资源,ES初始是默认关闭,需要在elasticsearch.yml配置文件中加入语句:
script.painless.regex.enabled: true
关于脚本化字段和正则表达式的使用,可参考以下链接。我主要是参考带★的两个链接,一个是官方给出的示例,一个是正则表达式的语句测试
官网:
脚本化字段介绍:https://www.elastic.co/guide/cn/kibana/current/scripted-fields.html
★脚本化字段示例:https://www.elastic.co/cn/blog/using-painless-kibana-scripted-fields(这个网站不知道为什么有时候会刷出空内容,多刷新几次就好了)
Painless语法:https://www.elastic.co/guide/en/elasticsearch/painless/7.10/index.html
菜鸟教程:
正则表达式菜鸟教程:https://www.runoob.com/regexp/regexp-tutorial.html
★正则表达式在线测试:http://c.runoob.com/front-end/854
★正则表达式Matcher()函数调用API:https://www.elastic.co/guide/en/elasticsearch/painless/7.10/painless-api-reference.html(在该界面Ctrl+F搜索Matcher)
2020-11-21 00:19:47,459 INFO org.Executor: Deleting absolute path: [nice, -n, 0, bash, /sdada/appcache/application_315146546_156/contanier_fd4156_fdsafasdfasd/fsfs_dsa.sh]
以上是我想要匹配的语句【其中很多是我键盘随意打出的,只留下了需要匹配的信息】,主要计划提取的信息是:
application: application_315146546_156
信息存储在message字段中。即想要将application编号从message中提取并存储在新字段application中。
二、新建Scripts Fields
Stack Management→Index Patterns→选中要处理的索引(我处理的是myx-t1-*)→Scripted Fields→Add Scripted Fields
给新字段Name命为application,编辑Scripts语句,单击下方链接可以预览处理结果,由于我只是部分数据存在这些字段,因此前十条匹配为空。
1.方法一:查找子串下标,按长度提取(Name:application)
def path = doc['message.keyword'];
if (path != null) {
path = path.toString();
int lastSlashIndex = path.lastIndexOf('application');
if (lastSlashIndex > 0) {
return path.substring(lastSlashIndex,lastSlashIndex+31);
}
}
该语句意义为:取message字段的数据,找到最后出现application的下标,如果下标存在(即找到该子串,否则返回值为-1),则将application字段赋值为从该下标开始到该下标后的31个字符(因为application编号字段长31个字符)。其他情况可以在if外加一句return null;不加可以,默认会赋为null
当语句修改后,单击Run script就可以刷新结果
2.方法二:正则表达式提取(Name:application_t1)
在正则表达式在线测试页面,我们通过调试找到能够成功匹配的正则表达式
/application[_0-9]+/
于是,编译Scripts
def path = doc['message.keyword'];
if (path != null){
path = path.toString();
def m = /application[_0-9]+/.matcher(path);
if (m.find()==true){
return m.group(0);
}
}
return "";
出现返回值则至少没有出现语法错误。
我们对字段进行创建保存,到Discover界面查看结果
三、查看生成结果
利用Scrips Field生成的字段是无法通过索引查询到的,主要在可视化DashBoard等界面使用。为此,我们可以想一些其他方法检索到相应的内容,例如以我的案例可以检索:在message中存在“application”字段的数据
等待更新,可以发现相应的application字段已经生成
问题小结:
1.First 10 results []
如果测试的结果显示仅仅为一个方括号,很大可能是匹配语法有问题,虽然此时没有报错,但是真正运行后无法产生结果。可以在Discover页面刷新,然后可能产生报错信息,进行细节的查看。
错误举例:
在下图中,预览结果没有报错,但是显示为[]
我们保存字段并到Discover页面刷新查看,单击右下角报出的错误警告,对应原因进行调试
2.doc['xxx'].value和doc['xxx']
一般来说,取内容的方式是doc['xxx'].value,但是我的message字段不知道为什么无法直接取value,只能通过doc['message.keyword']获取,并且获取完成后需要toString()转换才可以进行检索,而一般获取的内容并不需要格式转换。
当预览结果不显示时,这只是一种尝试方式,我目前还没有理解原理,有了解的欢迎和我交流~
3.can not write type [class java.util.regex.Matcher]
can not write type一般是一个类型问题,ES无法识别或者与输入输出的类型不匹配,我发生这个问题是因为在m=//.mathcer(test)之后,直接返回m,导致无法识别,正确的返回值应该是m.matches()【bool类型,返回值true/false,表示是否成功匹配】或是m.group(1),即返回匹配到的内容
def m = /pattern/.matcher(doc[''].value);
return m.matches()
# 或是
def m = /pattern/.matcher(doc[''].value);
if (m.matches()){
return m.group(1)
}
4.正则表达式m.matches()返回false
参考博客: