一、Logstash 介绍
logstash是一个用来管理事件和日志的工具,它的作用是收集日志,解析日志,存储日志为以后使用。
Logstash 是一个轻量级、强大的日志处理工具,可以用来分散的、多样化的日志搜收集起来、自定义过滤处理转换、存储日志数据到某个文件或者服务器。用于从文件中收集日志事件。
Logstash 也可以进行数据的转换:Logstash提供了多种输入和输出插件,可以从各种数据源读取数据,并将其发送到各种目标。对于SQL数据库,Logstash提供了一些特定的输入和输出插件,如JDBC输入插件和JDBC输出插件,可以方便地与关系型数据库进行数据交互。通过配置Logstash的输入和输出插件,你可以定义数据源和目标的连接信息、查询语句或写入操作,以实现数据迁移。
对于NoSQL数据库,Logstash也提供了一些特定的输入和输出插件,如Elasticsearch输入插件和Elasticsearch输出插件,可以与Elasticsearch进行数据交互。此外,Logstash还支持其他NoSQL数据库,如MongoDB和Cassandra,可以使用相应的插件进行数据迁移
Logstash 能够动态地采集、转换和传输数据,不受格式或复杂度的影响。利用 Grok 从非结构化数据中派生出结构,从 IP 地址解码出地理坐标,匿名化或排除敏感字段,并简化整体处理过程
logstash处理事件有三个阶段:input —> filter —> output。input产生事件,filter 对事件进行修改,output输出到其它地方。
-
数据输入采集阶段:
采集各种样式、大小和来源的数据:数据往往以各种各样的形式,或分散或集中地存在于很多系统中。Logstash 支持各种输入选择,可以同时从众多常用来源捕捉事件。能够以连续的流式传输方式,轻松地从您的日志、指标、Web 应用、数据存储以及各种 AWS 服务采集数据。 -
筛选
数据从源传输到存储库的过程中,Logstash 筛选器能够解析各个事件,识别已命名的字段以构建结构,并将它们转换成通用格式,以便进行更强大的分析和实现商业价值。
Logstash 能够动态地转换和解析数据,不受格式或复杂度的影响:- 利用 Grok 从非结构化数据中派生出结构
- 从 IP 地址破译出地理坐标
- 将 PII 数据匿名化,完全排除敏感字段
- 简化整体处理,不受数据源、格式或架构的影响。
使用我们丰富的筛选器库和功能多样的 Elastic Common Schema,您可以实现无限丰富的可能。
-
输出
选择您的存储库,传输您的数据
尽管 Elasticsearch 是我们的首选输出方向,能够为我们的搜索和分析带来无限可能,但它并非唯一选择。
Logstash 提供了众多输出选择,您可以将数据发送到所需的位置,并且能够灵活地解锁众多下游用例。
二、配置文件
Logstash配置文件位于Logstash安装目录下bin/logstash.conf
启动参数
启动命令:
logstash -f logstash.conf
其中我们启动的时候给Logstash脚本传入了-e的参数,但实际上,Logstash的启动参数有很多,我们来看一下各个启动参数的作用:
-e #立即启动实例,例如:./logstash -e “input {stdin {}} output {stdout {}}”
-f #指定启动实例的配置文件,例如:./logstash -f config/test.conf
-t #测试配置文件的正确性,例如:./logstash -f config/test.conf -t
-l #指定日志文件名称,例如:./logstash -f config/test.conf -l logs/test.log
-w #指定filter线程数量,不指定默认是5,例如:./logstash-f config/test.conf -w 8
配置文件介绍
文件 | 描述 |
---|---|
logstash.yml | 配置Logstash的yml。 |
pipelines.yml | 包含在单个Logstash实例中运行多个管道的框架和说明。 |
jvm.options | 配置Logstash的JVM,使用此文件设置总堆空间的初始值和最大值,此文件中的所有其他设置都被视为专家设置。 |
log4j2.properties | 包含log4j 2库的默认设置。 |
logstash.yml
logstash.yml 配置 es 数据推送的地址
logstash.con
logstash.con 文件 主要用于定义数据处理插件配置
logstash.conf配置文件结构
input {
#标准输入源插件
stdin {
}
#普通文件源插件
file {
path => ["/var/log/*.log", "/var/log/message"]
....
}
......
}
filter {
#grok过滤插件
grok {
match => ["message", "%{HTTPDATE:logdate}"]
.....
}
#date过滤插件
date {
match => ["logdate", "dd/MMM/yyyy:HH:mm:ss Z"]
.....
}
.....
}
output {
stdout {
}
elasticsearch {
hosts => ["127.0.0.1:9200"]
....
}
.....
}
input 输入插件;filter 过滤器插件;output 输出插件。
配置文件结构示例
input {
file {
path => "/home/test/logstash/ml-25m/movies.csv"
start_position => "beginning"
sincedb_path => "/dev/null"
}
}
filter {
csv {
separator => ","
columns => ["id","content","genre"]
}
mutate {
split => { "genre" => "|" }
remove_field => ["path", "host","@timestamp","message"]
}
mutate {
split => ["content", "("]
add_field => { "title" => "%{[content][0]}"}
add_field => { "year" => "%{[content][1]}"}
}
mutate {
convert => {
"year" => "integer"
}
三 、插件基础
logstash功能很强大。从 logstash 1.5.0 版本开始,logstash 将所有的插件都独立拆分成 gem 包。这样每个插件都可以独立更新,不用等待 logstash 自身做整体更新的时候才能使用了。为了达到这个目标,logstash 配置了专门的 plugins 管理命令
logstash通过管道完成数据的采集与处理,管道配置中包含input、output和filter(可选)插件,input和output用来配置输入和输出数据源、filter用来对数据进行过滤或预处理,阿里云Logstash支持多管道并行运行,目前最多支持20个;
每个配置部分可以包含一个或多个插件。例如,指定多个filter插件,Logstash会按照它们在配置文件中出现的顺序进行处理。
1.Logstash插件分类
- inputs:输入
- codecs:解码
- filters:过滤
- outputs:输出
2. logstash 中支持的数据类型
Boolean,例如:ssl_enable => true
Number,例如:port => 33
String,例如:name => “Hello world”
hash,例如:options => {key1 => “value1”, key2 => “value2”}
array,例如:match => [“datetime”, “UNIX”, “ISO8601”]
- array
数组可以是单个或者多个字符串值。
path => [ “/var/log/messages”, “/var/log/*.log” ]
path => “/data/mysql/mysql.log”
如果指定了多次,追加数组。此实例path数组包含三个字符串元素。 - boolean
布尔值必须是TRUE或者false。true和false不能有引号。
ssl_enable => true - bytes
指定字节单位。支持的单位有SI (k M G T P E Z Y) 和 Binary (Ki Mi Gi Ti Pi Ei Zi Yi)。Binary单位基于1024,SI单位基于1000。不区分大小写和忽略值与单位之间的空格。如果没有指定单位,默认是byte。
my_bytes => “1113” # 1113 bytes
my_bytes => “10MiB” # 10485760 bytes
my_bytes => “100kib” # 102400 bytes
my_bytes => “180 mb” # 180000000 bytes - Codec
logstash编码名称用来表示数据编码。用于input和output段。便于数据的处理。如果input和output使用合适的编码,就无需单独的filter对数据进行处理。
codec => “json” - hash
键值对,注意多个键值对用空格分隔,而不是逗号。
match => {
“field1” => “value1”
“field2” => “value2”
… } - number
必须是有效的数值,浮点数或者整数。
port => 33 - password
一个单独的字符串。
my_password => “password” - path
一个代表有效的操作系统路径。
my_path => “/tmp/logstash” - string
name => “Hello world”
name => ‘It\’s a beautiful day’
3. Logstash支持的判断方法
4. Logstash支持的逻辑判断
– in、notin、and、or、nand、xor
5.字段引用
logstash字段引用语法。要在 Logstash 配置中使用字段的值,只需要把字段的名字写在中括号 [] 里就行了,这就叫字段引用。还需注意字段层次。如果引用的是一个顶级字段,可以省略[],直接指定字段名。要引用嵌套的字段,需要指定完整的路径,如[top-level field][nested field]。
下面有五个顶级字段(agent, ip, request, response, ua) 和三个嵌套字段 (status, bytes, os)。
6.条件判断
Logstash支持下面的操作符:
1、==(等于), !=(不等于), <(小于), >(大于), <=(小于等于), >=(大于等于)
2、=~(匹配正则), !~(不匹配正则)
3、in(包含), not in(不包含)
4、and(与), or(或), nand(非与), xor(非或)
5、()(复合表达式), !()(对复合表达式结果取反)
例如以下的条件判断:
if "_grokparsefailure" not in [tags] {
}
else if [status] !~ /^2\d\d/ or ( [url] == "/noc.gif" nand [geoip][city] != "beijing" ) {
}
else {
}
环境变量引用
Logstash支持引用系统环境变量,环境变量不存在时可以设置默认值,例如:
export TCP_PORT=12345
input {
tcp {
port => "${TCP_PORT:54321}"
}
}
四、常用插件
1. Input Plugin
输入插件允许一个特定的事件源可以读取到 Logstash 管道中,配置在 input {} 中,且可以设置多个
1.1 从文件输入
从文件读取数据,如常见的日志文件。文件读取通常要解决几个问题:
No. | 问题 | 解决办法 |
---|---|---|
1 | 文件内容如何只被读取一次? | 即重启Logstash时,从上次读取的位置继续 sincedb |
2 | 如何即时读取到文件的新内容 | 定时检查文件是否有更新 |
3 | 如何发现新文件并进行读取 | 定时检查是否有新文件生成 |
4 | 如何文件发生了归档(rotation)操作,是否影响当前的内容读取 | 不影响,被归档的文件内容可以继续被读取 |
所有输入插件都支持的配置选项
Setting | Input type | Required | Default | Description |
---|---|---|---|---|
add_field | hash | No | {} | 添加一个字段到一个事件 |
codec | codec | No | plain | 用于输入数据的编解码器 |
enable_metric | boolean | No | true | |
id | string | No | 添加一个ID插件配置,如果没有指定ID,则Logstash将生成一个ID。强烈建议配置此ID,当两个或多个相同类型的插件时,这个非常有用的。例如,有两个文件输入,添加命名标识有助于监视 | |
tags | array | No | 添加任意数量的标签,有助于后期处理 | |
type | string | No | 为输入处理的所有事件添加一个字段,自已随便定义,比如linux系统日志,定义为syslog |
Logstash不只是一个input|filter|output的数据流,而是一个input|decode|filter|encode|output的数据流。codec就是用来decode,encode 事件的。所以codec常用在input和output中
常用的codec插件有plain,json,multiline等,常用的codec插件有plain,json,multiline等
参考:https://blog.51cto.com/zengestudy/1832801
stdin 插件
从标准输入读取数据,从标准输出中输出内容:
[root@es-node1 ~]# vim /etc/logstash/conf.d/test1.conf
input {
stdin {
type => "stdin" # 自定义事件类型,可用于后续判断
tags => "stdin_type" # 自定义事件 tag,可用于后续判断
}
}
output {
stdout {
codec => "rubydebug"
}
}
执行测试:
[root@es-node1 ~]# logstash -f /etc/logstash/conf.d/test1.conf
hello world
file插件
从 file 文件中读取数据,然后输入至标准输入
Setting | Input type | Required | Default | Description |
---|---|---|---|---|
close_older | number | No | 3600 | 单位秒,打开文件多长时间关闭 |
delimiter | string | No | \n | 每行分隔符 |
discover_interval | number | No | 15 | 单位秒,多长时间检查一次path选项是否有新文件 |
exclude | array | No | 排除监听的文件,跟path一样,支持通配符 | |
max_open_files | number | No | 打开文件最大数量 | |
path | array | YES | 输入文件的路径,可以使用通配符 例如/var/log/*/.log,则会递归搜索 | |
sincedb_path | string | No | sincedb数据库文件的路径,用于记录被监控的日志文件当前位置 | |
sincedb_write_interval | number | No | 15 | 单位秒,被监控日志文件当前位置写入数据库的频率 |
start_position | string, one of [“beginning”, “end”] | No | end | 指定从什么位置开始读取文件:开头或结尾。默认从结尾开始,如果要想导入旧数据,将其设置为begin。如果sincedb记录了此文件位置,那么此选项不起作用 |
stat_interval number | No | 1 | 单位秒,统计文件的频率,判断是否被修改。增加此值会减少系统调用次数。 |
cat file_logstash.conf
input {
file {
path => "/var/log/test.log"
type => "syslog"
exclude => "*.gz" # 不监听的文件
start_position => "beginning" # 第一次从头开始读取文件 beginning or end
stat_interval => "3" #定时检查文件是否更新,默认1s
}
}
output {
stdout {
codec => rubydebug
}
}
运行命令
/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/file_logstash.conf
输出
echo "file logstash" > /var/log/test.log
{
"@version" => "1",
"path" => "/var/log/test.log",
"type" => "syslog",
"@timestamp" => 2021-10-30T07:58:42.699Z,
"host" => "logstash-node1",
"message" => "file logstash"
}
beats 插件
从filebeat文件中读取数据,然后输入至标准输入
cat beats_logstash.conf
cat beats_logstash.conf
input {
beats {
port => 5044 # filebeat 发送数据到logstash主机的5044端口
}
}
output {
stdout {
codec => rubydebug
}
}
kafka插件
- 输入配置
input {
kafka {
zk_connect =>
"kafka1:2181,kafka2:2181,kafka3:2181"
group_id => "logstash"
topic_id => "apache_logs"
consumer_threads => 16
}
}
消费端的一些比较有用的配置项:
group_id:消费者分组,可以通过组 ID 去指定,不同的组之间消费是相互不受影响的,相互隔离。
topic_id:指定消费话题,也是必填项目,指定消费某个 topic ,这个其实就是订阅某个主题,然后去消费。
reset_beginning:logstash 启动后从什么位置开始读取数据,默认是结束位置,也就是说 logstash 进程会以从上次读取结束时的偏移量开始继续读取,如果之前没有消费过,那么就开始从头读取.如果你是要导入原有数据,把这个设定改成 “true”, logstash 进程就从头开始读取.有点类似 cat ,但是读到最后一行不会终止,而是变成 tail -F ,继续监听相应数据。
decorate_events:在输出消息的时候会输出自身的信息包括:消费消息的大小, topic 来源以及 consumer 的 group 信息。
rebalance_max_retries:当有新的 consumer(logstash) 加入到同一 group 时,将会 reblance ,此后将会有 partitions 的消费端迁移到新的 consumer 上,如果一个 consumer 获得了某个 partition 的消费权限,那么它将会向 zookeeper 注册, Partition Owner registry 节点信息,但是有可能此时旧的 consumer 尚没有释放此节点,此值用于控制,注册节点的重试次数。
consumer_timeout_ms:指定时间内没有消息到达就抛出异常,一般不需要改。
以上是相对重要参数的使用示例,更多参数可以选项可以跟据 https://github.com/joekiller/logstash-kafka/blob/master/README.md 查看 input 默认参数。
注意
1.想要使用多个 logstash 端协同消费同一个 topic 的话,那么需要把两个或是多个 logstash 消费端配置成相同的 group_id 和 topic_id , 但是前提是要把 相应的 topic 分多个 partitions (区) ,多个消费者消费是无法保证消息的消费顺序性的。
这里解释下,为什么要分多个 partitions(区) , kafka 的消息模型是对 topic 分区以达到分布式效果。每个 topic 下的不同的 partitions (区) 只能有一个 Owner 去消费。所以只有多个分区后才能启动多个消费者,对应不同的区去消费。其中协调消费部分是由 server 端协调而成。不必使用者考虑太多。只是 消息的消费则是无序的 。
总结:保证消息的顺序,那就用一个 partition 。 kafka 的每个 partition 只能同时被同一个 group 中的一个 consumer 消费 。
- Output 配置
以下配置可以实现对 kafka 写入端 (producer) 的基本使用。
output {
kafka {
broker_list => "localhost:9092"
topic_id => "test"
compression_codec => "snappy" # string (optional), one of ["none", "gzip", "snappy"], default: "none"
}
}
Output 解释
生产的可设置性还是很多的,设置其实更多,以下是更多的设置:
compression_codec:消息的压缩模式,默认是 none,可以有 gzip 和 snappy (暂时还未测试开启压缩与不开启的性能,数据传输大小等对比)。
compressed_topics:可以针对特定的 topic 进行压缩,设置这个参数为 topic ,表示此 topic 进行压缩。
request_required_acks:消息的确认模式:
可以设置为 0: 生产者不等待 broker 的回应,只管发送.会有最低能的延迟和最差的保证性(在服务器失败后会导致信息丢失)
可以设置为 1: 生产者会收到 leader 的回应在 leader 写入之后.(在当前 leader 服务器为复制前失败可能会导致信息丢失)
可以设置为 -1: 生产者会收到 leader 的回应在全部拷贝完成之后。
partitioner_class:分区的策略,默认是 hash 取模
send_buffer_bytes:socket 的缓存大小设置,其实就是缓冲区的大小
消息模式相关:serializer_class
消息体的系列化处理类,转化为字节流进行传输, 请注意 encoder 必须和下面的 key_serializer_class 使用相同的类型 。
key_serializer_class:默认的是与 serializer_class 相同
producer_type:生产者的类型 async 异步执行消息的发送 sync 同步执行消息的发送
queue_buffering_max_ms:异步模式下,那么就会在设置的时间缓存消息,并一次性发送
queue_buffering_max_messages:异步的模式下,最长等待的消息数
queue_enqueue_timeout_ms:异步模式下,进入队列的等待时间,若是设置为0,那么要么进入队列,要么直接抛弃
batch_num_messages:异步模式下,每次发送的最大消息数,前提是触发了 queue_buffering_max_messages 或是 queue_enqueue_timeout_ms 的限制
以上是相对重要参数的使用示例,更多参数可以选项可以跟据 https://github.com/joekiller/logstash-kafka/blob/master/README.md 查看 output 默认参数。
小贴士
默认情况下,插件是使用 json 编码来输入和输出相应的消息,消息传递过程中 logstash 默认会为消息编码内加入相应的时间戳和 hostname 等信息。如果不想要以上信息(一般做消息转发的情况下),可以使用以下配置,例如:
output {
kafka {
codec => plain {
format => "%{message}"
}
}
}
TCP插件
通过TCP套接字读取事件,即接收数据。与标准输入和文件输入一样,每个事件都被定位一行文本。
# cat /etc/logstash/conf.d/tcptest.conf
input {
tcp {
port => 12345
}
}
filter {
}
output {
stdout{
}
}
在其他主机上安装nc工具,对logstash发送信息,即可被读取出来。
root@vm4 ~]# yum -y install nc
[root@vm4 ~]# nc 10.1.1.13 12345
haha
在vm3上验证查看
{
“@version” => “1”,
“@timestamp” => 2019-07-02T15:28:00.301Z,
“port” => 33778,
“type” => “nc”,
“message” => “haha”,
“host” => “vm4.cluster.com”
}
P是一种网络传输控制协议,很多公司的数据不一定是在本地的,而是在传承网络的;
这个时候使用TCP简历连接后,通信双王就可以进行数据传输了;TCP插件可以监控某个端口,当数据打入logstash监听的端口队列的时候,logstash就可以进行数据的采集
input{
tcp {
port => 9876
mode => "server"
ssl_enable => false
}
}
output{
stdout{}
}
启动并且监听到9876端口;
检测logstash 配置文件
bin/logstash -f /usr/local/elk/logstash-5.5.2/conf/template/monitor_tcp.conf -t
bin/logstash -f /usr/local/elk/logstash-5.5.2/conf/template/monitor_tcp.conf
public static void main(String[] args) throws Exception{
// 向服务器端发送请求,服务器IP地址和服务器监听的端口号
Socket client = new Socket("hadoop01", 9876);
// 通过printWriter 来向服务器发送消息
PrintWriter printWriter = new PrintWriter(client.getOutputStream());
System.out.println("连接已建立...");
for(int i=0;i<10;i++){
// 发送消息
printWriter.println("hello logstash , 这是第"+i+" 条消息");
printWriter.flush();
}
}
观察结果
2.filter 插件
mutate 数据修改插件
它提供了丰富的基础类型数据处理能力。可以重命名,删除,替换和修改事件中的字段。
Mutate 过滤器常用的配置选项
add_field 向事件添加新字段,也可以添加多个字段
remove_field 从事件中删除任意字段
add_tag 向事件添加任意标签,在tag字段中添加一段自定义的内容,当tag字段中超过一个内容的时候会变成数组
remove_tag 从事件中删除标签(如果存在)
convert 将字段值转换为另一种数据类型
id 向现场事件添加唯一的ID
lowercase 将字符串字段转换为其小写形式
replace 用新值替换字段
strip 删除开头和结尾的空格
uppercase 将字符串字段转换为等效的大写字母
update 用新值更新现有字段
rename 重命名事件中的字段
gsub 通过正则表达式替换字段中匹配到的值
merge 合并数组或 hash 事件
split 通过指定的分隔符分割字段中的字符串为数组```
示例
●将字段old_field重命名为new_field
filter {
mutate {
#写法1,使用中括号括起来
rename => ["old_field" => "new_field"]
#写法2,使用大括号{}括起来
rename => { "old_field" => "new_field" }
}
}
●添加字段
filter {
mutate {
add_field => {
"f1" => "field1"
"f2" => "field2"
}
}
}
●将字段删除
filter {
mutate {
remove_field => ["message", "@version", "tags"]
}
}
●将filedName1字段数据类型转换成string类型,filedName2字段数据类型转换成float类型
filter {
mutate {
#写法1,使用中括号括起来
convert => ["filedName1", "string"]
#写法2,使用大括号{}括起来
convert => { "filedName2" => "float" }
}
}
●将filedName字段中所有"/“字符替换为”_"
filter {
mutate {
gsub => ["filedName", "/" , "_"]
}
}
●将filedName字段中所有",“字符后面添加空格
filter {
mutate {
gsub => ["filedName", "," , ", "]
}
}
●将filedName字段以"|"为分割符拆分数据成为数组
filter {
mutate {
split => ["filedName", "|"]
}
}
●合并 “filedName1” 和 “ filedName2” 两个字段
filter {
merge { "filedName2" => "filedName1" }
}
●用新值替换filedName字段的值
filter {
mutate {
replace => { "filedName" => "new_value" }
}
}
●添加字段first,值为message数组的第一个元素的值
filter {
mutate {
split => ["message", "|"]
add_field => {
"first" => "%{[message][0]}"
}
}
}
●有条件的添加标签
filter {
#在日志文件路径包含 access 的条件下添加标签内容
if [path] =~ "access" {
mutate {
add_tag => ["Nginx Access Log"]
}
}
#在日志文件路径是 /var/log/nginx/error.log 的条件下添加标签内容
if [path] == "/var/log/nginx/error.log" {
mutate {
add_tag => ["Nginx Error Log"]
}
}
}
数据源
-
示例1
-
示例2
multiline 多行合并插件
java错误日志一般都是一条日志很多行的,会把堆栈信息打印出来,当经过 logstash 解析后,每一行都会当做一条记录存放到 ES, 那这种情况肯定是需要处理的。 这里就需要使用 multiline 插件,对属于同一个条日志的记录进行拼接。
2022-11-11 17:09:19.774[XNIo-1 task-1]ERROR com.passjava.controlle .NembercController-查询用户 活动数据失败,异常信息为:
com.passjava.exception.MemberException: 当前没有配置活动规则
at com.passjava.service.impL.queryAdmin(DailyServiceImpl.java:1444)
at com.passjava.service.impl.dailyserviceImpL$$FastcLass
2022-11-11 17:10:56.256][KxNIo-1 task-1] ERROR com.passjava.controlle .NemberControl1er-查询员工 饭活动数据失败,异常信息为:
com.passjava.exception.MemberException: 当前没有配置活动规则
at com.passjava.service.impL.queryAdmin(DailyServiceImpl.java:1444)
at com.passjava.service.impL.daiLyserviceImpL$$FastcLass
- 安装 multiline 插件
在线安装插件
cd /usr/share/logstash
bin/logstash-plugin install logstash-filter-multiline
离线安装插件
先在有网的机器上在线安装插件,然后打包,拷贝到服务器,执行安装命令
bin/logstash-plugin prepare-offline-pack --overwrite --output logstash-filter-multiline.zip logstash-filter-multiline
bin/logstash-plugin install file:///usr/share/logstash/logstash-filter-multiline.zip
检查下插件是否安装成功,可以执行以下命令查看插件列表
bin/logstash-plugin list
- 使用 multiline 插件
第一步:每一条日志的第一行开头都是一个时间,可以用时间的正则表达式匹配到第一行。
第二步:然后将后面每一行的日志与第一行合并。
第三步:当遇到某一行的开头是可以匹配正则表达式的时间的,就停止第一条日志的合并,开始合并第二条日志。
第四步:重复第二步和第三步。
pattern:用来匹配文本的表达式,也可以是grok表达式
●what:如果pattern匹配成功的话,那么匹配行是归属于上一个事件,还是归属于下一个事件。previous: 归属于上一个事件,向上合并。next: 归属于下一个事件,向下合并
●negate:是否对pattern的结果取反。false:不取反,是默认值。true:取反。将多行事件扫描过程中的行匹配逻辑取反(如果pattern匹配失败,则认为当前行是多行事件的组成部分)
date 时间处理插件
用于分析字段中的日期,然后使用该日期或时间戳作为事件的logstash时间戳。
在Logstash产生了一个Event对象的时候,会给该Event设置一个时间,字段为“@timestamp”,同时,我们的日志内容一般也会有时间,但是这两个时间是不一样的,因为日志内容的时间是该日志打印出来的时间,而“@timestamp”字段的时间是input插件接收到了一条数据并创建Event的时间,所有一般来说的话“@timestamp”的时间要比日志内容的时间晚一点,因为Logstash监控数据变化,数据输入,创建Event导致的时间延迟。这两个时间都可以使用,具体要根据自己的需求来定。
现在我们想转换时间,那就要写出"dd/MMM/yyyy:HH:mm:ss Z"
你发现中间有三个M,你要是写出两个就不行了,因为两个大写的M表示两位数字的月份,可是我们要解析的文本中,月份则是使用简写的英文,所以只能去找三个M。还有最后为什么要加上个大写字母Z,因为要解析的文本中含有“+0800”时区偏移,因此我们要加上去,否则filter就不能正确解析文本数据,从而转换时间戳失败。
filter{
grok{
match => {"message" => ".* -\ -\ \[%{HTTPDATE:timestamp}\]"}
}
date{
match => ["timestamp","dd/MMM/yyyy:HH:mm:ss Z"]
}
}
运行结果:
{
"host" => "localhost",
"timestamp" => "07/Feb/2022:16:24:19 +0800",
"@timestamp" => 2022-02-07T08:24:19.000Z,
"message" => "192.168.80.10 - - [07/Feb/2022:16:24:19 +0800] \"GET /HTTP/1.1\" 403 5039",
"@version" => "1"
}
在上面那段rubydebug编码格式的输出中,@timestamp字段虽然已经获取了timestamp字段的时间,但是仍然比北京时间晚了8个小时,这是因为在Elasticsearch内部,对时间类型字段都是统一采用UTC时间,而日志统一采用UTC时间存储,是国际安全、运维界的一个共识。其实这并不影响什么,因为ELK已经给出了解决方案,那就是在Kibana平台上,程序会自动读取浏览器的当前时区,然后在web页面自动将UTC时间转换为当前时区的时间。
grok正则插件
Grok是logstash最主要的过滤插件,grok是通过系统预定义的正则表达式或者通过自己定义正则表达式来匹配日志中的各个值,安装了logstash后默认会有一些常用软件的日志匹配正则,在使用时自己可以根据自己的日志格式或者对匹配正则进行调整或者直接调用。如果,自己想在其他目录定义正则规则匹配日志,在使用时需要指定正则的路径。
对于以下一行日志:
55.3.244.1 GET /index.html 15824 0.043
使用如下的规则:
%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration}
grok配置示例如下:
filter {
grok {
match => { "message" => "%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration}" }
}
}
那么这行日志经过grok之后会得到以下的field:
client: 55.3.244.1
method: GET
request: /index.html
bytes: 15824
duration: 0.043
常用的配置选项:
- match:用来对字段的模式进行匹配
- patterns_dir:用来指定规则的匹配路劲,如果使用logstash自定义的规则时,不需要写此参数。Patterns_dir可以同时制定多个存放过滤规则的目录。语法格式:patterns_dir => [“/ opt / logstash / patterns”,“/ opt / logstash / extra_patterns”]
- remove_field:如果匹配到某个”日志字段,则将匹配的这个日志字段从这条日志中删除
Grok过滤正则规则可以自己根据自己的日志格式自行编写,在编写grok过滤规则时容易出错,此时可以使用grokdebug网站对自己的日志及编写的正则规则进行调试,grokdebug网址为(https://grokdebug.herokuapp.com/)
3.output插件
和前面介绍的input插件一样,output插件也是最基础最简单的输出插件。在《使用EFK快速搭建安全可靠的日志服务》一文中我们使用的elasticsearch作为最终的输出存储,因此output插件使用的是elasticsearch。对于grok解析失败的文件会写入到本地文件中,因此用了file插件,通过分支进行判断。示例如下:
output {
if "_grokparsefailure" in [tags] or "_jsonparsefailure" in [tags] {
file {
path => "/home/work/logstash/failure_output/failure-%{+YYYY-MM-dd}.log"
}
} else {
elasticsearch {
hosts => ["https://es-host1:9920","https://es-host2:9920","https://es-host3:9920"]
index => "logstash-%{[@metadata][index_name]}-%{+YYYY.MM.dd}"
document_id => "%{[@metadata][document_id]}"
ssl => true
ssl_certificate_verification => true
truststore => "/home/work/certificate/truststore.jks"
truststore_password => "adofkoe"
user => "logstash"
password => "dafodmfkamkefadfg"
}
}
}
除了elasticsearch,还支持以下输出:
- file
- influxdb
- mongodb
- redis