目录
2.4 文件输入 + filter + 写入elasticsearch
2:具体进行(不知道filebeat怎么把读取的内容在控制台能看到,所以结合logstash)
写在前面
很久没有写日志了,这次花了两个星期研究了elk的搭建和运行
之前单纯看elasticsearch的时候,网上各种资料都有。
遇到的一个问题就是:
1.es更新比较快,资料中的配置方式等由于版本更新可能发生变化
2.elk中由于涉及了多个组件,每个组件对于自己都是要去研究的
目前我关于这方面的水平是
elasticsearch:一只脚入门,能大概说出来和关系型数据库,结构的对应比较。但是不能很熟练的使用各种api操作es
kibana:会搭建,会看数据和绘制看板
logstash 和 filebeat:刚入门,知道其中的组件结构,会简单的配置和使用
所以写一下日志来总结下这段时间的思路,也是巩固一下了解到的信息
个人理解
(我不管它能干多牛逼的事,只当它能干啥,随着使用的深入,会扩容对它的理解)
elasticsearch:存储查询数据
kibana:图形化展示数据
logstash:接收数据,抠数据,输送数据
filebeat:从文件采集数据,输送数据
我们是为了能方便的查看日志:
一.使用filebeat,把数据从服务器的日志文件中拿到
二.根据filebeat里面配置启用的outputs,把数据输送给logstash
三.logstash接收到数据后,使用filter组件,抠出每一行的需要的内容,比如:时间,日志级别,具体详情...,同时赋值给定义的变量
四.根据logstash里面配置的output,把美化好的数据输送给elasticsearch
五.使用kibana链接elasticsearch可视化的看到数据,根据数据的维度,比如:时间或者日志级别,绘制需要的图表,再把各种图表放在一起作为一个看板展示
搭建
网上有很多教程,官网上面的搭建步骤也是挺清楚的。主要是很多都是默认配置就行
具体实施
一.使用logstash
1:前置说明
a. 先用它是因为它能在命令行窗口看到数据的输入和输出,我还是比较喜欢看到东西的,方便观察
b. 它的构成有三个组件:input-输入源、filter-过滤器、output-输出源
c. 重点是filter中的各个插件,比如:grok-扣数据,date-替换时间值。。。
d. 需要调用bin目录中的logstash脚本,使用bat脚本启动,可以把测试的配置单独设置一个目录,方便点
e. logstash启动的时候,挺慢的。目前还没具体研究,网上说的原因我还没有去尝试
2:具体进行
2.1 最简单方式
2.1.1 input-手动输入,filter-不要,output-控制台(命令行窗口)
2.1.2 定义first.bat脚本
内容是执行bin/logstash,并指定conf文件-first.conf。我在安装根目录下创建了一个run目录--与bin目录同级别。first.bat在run目录里面,具体内容如下:
#first.bat
#运行bin/logstash, 指定使用哪个配置文件(first.conf也在run目录中)
../bin/logstash -f ./first.confpause #暂停,如果报错了,可以看到原因,否则可能一闪而过,还要去logs目录中看报错原因
#first.conf
#输入源
input {
stdin{}
}#输出源
output {
stdout { codec => rubydebug }
}
2.1.3 双击运行first.bat
出现如下提示:
2.1.4 随便输入个东西看看会怎么样,可以多次输入
a. 每此输出结果都在后面加了一个“\r”的换行符
b.直接enter键换行,也会当成一次输入 3. 输出结果会自动装配4个属性,其中@开头的叫原数据-metadata,所有的输入都在message属性中
2.2 手动输入 + filter入门
2.2.1 input-手动输入,filter-grok、date插件,output-控制台(命令行窗口)
2.2.2 定义second.bat脚本
运行、指定second.conf。具体内容如下:
#second.bat
../bin/logstash -f ./second.conf
pause
#second.conf
#手动输入
input {
stdin{ }
}#过滤器
filter {
#置换 换行符 \r -> 空串
mutate {
gsub => [ "message", "\r", "" ]
}
#丢弃 messge为空的数据
if [message] == ""{
drop{}
}
#分段匹配-扣数据 一行数据 满足 LOGLEVEL + 空格 + NUMBER + 空格 + USERNAME + 其他 的格式,如:warn 123 Luncky ! go go go 。 但是匹配不了,如:warn Luncky 123 go go go#LOGLEVEL-日志级别正则、NUMBER-数字正则、USERNAME-姓名正则 是logstash内置的正则匹配代名词(代名词是我自己对它的称呼,因为好理解)。说有120多种,其他的可以在网上搜到
#然后分别赋值给对应的变量:loglevel、num、user,至于为什么是 %{LOGLEVEL:loglevel} 这种格式,那是人家的语法规定。。。 下图旁边的小图帮忙理解,至于 LOGLEVEL 这样大写的东西哪来的,后面会说
grok {
match => {
"message" => "%{LOGLEVEL:loglevel} %{NUMBER:num} %{USERNAME:user}"
}
}
}output {
stdout { codec => rubydebug }
}
2.2.3 分别输入
1. warn 123 Luncky ! go go go 2. 按键enter换行 3. warn Luncky 123 go go go,输出如下:
2.2.4 结果分析
可以理解为:如果存表的话,就可以把 这一行:“warn 123 Luncky ! go go go“ 的内容,拆分出来 warn、123、Luncky三个字段存入表中,对应表的日志级别,数字类型(比如:错误码),作者
2.3 文件输入 + filter
2.3.1 input-文件file、filter-同上、output-同上
2.3.2 定义third.bat脚本
运行、指定third.conf。conf中的input-file插件读取某个路径下的文件:third.txt。具体内容如下:
#third.bat
../bin/logstash -f ./third.conf
pause
#third.conf
input {
file {# 文件路径,也可以是数组,读取多个文件; 支持 模糊匹配, 如 /run/*.txt--run路径下所有txt结尾的文件,/run/*--run路径下所有文件。 如果没找到文件,不会报错,就是不动了!!啥反应都没有,也不说没找到文件
path => "E:/elk/7.6.2/logstash-7.6.2/run/third.txt"#读取位置 就两个值:beginning 和 end(默认)
start_position => "beginning"#排除的文件
#exclude => "exclude.log"#logstash会记录是不是已经读取过某些文件,修改用于判断的数据存放的位置--为了方便删除判断标识,省的来回改文件内容
sincedb_path => "E:/elk/7.6.2/logstash-7.6.2/run/file.txt"
}
}filter {
mutate {
gsub => [ "message", "\r", "" ]
}
if [message] == ""{
drop{}
}
grok {
match => {
"message" => "%{LOGLEVEL:loglevel} %{NUMBER:num} %{USERNAME:user}"
}
}
}output {
stdout { codec => rubydebug }
}
#third.txt 也就是把 2.2输入的数据放在了文件中,第二行是换行
warn 123 Luncky ! go go go
warn Luncky 123 go go go
#这个文件就3行!!!有第四行的删除--即使只是一个空白行,为了做个实验加深理解
2.3.3 运行结果
如下:比2.2.3第一个结果多了一个path属性-因为用了file插件读取;
2.3.4 注意
绿圈的光标,也就是文件中的三行看起了只解析了一行。其实不是的
1. 第二行是换行,但是在conf-filter中把换行置换为空后,丢弃。所以第二行不来正常
2. 第三行就有问题了,即便没匹配上,也应该像2.2.3第三个结果那样,告诉我读到了什么-message中的信息,然后告诉我为什么抠不出来-tags中的信息
3. 所以上面说的third.txt文件第一次一定要有且仅有3行!! 因为我发现,logstash会丢弃最后一行!!(应该和它的实现逻辑有关)
4. 不需要重启,直接在third.txt,加个第四行(空白行,随便输入什么都行),保存后就会出现第三行的解析结果了,如下(我用的空白行):
2.4 文件输入 + filter + 写入elasticsearch
2.4.1 其实就是在2.3的基础上,把output改一下,加上 elasticsearch插件
所有文件如下:
#fourth.bat
../bin/logstash -f ./fourth.conf
pause
#fourth.conf
input {
file {
path => ["E:/elk/7.6.2/logstash-7.6.2/run/fourth.txt"]
start_position => "beginning"
#exclude => "exclude.log"
sincedb_path => "E:/elk/7.6.2/logstash-7.6.2/run/file.txt"
}
}filter {
mutate {
gsub => [ "message", "\r", "" ]
}
if [message] == ""{
drop{}
}
grok {
match => {
"message" => "%{LOGLEVEL:loglevel} %{NUMBER:num} %{USERNAME:user}"
}
}
}output {
#暂时保留控制台输出
stdout { codec => rubydebug }
# es插件
elasticsearch{#指定索引
index => "fourth-txt"
hosts => ["localhost:9200"]
}
}
fourth.txt
warn 404 Luncky ! go go go
warn Luncky 123 go go go
debug 200 Banana ! go go go
info 200 Apple ! go go go
error 500 Bear go go go
#最后有个空行
2.4.2 启动elasticsearch和kibana,运行 fourth.bat
后在控制台可以看到如下(5行,其中一条数据匹配不了):
kibana中看到新生成的索引
创建索引规则
查看数据,对比关系型数据库的话,这里的数据就比较像可视化工具看到的一张表了
2.5 在2.4的基础上,真正读取日志文件,导入到es中
上一块做的事情是打通从文件到es的过程,能看出来其实重点就是操作logstash-filter,回忆它做的事情:读文件(从文件拿到数据)--》数据解析(扣数据)--》发送数据到控制台和es
读取日志也是这个流程,而且不同的地方仅仅在于:日志的内容和我自定义的 xxx.txt 文件不一样而已。 而这个不一样所影响的只是这个流程中“扣数据”的部分,具体为:filter-grok-match,毕竟内容都变了,肯定要换正则去匹配了
所以只需要修改 fourth.txt(为了像一点,改了后缀为 fourth.log) 和 fourth.conf 了
#fourth.log有中文,最后空行 从tomcat的 access.log 中复制的
07-Apr-2021 11:15:32.646 信息 [main] org.apache.catalina.startup.Catalina.load Initialization processed in 811 ms
07-Apr-2021 11:15:32.719 信息 [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina]
07-Apr-2021 11:15:32.725 信息 [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/9.0.11
07-Apr-2021 11:15:32.747 信息 [main] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [E:\apache-tomcat-9.0.11\webapps\clanrest_war]
#fourth.conf
input {
file {
path => ["E:/elk/7.6.2/logstash-7.6.2/run/fourth.log"]
start_position => "beginning"
#exclude => "exclude.log"
sincedb_path => "E:/elk/7.6.2/logstash-7.6.2/run/file.txt"
}
}filter {
mutate {
gsub => [ "message", "\r", "" ]
}
if [message] == ""{
drop{}
}
grok {#该属性用于自定义上面说到的 正则代名词,指定一个目录即可,该目录下我放了一个叫:fourth_patternsd的文件(不带后缀),具体内容在下面
patterns_dir => ["./patterns"]#重新定义正则匹配规则,抠出来上图红框的部分 其中的 EN_TIME 就在fourth_patternsd文件中定义了 其他大写的东西是logstash自带的,但是原理和这种定义是一样的
match => {
"message" => "%{EN_TIME:time} %{JAVALOGMESSAGE:msg} \[%{JAVALOGMESSAGE:thread}\] %{JAVACLASS:class} %{JAVALOGMESSAGE:info}"
}
}
}output {
stdout { codec => rubydebug }
elasticsearch{
index => "fourth-log" #索引名称改一下
hosts => ["localhost:9200"]
}
}
#具体代名词有哪些 可以查看官方的: https://github.com/logstash-plugins/logstash-patterns-core/tree/master/patterns
#fourth_patternsd
#配置英文时间格式 07-Apr-2021 11:15:32.646 ,其中用到了一些基本的正则代名词 (grok语法)
EN_TIME %{MONTHDAY}-%{MONTH}-%{YEAR} %{TIME}
#纯正则写法也行,就是麻烦点
#EN_TIME [0-9]{2}-[A-Z][a-z]{2}-[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{3}
内置的正则代名词,从官方给到的项目中可以查看到:
运行结果,控制台和kibana如下:
PS: 至于正则代名词使用,是不是能正确抠取数据,没必要一次次运行logstash,有个kibana中调试工具(官方推荐的网址,使用时一直在报错):
kibana 中看到的数据 (message所有内容已经抠完了,其实这个message属性对我来说已经没有用了,所以可以在fourth.conf中 filter-mutate 删除掉 )
看似还行,其实不然。
1. Time列是自带的,对应 @timestamp,值是操作的时间,我希望把它换成日志中的时间,也就是time列(不换也行,像我一样自己抠一个time列,官方也不建议修改@timestamp!)
2. time列是我抠出来的,但是格式看着不舒服,我想换成 “yyyy-MM-dd HH:mm:ss” 格式
3. 不想要message属性
4. 之前没匹配上的话,logstash会自动加一个tags属性,那我也想给我的这批数据加个tag
所以,修改下 fourth.conf ,如下:
#只是添加了一些东西
input {
file {
path => ["E:/elk/7.6.2/logstash-7.6.2/run/fourth.log"]
start_position => "beginning"
#exclude => "exclude.log"
sincedb_path => "E:/elk/7.6.2/logstash-7.6.2/run/file.txt"
}
}filter {
mutate {
gsub => [ "message", "\r", "" ]
}
if [message] == ""{
drop{}
}
grok {
patterns_dir => ["./patterns"]
match => {
"message" => "%{EN_TIME:time} %{JAVALOGMESSAGE:msg} \[%{JAVALOGMESSAGE:thread}\] %{JAVACLASS:class} %{JAVALOGMESSAGE:info}"
}
}# 替换时间到 @timestamp节点
date {
match => ["time" , "dd-MMM-yyy HH:mm:ss.SSS"]
#target => "@timestamp" #这里注释的原因是 target默认就是替换@timestamp(却不建议修改,我理解错了?)
}# 转换时间格式
ruby{
code => "event.set('time', (event.get('@timestamp').time.localtime).strftime('%Y-%m-%d %H:%M:%S'))"
}
# 删除不想要的节点、添加tag
mutate {
add_tag => ["FOURTH_LOG"]
remove_field => ["message"]
}
}output {
stdout { codec => rubydebug }
elasticsearch{
index => "fourth-log"
hosts => ["localhost:9200"]
}
}
运行结果如下(重启后,我添加了一行日志):
kibana就不展示了
至此,logstash操作文件数据的入门例子就算可以了
回顾下:
1. logstash主要是抠取、过滤数据。 不抠取也行,那么所有的数据都在“message”属性中,以后要用的话不方便查看
2. 抠取的话,需要使用filter-过滤器组件,使用其中的grok插件,用正则代名词(可以自定义)先匹配数据。匹配时注意空格和符号。这一块是重点,也是操作logstash,比较费时的事情
3. 抠取出来后,可以按照想要的格式去新增、修改、删除一些属性或者标签;甚至是转换格式,比如:string类型数据转成int
二.使用filebeat
1:前置说明
a. 只是把logstash中的input-输入插件,从file替换成beats;
b. 现在的filebeat配置中是可以直接把数据发送给es或者kibana等等的终端,而且还能进行抠数据,也就是可以说拥有logstash的filter功能。我之所以还是使用logstash的原因是:filebeat中抠数据有点复杂,哈哈
c. 可以指定多个目录下的不同的文件读取,只要做好标记,就可以在接收端根据标记知道这是哪里的文件内容
d. 由于我这边是读取的日志,重点肯定是对于错误信息的采集,所有用了其中很重要的“多行合并”,配置中有三个参数,老半天才理解透是怎么回事
2:具体进行(不知道filebeat怎么把读取的内容在控制台能看到,所以结合logstash)
2.1 启动logstash,监听5044端口
(filebeat默认端口,可以修改;bat文件我就不发了)
#fifth.conf
input {
#监听beats,替换了原来的file插件
beats {
port => 5044
}
}filter {
mutate {
gsub => [ "message", "\r", "" ]
}
if [message] == ""{
drop{}
}
grok {
patterns_dir => ["./patterns"]
match => {
"message" => "%{EN_TIME:time} %{JAVALOGMESSAGE:msg} \[%{JAVALOGMESSAGE:thread}\] %{JAVACLASS:class} %{JAVALOGMESSAGE:info}"
}
}
date {
match => ["time" , "dd-MMM-yyy HH:mm:ss.SSS"]
#target => "@timestamp"
}
ruby{
code => "event.set('time', (event.get('@timestamp').time.localtime).strftime('%Y-%m-%d %H:%M:%S'))"
}
mutate {
add_tag => ["FIFTH_LOG"]
remove_field => ["message"]
}
}output {
stdout { codec => rubydebug }
elasticsearch{
index => "fifth-log"
hosts => ["localhost:9200"]
}
}
2.2 配置filebeat
在filebeat根目录下创建了 run目录,其中新建了start.bat、start.yml、start.log(就是把fourth.log复制过来改个名字)
2.2.1 start.bat还是要执行根目录下的filebeat.exe进程的
所以先cd出来;当调用yml配置文件时,由于已经cd了,所以路径要加上 run目录
#start.bat
CD ../
filebeat.exe -e -c ./run/start.yml
pause
2.2.2 start.yml中的配置
我是为了入门,所以基本都是用的默认和必须的设置;注意缩进,挺严格的;其中暴露的端口和logstash监听的端口一致;
#start.yml
#这个设置和logstash中用于判断是不是读取过文件记录差不多,为了方便删除,设置了下
path.data: ${path.home}/run/data
#=========================== Filebeat inputs =============================
filebeat.inputs:
- type: log
enabled: true
paths:
- ./run/tomcat.log#----------------------------- Logstash output --------------------------------
output.logstash:
hosts: ["localhost:5044"]
PS:这里直接复制的话,会导致缩进有问题,可能出现如下错误:
手动调一下缩进,只用空格键一个一个的缩进,不要用Tab键!!!
2.2.3 启动后
filebeat
logstash
看起来很乱,没错,多了很多字段,而且这些字段是我不需要的,所以修改配置文件
2.2.4 去除不想要的字段
#start.bat
path.data: ${path.home}/run/data
#=========================== Filebeat inputs =============================
filebeat.inputs:
- type: log
enabled: true
paths:
- ./run/start.log#----------------------------- Logstash output --------------------------------
output.logstash:
hosts: ["localhost:5044"]# 处理器 定义要抛弃的字段
processors:
- drop_fields:
fields: ["log", "ecs", "agent", "input", "host"]
至此,filebeat + logstash + elasticsearch + kibana 读取文件,存储数据的入门案例结束了。(es我不算入门,kibana只是可视化工具,所以这两个都没详细说)
2.3 filebeat配置多行合并--解析错误日志
2.3.1 错误日志
错误日志和刚才日志最大的不同是:报错的信息和具体出错行信息,它们是不同的行,而且格式不一样----也就是很多行表示一个信息,就像下面的error.log:
#error.log (项目中log4j打印的自定义日志)
2020-04-21 14:00:56,954 [DubboServerHandler-172.16.133.83:20440-thread-197] ERROR c.w.c.i.r.r.RpcResExecutor - null
java.lang.NullPointerException: null
at com.wordoor.clan.facade.UserBookUnitFacadeService.subscribeExtra(UserBookUnitFacadeService.java:557)
at com.wordoor.clan.facade.UserBookUnitFacadeService.invoke(<generated>)
2020-04-21 14:00:56,957 [DubboServerHandler-172.16.133.83:20440-thread-197] warn c.w.c.i.r.r.RpcResExecutor - Request cost [6]
2020-04-21 14:01:00,001 [DubboServerHandler-172.16.133.83:20440-thread-197] info c.w.c.c.l.BusinessLogger - [com.wordoor.clan.rpcserv.user.UserScheduleRpcService:queryPage]queryPage with UserSchedulePageParamData[UserSchedulePageParamData[queryDate=Wed Apr 21 14:01:00 CST 2021,pn=1,ps=500,userId=<null>,lang=<null>,requestIp=<null>]]
2.3.2 很明显
这其实是三条(error,warn,info各一条)日志,处理思路就是:把表达相同意思的多行合并一下,而合并完之后,三条数据的格式都是:日期+线程+日志级别+具体信息
所以对应的修改内容就是:
2.3.2.1. filebeat:配置多行合并策略
# filebeat 的 start.yml
path.data: ${path.home}/run/data
#=========================== Filebeat inputs =============================
filebeat.inputs:
- type: log
enabled: true
paths:#修改读取文件
- ./run/error.log#多行合并策略--三个配置
multiline.pattern: ^\d{4}-\d{1,2}-\d{1,2}
multiline.negate: true
multiline.match: after#----------------------------- Logstash output --------------------------------
output.logstash:
hosts: ["localhost:5044"]processors:
- drop_fields:
fields: ["log", "ecs", "agent", "input", "host"]
策略解读:
multiline.pattern: ^\d{4}-\d{1,2}-\d{1,2} 正则配置--以\d{4}-\d{1,2}-\d{1,2}格式开头的行,也就是 2020-04-21 14:00:56,954 中的年-月-日开头
multiline.negate: true 是否拼接 true:追加 false:不加
multiline.match: after 拼接位置 before:前面 after:后面
具体解释:先看后两个,目前表示:在后面追加。 至于在谁的后面加,就看第一个:以 时间 开头的行的后面追加,图解如下:
也就是每解析一行,这一行的数据先临时挂起来,等下一行数据解析结束后,才能决定挂起来的行怎么操作
a.下一行没匹配,就把下一行加到悬挂行的前面或后面,悬挂行继续悬挂;
b.下一行匹配了,就把这个刚匹配的行悬挂,原悬挂行可以放下来,输出出去了
PS: 实际不是这个意思,但是我这么理解!!!具体人家想表示什么,可以在网上查查资料,反正我是看的一脸懵逼
2.3.2.2. logstash:按照这种格式抠数据
#logstash 的 fifth.conf
input {
beats {
port => 5044
}
}filter {
mutate {
gsub => [ "message", "\r", "" ]
}
if [message] == ""{
drop{}
}
grok {# 该目录下 新增了正则代名词文件内容
patterns_dir => ["./patterns"]
match => {# 修改匹配格式 这里的 CN_TIME 和 之前的 ZN_TIME都是patterns目录里面文件four_patterns中定义的
"message" => "%{CN_TIME:time} \[%{JAVALOGMESSAGE:thread}\] %{LOGLEVEL:level} %{JAVACLASS:class} - %{JAVALOGMESSAGE:info}"
}
}
date {#注意日期格式变化了
match => ["time" , "yyyy-MM-dd HH:mm:ss,SSS"]
}
ruby{
code => "event.set('time', (event.get('@timestamp').time.localtime).strftime('%Y-%m-%d %H:%M:%S'))"
}
mutate {#换一个tag
add_tag => ["ERROR_LOG"]#先不移除message,方便看是不是成功的多行合并了
#remove_field => ["message"]
}
}output {
stdout { codec => rubydebug }
elasticsearch{#换一个索引--因为抠出来的数据属性变化了,存在同一个索引下可能报错
index => "error-log"
hosts => ["localhost:9200"]
}
}
重点看多行合并的结果,如下:
还有点小问题
这里的索引我取名是:error-log,所以我希望只有error信息,那么info和warn信息我要丢弃(有大小写)
那么修改下 fifth.conf---至于为什么不在读取的时候,也就是filebeat中丢弃
我的想法是:人家只是采集文件数据的,这种丢弃什么的涉及到了处理逻辑,所以还是在logstash中进行吧,毕竟logstash才是整合数据的地方(各司其职)---主要是我不会怎么在filebeat中进行这种逻辑,可能需要用管道的语法吧
#fifth.conf
input {
#监听beats源
beats {
port => 5044
}
}filter {
mutate {
gsub => [ "message", "\r", "" ]
}
if [message] == ""{
drop{}
}
grok {
patterns_dir => ["./patterns"]
match => {
"message" => "%{CN_TIME:time} \[%{JAVALOGMESSAGE:thread}\] %{LOGLEVEL:level} %{JAVALOGMESSAGE:class} - %{JAVALOGMESSAGE:info}"
}
}
mutate {#去除前后空格
strip => ["level"]
#把level统一大写
uppercase => ["level"]
add_tag => ["ERROR_LOG"]
#remove_field => ["message"]
}# 按条件去除
if ([level] in ["WARN","INFO"]) {
drop {}
}# 不想动 @timestamp 所以注释掉和时间有关的东西
# date {
#match => ["time" , "yyyy-MM-dd HH:mm:ss,SSS"]
# }# 转换时间格式
# ruby{
# code => "event.set('time', (event.get('@timestamp').time.localtime).strftime('%Y-%m-%d %H:%M:%S'))"
#}
}output {
stdout { codec => rubydebug }
elasticsearch{
index => "error-log"
hosts => ["localhost:9200"]
}
}
至此,我想要的东西有一个完整的雏形了。这个时候可以试着在error.log中添加错误日志,来测试下:是不是当日志增加的时候,会持续的收集数据了
红框的时间就是@timestamp的值,也就是记录日志的时间。为了能更好的看到新采集的记录,所以在fifth.conf中把时间相关的注释了
2.4 同时采集多个路径下的日志,并存储到不同的es索引中
同一个filebeat实例可以直接读取不同的文件,如下:
#start.yml
path.data: ${path.home}/run/data
#=========================== Filebeat inputs =============================
filebeat.inputs:
- type: log
enabled: true
paths:
- ./run/error.log#添加fields 标记文件
fields:
#与logstash中的if条件对应
filetype: error_log
multiline.pattern: ^\d{4}-\d{1,2}-\d{1,2}
multiline.negate: true
multiline.match: after
- type: log
enabled: true
paths:
- ./run/tomcat.log
fields:
#与logstash中的if条件对应
filetype: tomcat_log
#注意日志格式不一样了,匹配可能有变化
multiline.pattern: ^\d{2}-[A-Z][a-z]{2}-\d{4}
multiline.negate: true
multiline.match: after#----------------------------- Logstash output --------------------------------
output.logstash:
hosts: ["localhost:5044"]processors:
- drop_fields:
fields: ["log", "ecs", "agent", "input", "host"]
#fifth.conf
input {
#监听beats源
beats {
port => 5044
}
}filter {
mutate {
gsub => [ "message", "\r", "" ]
}
if [message] == ""{
drop{}
}
#与 filebeat 中的标记对应---这里有个坑,网上有的资料是 直接 if [filetype] == "tomcat_log",可能是版本不一样,我这边是用 [fields][filetype]才能拿到这个属性的,相当于json数据要一层层获取到想要的节点才行
if [fields][filetype] == "tomcat_log"{
# 提取 message 中各段信息
grok {
patterns_dir => ["./patterns"]
match => {
"message" => "%{EN_TIME:time} %{LOGLEVEL:level} \[%{JAVALOGMESSAGE:thread}\] %{JAVALOGMESSAGE:info}"
}
}
}else{
# 提取 message 中各段信息
grok {
patterns_dir => ["./patterns"]
match => {
"message" => "%{CN_TIME:time} \[%{JAVALOGMESSAGE:thread}\] %{LOGLEVEL:level} %{JAVALOGMESSAGE:class} - %{JAVALOGMESSAGE:info}"
}
}
}
mutate {strip => ["level"]
uppercase => ["level"]
add_tag => ["ERROR_LOG"]
#remove_field => ["message"]
}
if ([level] in ["WARN","INFO"]) {
drop {}
}# 替换时间到 @timestamp节点
# date {
#match => ["time" , "yyyy-MM-dd HH:mm:ss,SSS"]
# }# 转换时间格式
# ruby{
# code => "event.set('time', (event.get('@timestamp').time.localtime).strftime('%Y-%m-%d %H:%M:%S'))"
#}
}output {
stdout { codec => rubydebug }
if [fields][filetype] == "tomcat_log"{
elasticsearch{
index => "tomcat-log"
hosts => ["localhost:9200"]
}
}else{
elasticsearch{
index => "error-log"
hosts => ["localhost:9200"]
}}
}
#tomcat.log
01-Sep-2020 10:17:15.022 error [main] org.apache.catalina.startup.Catalina.start Server startup in 49941 ms
java.lang.NullPointerException
at com.ijpay.wxpay.WxPayApiConfigKit.getAppId(WxPayApiConfigKit.java:70)
at com.ijpay.wxpay.WxPayApiConfigKit.getWxPayApiConfig(WxPayApiConfigKit.java:76)
at com.wordoor.trans.rest.web.payment.wxpay.WxPayController.scanCode2(WxPayController.java:93)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
01-Sep-2020 10:17:15.022 error [main] org.apache.catalina.startup.Catalina.start Server startup in 49941 ms
PS
1. 结果就不贴了,不外乎多了个if判断
2. 之前如果没出问题,这里的问题不外乎:匹配问题,标识问题,判断问题
最后
1. 没写过那么长的日志,有些内容也是反复修改的,可能会有混乱的地方
2. 只是说了怎么搞文件什么的,至于文件中的语法,代表含义等等的没有细说,后面会不上文章来说明的
3. 毕竟是入门嘛,先能使用,再研究含义我觉得会快一点
更新----2021年5月21
1. logstash的filter中的 level 抠出来后,在mutate插件中 新增了一个 strip => ["level"],用来去除前后的空格(配置文件中已经加入)
更新---2021年5月26
1. elasticsearch启动的时候,报了一个关于jdk的错,意思是:jvm应该用 server版的。我可不想改jdk,所以就改了启动脚本的配置--elasticsearch.bat
JVM is using the client VM [Java HotSpot(TM) Client VM] but should be using a server VM for the best performance
红框里面只保留 else,就是不看本机的java_home,直接用 es根目录的jdk(7.x版本的是有这个jdk目录的)