本題
概要
SpringBoot のログを Elasticsearch に送って Kibana で見たかったが、SpringBoot のログを Elasticsearch に送るための方法がすぐにはわからなかった。fluentd を使って転送できたのでその方法を記す。
- 確認した構成
- Elastic Stack サーバ
- OS: CentOS7 / Elasticsearch: Version 5.0.1 / Kinbana Version: Version 5.0.1
- SpringBoot サーバ
- OS: CentOS7 / SpringBoot: Version1.4.2 / td-agent 0.12.29
- Elastic Stack サーバ
対象とするログ
spring.log
(略)
2016-12-09 21:27:13.240 INFO 13404 --- [pool-1-thread-1] com.example.Task : 1039443329 is 1039443329
2016-12-09 21:27:13.741 ERROR 13404 --- [pool-1-thread-1] o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred in scheduled task.
java.lang.RuntimeException: FizzBuzz
at com.example.Task.fizzBuzz(Task.java:21) ~[main/:na]
at com.example.Task.doTask(Task.java:16) ~[main/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_91]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_91]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_91]
(略)
- 特徴
- スタックトレースなど複数行にまたがるログがある。
fluentd の設定
/etc/td-agent/td-agent.conf
<source>
type tail
path /spring/logs/spring.log
pos_file /var/log/td-agent/spring.log.pos
tag spring.logtest
refresh_interval 5s
format multiline
format_firstline /\d{4}-\d{1,2}-\d{1,2} \d{1,2}:\d{1,2}:\d{1,2}\.\d{3}.*---/
format1 /^(?<time>\d{4}-\d{1,2}-\d{1,2} \d{1,2}:\d{1,2}:\d{1,2}\.\d{3})\s+(?<level>[^\s]+)\s+(?<process>[^\s]+)\s+---\s+\[(?<thread>[^\s]+)\]\s+(?<class>[^\s]+)\s+:\s+(?<message>.*)/
</source>
<match spring.**>
type Elasticsearch
type_name spring_logtest
host 192.168.33.9
port 9200
logstash_format true
logstash_prefix spring_logtest
logstash_dateformat %Y%m%d
include_tag_key true
tag_key @log_name
flush_interval 5s
</match>
- (入力)tail プラグイン 詳細はこちらで確認してください
- format multiline 機能を使って複数行のログを1つの情報として扱えるようになる。
- 完璧な正規表現ではないので誤検知もあり得る
- format_firstline で1つのログの先頭行を判定するための正規表現
- format1 でログの各項目に意味づけする (<フィールド名>データ抽出の正規表現)
- format multiline 機能を使って複数行のログを1つの情報として扱えるようになる。
- Elasticsearchプラグイン 詳細はこちらで確認してください
- host / port : Elasticsearch サーバの host と port
結果
感想
これが推奨される方法なのだろうか? SpringBoot も Elasticsearch も Kibana も簡単なんだけど、SpringBoot のログを Elasticsearch に転送するという部分だけこんなにゴリゴリ正規表現書かなくちゃいけないのはスマートではないような気がするので。良い方法あったら教えてください。
おまけ:確認をした構成を作るまで
Elastic Stack サーバ のセットアップ
この記事がわかりやすい
Elastic Stack 5.0.0 GAリリース! 早速インストール!! #Elasticsearch"
- 記事は Amazon Linux を想定していますが CentOSも同じコマンド行けました。
- 本稿に関係あるのは、「ElasticsearchとKibanaのインストール」までで良いです。
- 「Beatsのインストール」までやっても損はないと思う
- 「Logstashのインストール」は本稿の構成の場合は不要
Spring Boot アプリケーションの準備
- アプリを作るところは省略
- ログをファイル出力するためには application.yml に 以下のように書く
application.yml
# 以下の設定だと <実行ディレクトリ>/logs/spring.log ができる
logging.file: logs/spring.log
fluentd(td-agent) の準備 @ SpringBoot サーバ
- 基本的に 公式の通りインストール。
- fluent-plugin-elasticsearch を使用する
- 以上をコマンドにすると以下。
sudo wget -r --no-parent --no-directories -A 'epel-release-*.rpm' http://dl.fedoraproject.org/pub/epel/7/x86_64/e/
curl -L https://toolbelt.treasuredata.com/sh/install-redhat-td-agent2.sh | sh
sudo td-agent-gem install fluent-plugin-Elasticsearch
- fluentd(td-agent) 再起動
- 上記の設定ができたらconfファイルを書き換えたので fluentd 再起動する。
sudo /etc/init.d/td-agent restart
- fluentd(td-agent) の動作確認
Springアプリケーションを起動してログを出力させた後。
/var/log/td-agent/td-agent.log
をみて Elasticsearch につながったっぽいログが出たら成功。