2019年7月18日木曜日

JSON 形式のログが出力されるアプリを docker fluentd ドライバでパースする方法

概要

アプリによっては JSON のログを 1 行ごとに出力する場合があります
そんな JSON のログを docker の fluentd driver で処理する方法を紹介します

環境

  • macOS 10.14.5
  • docker 18.09.2

アプリ

JSON を 1 行ごとに出力すれば、なんでも OK です

  • vim app.rb
require 'logger'
require 'securerandom'

unless ENV['LOCAL'] == "true"
  $stdout = IO.new(IO.sysopen("/proc/1/fd/1", "w"), "w")
  $stdout.sync = true
  STDOUT = $stdout
end
logger = Logger.new(STDOUT)
logger.formatter = proc do |severity, datetime, progname, msg|
  %Q|{"timestamp": "#{datetime.to_s}", "message": "#{msg}"}\n|
end

loop do
  logger.info(SecureRandom.uuid)
  sleep(3)
end
  • ruby app.rb
{"timestamp": "2019-07-17 12:32:42 +0900", "message": "7947d912-4e97-4227-b49c-83e3ecb30e98"} {"timestamp": "2019-07-17 12:32:45 +0900", "message": "36d3af1e-803f-4e76-a9f2-40cb540d8a2d"}

こんな感じで出力されれば OK です

Dockerfile

あとはこれを docker 上で動作させるようにします

  • vim Dockerfile
FROM ruby

ADD . /home
WORKDIR /home

CMD ["ruby", "app.rb"]
  • docker build -t myapp .

fluentd コンテナ

特にプラグインはないので設定ファイルだけ作成します

  • vim fluent.conf
<source>
  @type forward
</source>

<filter docker.app>
  @type parser
  format json
  key_name log
  reserve_data true
</filter>

<match docker.app>
  @type stdout
</match>

ポイントは parser プラグインを使うところです
これで事前に JSON のログをパースします
ちなみにログは log というキーに詰め込まれているので key_namelog を指定します
reserve_data true にするとパースされる前のログもその残ります
不要であれば false を設定しましょう

あとはコンテナを起動すれば OK です

  • docker run --rm -p 24224:24224 -p 24224:24224/udp -v $(pwd)/fluent.conf:/fluentd/etc/fluent.conf -e FLUENTD_CONF=fluent.conf --name=fluentd fluent/fluentd

動作確認

まずアプリコンテナを起動しましょう

  • docker run -d --log-driver=fluentd --log-opt fluentd-address=localhost:24224 --log-opt tag="docker.app" myapp

次に fluentd コンテナのログを確認します

  • docker logs -f fluentd

すると以下のようにログが表示されるのが確認できます

2019-07-17 03:59:03.427725600 +0000 docker.app: {"container_id":"a7e199fa8f7b03fdcd84032f9633721668fd7a8f4c07f6931576978b7ff82bc7","container_name":"/reverent_tereshkova","source":"stdout","log":"{\"timestamp\": \"2019-07-17 03:55:46 +0000\", \"message\": \"d4d05f96-8523-4b3f-a965-89967600c58c\"}","timestamp":"2019-07-17 03:55:46 +0000","message":"d4d05f96-8523-4b3f-a965-89967600c58c"}

reserve_data false にすれば log キーのパースされていない元データがなくなります
そちらのほうがすっきりする場合はあります

最後に

JSON のログを docker fluentd ドライバでパースする方法を紹介しました
filter で処理したあとはちゃんと match で受け取るのを忘れないようにしましょう

参考サイト

0 件のコメント:

コメントを投稿