share facebook facebook2 twitter menu hatena pocket slack

2014.07.30 WED

HA Proxy 白帯シリーズ(5) HA Proxy 超小ネタ(3) 〜 ログ出力を fluentd を使って frontend セクション毎に異なるファイルに出力する 〜

川原 洋平

WRITTEN BY川原 洋平

どうも、かっぱ@inokara)です。

はじめに

HA Proxy のログは syslog を経由して下記のように一つの haproxy.log ファイルに出力していますが…

01

frontend セクションを複数設定している場合には frontend 毎にログを異なるファイルに分けれれば色々と嬉しいような気がしたので試してみました。


悩む

ググったところ rsyslog で頑張れや…的な情報しか見つからず、諦めようとしていた矢先にログを何とかしたいなら泣く子も黙る fluentd を使うことを思い付きました。処理の流れとしては以下のような流れにすることを目論んでいます。

02


やってみた

結果

  • 条件付きで出来ました

やり方

haproxy のログフォーマット

以下のような感じで Custom log format を使いました。

log-format %{+Q}o %{-Q}ci - - [%T] %r %ST %B "" "" %cp %ms %ft %b %s

ポイントは frontend の名前を意味する %ft を設定して frontend_name_transport をログに記録します。上記のフォーマットで以下のようなログが出力されます。フォーマットの詳しい解説はこちら

 xxx.xxx.xxx.xxx - - [27/Jul/2014:15:20:58 +0000] "GET /check HTTP/1.1" 200 293 "" "" 61819 734 "cluster1" "backend1" "web1"
in_tail プラグインの format

以下のような format を書きました。

format /^ +(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) [(?<timestamp>[^]]*)] "(?<method>S+)(?: +(?<path>[^ ]*) +S*)?" (?<code>[^ ]*) (?<size>[^ ]*) [^ ]* [^ ]* (?<client_port>[^ ]*) (?<accept_date_milliseconds>[^ ]*) "(?<frontend_name_transport>[^ ]*)" "(?<backend_name>[^ ]*)" "(?<server_name>[^ ]*)"$/

ポイントは

^ +(?<host>[^ ]*)

なぜか haproxy のログは行頭に半角スペースが入るようなので上記のように半角スペースを入れてあげます。後はシンプルにパターンマッチを重ねていくだけです。尚、format を書くにあたっては以下のサイトがとても役に立ちました。

有難うございます!

fluent-plugin-rewrite

今回は frontend 毎(frontend_name_transport 毎)にログ出力を分けるにあたっては以下のプラグインを利用させて頂きました。

fluent-plugin-rewrite を以下のように設定しました。

<match haproxy>
  type copy
  <store>
    type file
    path /tmp/haproxy.log
  </store>
  <store>
    type rewrite
    <rule>
      key           frontend_name_transport
      pattern       ^(cluster1)
      append_to_tag true
      fallback      others
    </rule>
  </store>
</match>

<match haproxy.cluster1>
  type file
  path /tmp/cluster1.log
</match>

<match haproxy.other>
  type file
  path /tmp/haproxy-other.log
</match>

挙動としては以下の通りです。

  1. in_tail プラグインでパースされたログには haproxy というタグが付く
  2. haproxy タグの付いたログは copy プラグインでファイル出力と rewrite フィルターによって処理される
  3. rewrite フィルターで key が frontend_name_transport で値に cluster1 が含まれるログを抽出
  4. 抽出したログに haproxy.cluster1 というタグを付けて emit する
  5. cluster1 にマッチしないログは haproxy.other というタグをつけて emit する

振り分けられたログ…

見てもどうこうってことはありませんが…

2014-07-27T15:20:58Z    haproxy.cluster1   {"host":"xxx.xxx.xxx.xxx","user":"-","timestamp":"27/Jul/2014:15:20:58 +0000","method":"GET","path":"/check","code":"200","size":"293","client_port":"61819","accept_date_milliseconds":"734","frontend_name_transport":"cluster1","backend_name":"backend","server_name":"web1"}

ちゃんと frontend_name_transport が cluster1 となっているログのみがログに記録されています。


という感じで

fluent-plugin-rewrite の rule で指定している frontend_name_transport のパターンを以下のような感じで追加していけば良さそうです。

pattern       ^(cluster1|cluster2|cluster3)

マジ、有難うございます…fluentd 様、様。

元記事は、こちら