logstashパイプラインには、入力と出力の2つの必須要素と、オプションの要素であるfilterが含まれています。
(フィルターの解析と処理の後)入力からイベントソースを読み取り、出力からターゲットリポジトリ(elasticsearchまたはその他)に出力します。
実稼働環境でlogstashを使用するには、通常、構成を使用してファイルを書き込んでから、logstashを開始します。
詳細については、公式Webサイトを参照してください:https://www.elastic.co/guide/en/logstash/7.1/index.html
nginxログを処理する
#vim nginx_access.conf
input{
file{
path => "/var/log/nginx/access.log"
start_position => "beginning"
type => "nginx_access_log"
}
}
filter{
grok{
match => {"message" => "%{IPORHOST:clientip} %{USER:ident} %{USER:auth} \[%{HTTPDATE:timestamp}\] \"%{WORD:verb} %{DATA:request} HTTP/%{NUMBER:httpversion}\" %{NUMBER:response:int} (?:-|%{NUMBER:bytes:int}) \"(?:-|%{DATA:referrer})\" \"%{DATA:user_agent}\" (?:%{IP:proxy}|-) %{DATA:upstream_addr} %{NUMBER:upstream_request_time:float} %{NUMBER:upstream_response_time:float}"}
match => {"message" => "%{IPORHOST:clientip} %{USER:ident} %{USER:auth} \[%{HTTPDATE:timestamp}\] \"%{WORD:verb} %{DATA:request} HTTP/%{NUMBER:httpversion}\" %{NUMBER:response:int} (?:-|%{NUMBER:bytes:int}) \"%{DATA:referrer}\" \"%{DATA:user_agent}\" \"%{DATA:proxy}\""}
}
if [request] {
urldecode {
field => "request"
}
ruby {
init => "@kname = ['url_path','url_arg']"
code => "
new_event = LogStash::Event.new(Hash[@kname.zip(event.get('request').split('?'))])
event.append(new_event)"
}
if [url_arg] {
ruby {
init => "@kname = ['key', 'value']"
code => "event.set('url_args', event.get('url_arg').split('&').collect {|i| Hash[@kname.zip(i.split('='))]})"
}
}
}
geoip{
source => "clientip"
}
useragent{
source => "user_agent"
target => "ua"
remove_field => "user_agent"
}
date {
match => ["timestamp","dd/MMM/YYYY:HH:mm:ss Z"]
locale => "en"
}
mutate{
remove_field => ["message","timestamp","request","url_arg"]
}
}
output{
elasticsearch {
hosts => "localhost:9200"
index => "nginx-access-log-%{+YYYY.MM.dd}"
}
# stdout {
# codec => rubydebug
# }
}
構成ファイルが正しく書き込まれているかどうかをテストする場合は、次の方法を使用してテストを開始します
/usr/share/logstash/bin/logstash -t -f /etc/logstash/conf.d/nginx.conf #测试配置文件
Configuration OK
/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/nginx_access.conf #启动logstash
logstashを開始します
#systemctl start logstash
入力プラグインを 使用すると、logstashは特定のイベントソースを読み取ることができます。
公式ウェブサイト:https://www.elastic.co/guide/en/logstash/current/input-plugins.html
イベントソースは、stdin画面入力、fileで指定されたファイル、またはes、filebeat、kafka、redisなどから読み取ることができます。
- stdin 標準入力
- ファイルはファイル からデータを読み取ります
file{ path => ['/var/log/nginx/access.log'] #要输入的文件路径 type => 'nginx_access_log' start_position => "beginning" } # path 可以用/var/log/*.log,/var/log/**/*.log,如果是/var/log则是/var/log/*.log # type 通用选项. 用于激活过滤器 # start_position 选择logstash开始读取文件的位置,begining或者end。 还有一些常用的例如:discover_interval,exclude,sincedb_path,sincedb_write_interval等可以参考官网
- syslogは、 システムログメッセージをネットワーク経由のイベントとして読み取ります
syslog{ port =>"514" type => "syslog" } # port 指定监听端口(同时建立TCP/UDP的514端口的监听) #从syslogs读取需要实现配置rsyslog: # cat /etc/rsyslog.conf 加入一行 *.* @172.17.128.200:514 #指定日志输入到这个端口,然后logstash监听这个端口,如果有新日志输入则读取 # service rsyslog restart #重启日志服务
- ビート はElasticビートからイベントを受け取ります
beats { port => 5044 #要监听的端口 } # 还有host等选项 # 从beat读取需要先配置beat端,从beat输出到logstash。 # vim /etc/filebeat/filebeat.yml .......... output.logstash: hosts: ["localhost:5044"]
- Kafka はKafkaトピックのデータをイベントとして読み取ります
kafka{ bootstrap_servers=> "kafka01:9092,kafka02:9092,kafka03:9092" topics => ["access_log"] group_id => "logstash-file" codec => "json" } kafka{ bootstrap_servers=> "kafka01:9092,kafka02:9092,kafka03:9092" topics => ["weixin_log","user_log"] codec => "json" } # bootstrap_servers 用于建立群集初始连接的Kafka实例的URL列表。 # topics 要订阅的主题列表,kafka topics # group_id 消费者所属组的标识符,默认为logstash。kafka中一个主题的消息将通过相同的方式分发到Logstash的group_id # codec 通用选项,用于输入数据的编解码器。
入力プラグインには多くの種類があり、公式ドキュメントを参照して構成できます。
フィルタプラグインフィルタプラグイン、イベントの中間処理を実行します
- grok はテキストを解析し、構築します。定期的な分析を通じて、非構造化ログデータを構造化されたクエリ可能なデータに解析します
grok { match => {"message"=>"^%{IPORHOST:clientip} %{USER:ident} %{USER:auth} \[%{HTTPDATE:timestamp}\] "%{WORD:verb} %{DATA:request} HTTP/%{NUMBER:httpversion}" %{NUMBER:response:int} (?:-|%{NUMBER:bytes:int}) %{QS:referrer} %{QS:agent}$"} } 匹配nginx日志 # 203.202.254.16 - - [22/Jun/2018:16:12:54 +0800] "GET / HTTP/1.1" 200 3700 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/601.7.7 (KHTML, like Gecko) Version/9.1.2 Safari/601.7.7" #220.181.18.96 - - [13/Jun/2015:21:14:28 +0000] "GET /blog/geekery/xvfb-firefox.html HTTP/1.1" 200 10975 "-" "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"
- grokには複数の一致一致ルールを含めることができることに注意してください。前の一致が失敗した場合は、以下を使用して一致を続行できます。例えば
grok { match => ["message", "%{IP:clientip} - %{USER:user} \[%{HTTPDATE:raw_datetime}\] \"(?:%{WORD:verb} %{URIPATHPARAM:request} HTTP/%{NUMBER:httpversion})\" (?:\"%{DATA:body}\" )?(?:\"%{DATA:cookie}\" )?%{NUMBER:response} (?:%{NUMBER:bytes:int}|-) \"%{DATA:referrer}\" \"%{DATA:agent}\" (?:(%{IP:proxy},? ?)*|-|unknown) (?:%{DATA:upstream_addr} |)%{NUMBER:request_time:float} (?:%{NUMBER:upstream_time:float}|-)"] match => ["message", "%{IP:clientip} - %{USER:user} \[%{HTTPDATE:raw_datetime}\] \"(?:%{WORD:verb} %{URI:request} HTTP/%{NUMBER:httpversion})\" (?:\"%{DATA:body}\" )?(?:\"%{DATA:cookie}\" )?%{NUMBER:response} (?:%{NUMBER:bytes:int}|-) \"%{DATA:referrer}\" \"%{DATA:agent}\" (?:(%{IP:proxy},? ?)*|-|unknown) (?:%{DATA:upstream_addr} |)%{NUMBER:request_time:float} (?:%{NUMBER:upstream_time:float}|-)"] }
grok構文:%{SYNTAX:SEMANTIC}は%{regular:カスタムフィールド名}を意味します
公式には、直接使用できる通常のgrokパターンが多数用意されています:https://github.com/logstash-plugins/logstash-patterns-core/blob/master/patterns
grokデバッグツール:http://grokdebug.herokuapp.com
正規表現デバッグツール:https://www.debuggex.com/
より定期的な知識を使用する必要があります。参照ドキュメントは次のとおりです。https://www.jb51.net/tools/zhengze.html
カスタムパターン:(?<フィールド名>パターン)
例:match 2018/06/27 14:00:54
(?<日時> \ d \ d \ d \ d \ / \ d \ d \ / \ d \ d \ d \ d:\ d \ d:\ d \ d)
結果を取得します: "datetime": "2018/06/27 14:00:54"
- 日付日付の解析フィールドの日付を解析してから、@ timestampにダンプします
[2018-07-04 17:43:35,503] grok{ match => {"message"=>"%{DATA:raw_datetime}"} } date{ match => ["raw_datetime","YYYY-MM-dd HH:mm:ss,SSS"] remove_field =>["raw_datetime"] } #将raw_datetime存到@timestamp 然后删除raw_datetime #24/Jul/2018:18:15:05 +0800 date { match => ["timestamp","dd/MMM/YYYY:HH:mm:ss Z] }
- Mutateはフィールドを処理し、フィールドの名前を変更、削除、置換、および変更します。
- 秘密の 型変換。タイプには、integer、float、integer_eu、float_eu、string、およびbooleanが含まれます。
filter{ mutate{ # covert => ["response","integer","bytes","float"] #数组的类型转换 convert => {"message"=>"integer"} } } #测试-------> { "host" => "localhost", "message" => 123, #没带“”,int类型 "@timestamp" => 2018-06-26T02:51:08.651Z, "@version" => "1" }
- split は、区切り文字を使用して文字列を配列に分割します
mutate{ split => {"message"=>","} } #----------> aaa,bbb { "@timestamp" => 2018-06-26T02:40:19.678Z, "@version" => "1", "host" => "localhost", "message" => [ [0] "aaa", [1] "bbb" ]} 192,128,1,100 { "host" => "localhost", "message" => [ [0] "192", [1] "128", [2] "1", [3] "100" ], "@timestamp" => 2018-06-26T02:45:17.877Z, "@version" => "1" }
- マージ フィールドをマージします。配列と文字列、文字列と文字列
filter{ mutate{ add_field => {"field1"=>"value1"} } mutate{ split => {"message"=>"."} #把message字段按照.分割 } mutate{ merge => {"message"=>"field1"} #将filed1字段加入到message字段 } } #---------------> abc { "message" => [ [0] "abc," [1] "value1" ], "@timestamp" => 2018-06-26T03:38:57.114Z, "field1" => "value1", "@version" => "1", "host" => "localhost" } abc,.123 { "message" => [ [0] "abc,", [1] "123", [2] "value1" ], "@timestamp" => 2018-06-26T03:38:57.114Z, "field1" => "value1", "@version" => "1", "host" => "localhost" }
- 名前の 変更はフィールドの名前を変更します
filter{ mutate{ rename => {"message"=>"info"} } } #--------> 123 { "@timestamp" => 2018-06-26T02:56:00.189Z, "info" => "123", "@version" => "1", "host" => "localhost" }
- remove_field フィールドの削除
mutate { remove_field => ["message","datetime"] }
- join は、配列を区切り文字で接続します。配列でない場合、処理されません。
mutate{ split => {"message"=>":"} } mutate{ join => {"message"=>","} } ------> abc:123 { "@timestamp" => 2018-06-26T03:55:41.426Z, "message" => "abc,123", "host" => "localhost", "@version" => "1" } aa:cc { "@timestamp" => 2018-06-26T03:55:47.501Z, "message" => "aa,cc", "host" => "localhost", "@version" => "1" }
- 秘密の 型変換。タイプには、integer、float、integer_eu、float_eu、string、およびbooleanが含まれます。
-
- gsub は、フィールド値を通常または文字列に置き換えます。文字列にのみ有効
mutate{ gsub => ["message","/","_"] #用_替换/ } ------> a/b/c/ { "@version" => "1", "message" => "a_b_c_", "host" => "localhost", "@timestamp" => 2018-06-26T06:20:10.811Z }
- update はフィールドを更新します。フィールドが存在しない場合は、何もしません
mutate{ add_field => {"field1"=>"value1"} } mutate{ update => {"field1"=>"v1"} update => {"field2"=>"v2"} #field2不存在 不做处理 } ----------------> { "@timestamp" => 2018-06-26T06:26:28.870Z, "field1" => "v1", "host" => "localhost", "@version" => "1", "message" => "a" }
- replace はフィールドを更新します。フィールドが存在しない場合は、作成します
mutate{ add_field => {"field1"=>"value1"} } mutate{ replace => {"field1"=>"v1"} replace => {"field2"=>"v2"} } ----------------------> { "message" => "1", "host" => "localhost", "@timestamp" => 2018-06-26T06:28:09.915Z, "field2" => "v2", #field2不存在,则新建 "@version" => "1", "field1" => "v1" }
- gsub は、フィールド値を通常または文字列に置き換えます。文字列にのみ有効
- geoip は、Maxmind GeoLite2データベースからのデータに基づいて、IPアドレスの地理的位置に関する情報を追加します
geoip { source => "clientip" database =>"/tmp/GeoLiteCity.dat" }
- rubyruby プラグインは任意のRubyコードを実行できます
filter{ urldecode{ field => "message" } ruby { init => "@kname = ['url_path','url_arg']" code => " new_event = LogStash::Event.new(Hash[@kname.zip(event.get('message').split('?'))]) event.append(new_event)" } if [url_arg]{ kv{ source => "url_arg" field_split => "&" target => "url_args" remove_field => ["url_arg","message"] } } } # ruby插件 # 以?为分隔符,将request字段分成url_path和url_arg --------------------> www.test.com?test { "url_arg" => "test", "host" => "localhost", "url_path" => "www.test.com", "message" => "www.test.com?test", "@version" => "1", "@timestamp" => 2018-06-26T07:31:04.887Z } www.test.com?title=elk&content=学习elk { "url_args" => { "title" => "elk", "content" => "学习elk" }, "host" => "localhost", "url_path" => "www.test.com", "@version" => "1", "@timestamp" => 2018-06-26T07:33:54.507Z }
- urldecodeは 、エンコードされたフィールドをデコードするために使用されます。これにより、URLでの中国語の文字化けの問題を解決できます。
urldecode{ field => "message" } # field :指定urldecode过滤器要转码的字段,默认值是"message" # charset(缺省): 指定过滤器使用的编码.默认UTF-8
- kv は、区切り文字を指定して文字列をキー/値に分割します
kv{ prefix => "url_" #给分割后的key加前缀 target => "url_ags" #将分割后的key-value放入指定字段 source => "message" #要分割的字段 field_split => "&" #指定分隔符 remove_field => "message" } --------------------------> a=1&b=2&c=3 { "host" => "localhost", "url_ags" => { "url_c" => "3", "url_a" => "1", "url_b" => "2" }, "@version" => "1", "@timestamp" => 2018-06-26T07:07:24.557Z
- useragent は、ユーザーエージェントに関する情報(シリーズ、オペレーティングシステム、バージョン、デバイスなど)を追加します。
if [agent] != "-" { useragent { source => "agent" target => "ua" remove_field => "agent" } } # if语句,只有在agent字段不为空时才会使用该插件 #source 为必填设置,目标字段 #target 将useragent信息配置到ua字段中。如果不指定将存储在根目录中
logstash比較演算子
等しい:==、!=、<、>、<=、> =
通常:=〜、!〜(右側のパターンを左側の文字列値と照合します)
包含関係:in、not in
サポートされているブール演算子:and、or、nand、xor
サポートされている単項演算子:!
出力プラグイン出力プラグイン、特定のターゲットにイベントを送信します。
- stdout標準出力。画面にイベントを出力する
output { stdout { codec => "rubydebug" } }
- ファイルへのファイル書き込みイベント
file { path => "/ data / logstash /%{host} / {application} codec => line {format =>"%{message} "}} }
- Kafkaはkafkaにイベントを送信します
kafka { bootstrap_servers => "localhost:9092" topic_id => "test_topic"#必要な設定。生成されたメッセージの件名 }
- elasticseachはログをesに保存します
elasticsearch { hosts => "localhost:9200" index => "nginx-access-log-%{+ YYYY.MM.dd}" } #indexイベントが書き込まれるインデックス。ログに基づいてインデックスを作成できるため、古いデータを削除したり、時間でログを検索したりできます。
コーデックプラグインを追加するコーデックプラグイン
コーデックは本質的にストリームフィルタであり、入力または出力プラグインの一部として実行できます。たとえば、上記の出力のstdoutプラグインで役立ちます。
- 複数行コーデックプラグイン複数行のマージ、スタックログまたは改行文字を含むその他のログの処理を使用する必要があります
input { stdin { codec => multiline { pattern => "pattern, a regexp" #正则匹配规则,匹配到的内容按照下面两个参数处理 negate => "true" or "false" # 默认为false。处理匹配符合正则规则的行。如果为true,处理不匹配符合正则规则的行。 what => "previous" or "next" #指定上下文。将指定的行是合并到上一行或者下一行。 } } } codec => multiline { pattern => "^\s" what => "previous" } # 以空格开头的行都合并到上一行 codec => multiline { # Grok pattern names are valid! :) pattern => "^%{TIMESTAMP_ISO8601} " negate => true what => "previous" } # 任何不以这个时间戳格式开头的行都与上一行合并 codec => multiline { pattern => "\\$" what => "next" } # 以反斜杠结尾的行都与下一行合并