tweeeetyのぶろぐ的めも

アウトプットが少なかったダメな自分をアウトプット<br>\(^o^)/

fluentd(td-agent)のtailプラグインとかのformat正規表現を作ってみるメモ

はじめに

fluentd(td-agent)を使ってin_tailでapacheaccessログformat正規表現を作ってみるメモです。
おおよそ先人の方々がいろいろ残してくださった情報のまんまではありますが。。

formatに指定する正規表現がすんなりうまくいかなくて
こちらを参考にほぼ同じような感じで試してみました。

補足

そんなにテクニカルでも有用でもないカモですがこちらにメモまとめをメモっておきました
td-agent(fluentd)を本番サ―ビスで小さく使ってみたメモ-まとめ

てことで、

ながれ

1.tailしたいaccessログ
2.format正規表現スクリプト
3.スクリプトでやってみた完成系とちょこっとメモ
4.tail(とかtail_ex)プラグインに指定する

って感じでメモ


1.tailしたいaccessログ

試したい環境についてはこんな感じです

諸情報
# cat /etc/redhat-release
CentOS release 6.4 (Final)

# /usr/local/apache2.4/bin/apachectl -v
Server version: Apache/2.4.4 (Unix)
Server built:   Apr 24 2013 16:50:43
httpd.confのfromat指定

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined

accessログ

実際に出力されるログはこんな感じ

172.21.65.11 - - [07/Jan/2014:16:09:26 +0900] "GET /mypage HTTP/1.1" 302 - "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.33 Safari/535.11" 8832
172.21.65.11 - - [07/Jan/2014:16:09:26 +0900] "GET / HTTP/1.1" 200 22660 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.33 Safari/535.11" 150183
172.21.65.11 - - [07/Jan/2014:16:09:30 +0900] "GET /js/libs/jquery.enqt.js HTTP/1.1" 200 4135 "http://hoge.piyo.jp/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.33 Safari/535.11" 282
172.21.65.11 - - [07/Jan/2014:16:09:30 +0900] "GET /css/main.css HTTP/1.1" 200 3098 "http://hoge.piyo.jp/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.33 Safari/535.11" 17479
172.21.65.11 - - [07/Jan/2014:16:09:30 +0900] "GET /img/top/logo.png HTTP/1.1" 200 50999 "http://hoge.piyo.jp/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.33 Safari/535.11" 242440

2.format正規表現スクリプト

参考にさせて頂いたサイトまんまですがこんな感じでスクリプトを作りました

  • vi /etc/td-agent/script/log_format_test.rb
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-

require 'time'
require 'fluent/log'
require 'fluent/config'
require 'fluent/engine'
require 'fluent/parser'

$log ||= Fluent::Log.new

# debug
log = '172.21.65.11'
format = /^(?<host>[^ ]+)$/
#time_format = '%d/%b/%Y:%T %z'
time_format = ''

parser = Fluent::TextParser::RegexpParser.new(format, 'time_format' => time_format)
result = parser.call(log)
puts result[0]
puts result[1]
puts Time.at(result[0])

log = '172.21.65.11'
format = /^(?.+)$/
の部分を最終的なログフォーマットに合わせて
少しずつ文字列を増やしながらテスト実行って感じです。

  • 実行結果
# /usr/lib64/fluent/ruby/bin/ruby /etc/td-agent/script/log_format_test.rb
1389087711
{"host"=>"172.21.65.11"}
2014-01-07 18:41:51 +0900

3.スクリプトでやってみた完成系とちょこっとメモ

#!/usr/bin/env ruby
# -*- coding: utf-8 -*-

require 'time'
require 'fluent/log'
require 'fluent/config'
require 'fluent/engine'
require 'fluent/parser'

$log ||= Fluent::Log.new

# debug
log = '172.21.65.11 - - [07/Jan/2014:16:09:26 +0900] "GET /mypage HTTP/1.1" 302 - "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.33 Safari/535.11" 8832'
format = /^(?<host>[^ ]+) [^ ]+ [^ ]+ \[(?<time>[^\]]+)\] "(?<request>[^ ]+ [^ ]+ [^ ]+)" (?<code>[^ ]+) .+ ".+" "(?<ua>.+)" (?<latency>[^ ]+)$/
time_format = '%d/%b/%Y:%T %z'

parser = Fluent::TextParser::RegexpParser.new(format, 'time_format' => time_format)
result = parser.call(log)
puts result[0]
puts result[1]
puts Time.at(result[0])
  • 結果
# /usr/lib64/fluent/ruby/bin/ruby /etc/td-agent/script/log_format_test.rb
1389078566
{"host"=>"172.21.65.11", "request"=>"GET /mypage HTTP/1.1", "code"=>"302", "ua"=>"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.33 Safari/535.11", "latency"=>"8832"}
2014-01-07 16:09:26 +0900
ちょこっとメモ
  • hostのとこ

(?[^ ]+)

rubyの正規表現なんかを見てもらうとより詳しくのってたりしますが「名前付きキャプチャ」を使ってます
この例でいうと、hostという名前尽きキャプチャでパースされたものがjsonになった際に

{host:xxx.xxx.xxx.xxx}

となります。

  • timeのとこ

\[(?

正規表現的にはhostのとこと同じで名前付きキャプチャを使ってます。
日時をかこってる[]ははぶいた状態で日時文字列をパースしたいので
\[と\]で囲った中身に名前付きキャプチャになってます。

また完成系のスクリプトの結果を見てもらうとわかるとおり、timeというjsonキー名は出力されません。
\[(?[^\]]+)\]とかにすれば出力されるjsonのkey:valueとして入ります。

補足

\[(?

format を自ら設定した場合には、必ず time_format ディレクティブが必要です。普段 format の指定に apache を指定している場合には、fluentd が気を利かせて time_format を暗黙的に設定してくれるので、注意が必要です。

参照:Apache ログを転送するための fluentd 初期設定
とのことなので今回のスクリプトで日付文字列もちゃんとパースしておいて
後でtime_formatに指定する感じになります。

rubyの日付フォーマットについてはこちらが参考になりました。
ruby 正規表現

4.tail(とかtail_ex)プラグインに指定する

td-agent.confはこんな感じ

<source>
  type tail_ex
  format /^(?<host>[^ ]+) [^ ]+ [^ ]+ \[(?<time>[^\]]+)\] "(?<request>[^ ]+ [^ ]+ [^ ]+)" (?<code>[^ ]+) .+ ".+" "(?<ua>.+)" (?<latency>[^ ]+)$/
  time_format %d/%b/%Y:%T %z
  read_all true
  path /apache/logs/access_log.%Y-%m-%d
  pos_file /var/log/td-agent/pos/access_log.pos
  tag apache.access
</source>