33.logstash

0.组件

input
  • stdin插件:从标准输入读取事件
input {
    stdin {
        add_field => {"key" => "value"}
        codec => "plain"
        type => "std"
        tags => ["test"]
    }
}
  • add_field:事件中添加一个字段
  • codec:codec是一个编解码器,在输入前对数据进行编解码,无需在filter中使用特定的插件处理
  • type:加上一个类型字段,用来标记事件类型
  • tags:标记事件的某方面属性。这是一个数组,一个事件可以有多个标签。
  • file插件:

Logstash 使用一个名叫FileWatch的Ruby Gem库来监听文件变化。这个库支持 glob 展开文件路径,而且会记录一个叫 .sincedb 的数据库文件来跟踪被监听的日志文件的当前读取位置。所以,不要担心 logstash 会漏过你的数据。sincedb文件中记录了每个被监听的文件的 inode number, major device number, minor device number和byte offset。

input {
    file {
        path => "/var/log/test.log"
        type => "test"
        sincedb_path => "/tmp/.sincedb_test"
        start_positon => "beginning"
    }
}
  • path:文件路径,可使用通配符,如/var/log/*.log,/var/**/*.log(**表示递归所有子目录)
  • type:加上一个类型字段,用来标记事件类型
  • sincedb_path:定义sincedb文件的位置(默认在用户家目录下,只能是beginning,end)
  • start_position:从什么位置开始读取文件数据,默认是结束位置
file {
        #监听文件的路径
        path => ["E:/software/logstash-1.5.4/logstash-1.5.4/data/*","F:/test.txt"]
        #排除不想监听的文件
        exclude => "1.log"
        
        #添加自定义的字段
        add_field => {"test"=>"test"}
        #增加标签
        tags => "tag1"

        #设置新事件的标志
        delimiter => "\n"

        #设置多长时间扫描目录,发现新文件
        discover_interval => 15
        #设置多长时间检测文件是否修改
        stat_interval => 1

         #监听文件的起始位置,默认是end
        start_position => beginning

        #监听文件读取信息记录的位置
        sincedb_path => "E:/software/logstash-1.5.4/logstash-1.5.4/test.txt"
        #设置多长时间会写入读取的位置信息
        sincedb_write_interval => 15
        
    }

  

  • kafka插件:该插件从kafka中的topic中读取事件
input {
    kafka {
        zk_connect => "xxx:2181,xxx:2181,xxx:2181"
        topic_id => "command_audit_log"
        codec => "json"
        consumer_threads => 5
        type => "command-audit"
    }
}
  • zk_connect:zookeeper的主机名和端口
  • topic_id: 指定消费主题
  • consumer_threads:定义分区读取数据的线程数
output
  • stdout插件:一个简单的打印输出,多用来进行debug
output {
    stdout {
        codec => rubydebug
        workers => 2
    }
}

  

  • workers:多线程输出
  • rubydebug使用ruby的Awesome打印库打印事件输出
  • elasticsearch插件:使用http协议将事件写入elasticsearch
output {
    elasticsearch {
        hosts => ["xxx:9200", "xxx:9200"]
        index => "logstash-%{type}-%{+YYYY.MM.dd}"
        workers => 2
        flush_size => 20000
        idle_flush_time => 10
    }
}
  • hosts:连接elasticsearch服务器
  • index:写入elasticsearch的索引名。这里可以使用变量。为了更贴合日志场景,Logstash 提供了 %{+YYYY.MM.dd} 这种写法。在语法解析的时候,看到以 + 号开头的,就会自动认为后面是时间格式,尝试用时间格式来解析后续字符串。所以,之前处理过程中不要给自定义字段取个加号开头的名字。此外,注意索引名中不能有大写字母,否则 ES 在日志中会报 InvalidIndexNameException,但是 Logstash 不会报错,这个错误比较隐晦。
  • flush_size 和 idle_flush_time 共同控制 Logstash 向 Elasticsearch 发送批量数据的行为。以上面示例来说:Logstash 会努力攒到 20000 条数据一次性发送出去,但是如果 10 秒钟内也没攒够 20000 条,Logstash 还是会以当前攒到的数据量发一次。默认情况下,flush_size 是 500 条,idle_flush_time 是 1 秒。这也是很多人改大了 flush_size也没能提高写入 ES 性能的原因——Logstash 还是 1 秒钟发送一次。
  • Logstash 在有多个 conf 文件的情况下,进入 ES 的数据会重复,几个 conf 数据就会重复几次,这是因为output 段顺序执行,没有对日志进行type判断的各插件配置都会全部执行一次。所以如果有多个conf文件,在 output 段对 type 进行判断,语法如下所示:
output {
    if [type] == "test" {
        elasticsearch { }
    }
}

  

  • kafka插件:使用http协议将事件写入elasticsearch
output {
    if [type] == "test" {
        kafka {
            bootstrap_servers => "xxx:9092,xxx:9092,xxx:9092"
            topic_id => "command_audit_log"
            compression_type => "snappy"
        }
    }
}

  

  • bootstrap_servers:kafka server的地址
  • topic_id:生成消息的话题(必填项)
  • compression_type:压缩类型(snappy,gzip,none)
  • 该插件默认的codec为json,所以事件将以json的格式导入,如果配置codec为plain,logstash除了编码messages外,还会添加timestamp和hostname的字段,如果只想输出message信息,配置如下output:
output {
    kafka {
        codec => plain {
        format => "%{message}"
        }
    }
}
filter插件
  • grok插件:通过正则解析任意文本,将非结构化日志数据弄成结构化和方便查询的结构
filter {
    grok {
        match => {
            "message" => "%{IPORHOST:clientip} - %{NOTSPACE:remote_user} \[%{HTTPDATE:timestamp}\] \"%{WORD:method} %{NOTSPACE:request} %{URIPROTO:proto}/%{NUMBER:httpversion}\" %{NUMBER:status} (?:%{NUMBER:size}|-) %{QS:referrer} %{QS:agent}"
        }
    }
}

多个匹配

match => [
    "message", "(?<request_time>\d+(?:\.\d+)?)",
    "message", "%{SYSLOGBASE} %{DATA:message}",
    "message", "(?m)%{WORD}"
]
  • date插件:从日志中解析时间,然后使用该时间作为logstash的事件时间戳
date {
        match => [ "timestamp" , "yyyy-MM-dd HH:mm:ss" ]
        timezone => "+08:00"
    }
  • mutate插件:提供了丰富的基础类型数据处理能力,包括类型转换,字符串处理和字段处理等

------转换类型:mutate可以设置的转换类型包括:"integer","float" 和 "string"

filter {
    mutate {
        covert => ["filed_name", "integer"]
    }
}
# 如果有多个字段需要转换可使用如下方法:
covert => ["filed_name_1", "integer", "filed_name_2", "float", "filed_name_3", "string"]

------字符串处理

gsub通过正则表达式替换匹配的值,只对字符串有效,每个替换包括3个元素的数组,分别对应字段名,正则匹配表达式,替换的值。

filter {
    mutate {
        gsub => [
            #将filed_name_1字段中所有"/"转换为"_"
            "filed_name_1", "/" , "_",
            # 将filed_name_2字段中所有"\","?","#","-"转换为"."
            "filed_name_2", "[\\?#-]", "."
        ]
    }
}

split通过特定的分隔符分割字符串为数组

filter {
    mutate {
        split => {"filed_name_1", "|"}
    }
}

join通过特定分隔符将数组元素拼接起来

filter {
    mutate {
        join => {"filed_name_1", "|"}
    }
}

merge合并两个数组或者哈希字段

filter {
    mutate {
        merge => {"filed_name_1" => "filed_name_2"}
    } 
}

strip去除字段中开头结尾的空格

filter {
    mutate {
        strip => ["filed_name_1", "filed_name_2"]
    }
}

------字段处理

rename重命名某个字段

filter {
    mutate {
        rename => {"old_field" => "new_field"}
    }
}

update更新某个字段的内容。如果字段不存在,不会新建。

filter {
    mutate {
        update => {"field_name" => "new message"}
    }
}

replace作用和 update 类似,但是当字段不存在的时候,它会起到add_field参数一样的效果,自动添加新的字段  

  • geoip插件:

GeoIP 是最常见的免费 IP 地址归类查询库,同时也有收费版可以采购。GeoIP 库可以根据 IP 地址提供对应的地域信息,包括国别,省市,经纬度等,对于可视化地图和区域统计非常有用。

filter {
    geoip {
        source => "ip_field"
    }
}

GeoIP 库数据较多,如果你不需要这么多内容,可以通过 fields 选项指定自己所需要的。下例为全部可选内容:

filter {
    geoip {
        fields => ["city_name", "continent_code", "country_code2", "country_code3", "country_name", "dma_code", "ip", "latitude", "longitude", "postal_code", "region_name", "timezone"]
    }
}

logstash会通过 latitude 和 longitude 额外生成geoip.location,用于地图定位

geoip库内只存有公共网络上的IP信息,查询不到结果的,会直接返回 null,而 logstash 的 geoip 插件对 null 结果的处理是:不生成对应的 geoip.字段。

  • kv插件:该插件用于自动解析类似于foo=bar类型的数据
input { stdin { type => "kv" } }
filter {
    if [type] == "kv" {
        kv {
            source => "message"
            prefix => "ex_"
            field_split => "&? "
            allow_duplicate_values => false
            default_keys => {
                "from" => "A"
                "to" => "B"
            }
            trim => "<>\[\],"
            trimkey => "<>\[\],"
            value_split => "=:"
        }
    }
}
  • source为数据源,需要解析的数据,可以是字段等
  • prefix给所有解析出来的字段加上一个前缀
  • field_split解析出键值对的分隔符
  • allow_duplicate_values布尔类型,是否删除重复的键值对。默认值true,不删除重复键值
  • default_keys增加默认的键值对到事件中,以防源数据解析后不存在这些键值
  • trim去除解析后value里面包含的小括号或者中括号等符号
  • trimkey去除解析后key里面包含的小括号或者中括号等符号
  • value_split设置键值识别关系的分隔符,默认为=

  

结合例子中的配置来解释:

配置中通过'&','?'和' '作为字段分隔符,通过'='和':'作为键值分隔符,数据解析后应该为:

<a: [,9]

b>=,34,

b:34]

[c]=<123>

然后去除key和value中的'[',']','<','>'和','得到:

"a" => "9"

"b" => "34"

"b" => "34"

"c" => "123"

 然后去除重复的键值对,并且添加前缀ex_得到:

"ex_a" => "9"

"ex_b" => "34"

"ex_c" => "123"

最后增加默认key得到:

"from“ => "A"

"to" => "B"

"ex_a" => "9"

"ex_b" => "34"

"ex_c" => "123"

 

1.参考网址

https://www.elastic.co/guide/en/logstash/current/filter-plugins.html

http://www.cnblogs.com/stozen/p/5638369.html

http://www.cnblogs.com/xing901022/p/4805586.html

http://zengestudy.blog.51cto.com/1702365/1832820

http://www.jianshu.com/p/6575041b597d

http://loveltyoic.github.io/blog/2016/01/08/logstash/

posted @ 2017-10-19 21:20  桃源仙居  阅读(1344)  评论(0)    收藏  举报