tl;dr
RDS のスローログ等はテーブル又はファイルに記録することが出来る。前回は、テーブルに記録する設定を用いて、テーブルからログを定期的に読み込んで EFK スタックで可視化する仕組みを考えた。
今回はテーブルではなくファイルに記録する設定を用いて、ファイルを定期的に読み込んで EFK スタックで可視化する仕組みを作ってみた。
memo
log_output: TABLE or log_output:FILE
テーブルに記録する場合とファイルに記録する場合の違いは以下の通り。
記録方法 | RDS パラメータ | 特徴 |
---|---|---|
テーブル | log_output: TABLE | 通常のクエリを mysql.general_log テーブルに、スロークエリを mysql.slow_log テーブルに書き込む |
ファイル | log_output:FILE | 通常のクエリログとスロークエリログの両方をファイルシステムに書き込む / ログファイルは 1 時間ごとにローテーションあれる |
ログのローテーションについては、それぞれ、以下のような措置が取られる。(ドキュメントより引用)
- ファイルに記録する場合
FILE ログ記録が有効になっている場合、ログファイルの検査が 1 時間ごとに実行され、作成後 24 時間を超えた古いログファイルは削除されます。削除後、残りのログファイルの合計サイズが、DB インスタンスに割り当てられた領域の 2 パーセントというしきい値を超えている場合、ログファイルのサイズがしきい値以下になるまで、最も大きいログファイルから順に削除されます。
- テーブルに記録する場合
TABLE ログ記録が有効になっている場合は、テーブルログに使用されている領域が、割り当てられたストレージ領域の 20% を超えるか、すべてのログの合計サイズが 10 GB を超えると、24 時間ごとにログテーブルのローテーションが実行されます。DB インスタンスに使用されている領域が、DB インスタンスに割り当てられたストレージ領域の 90% を超えている場合は、ログのローテーションを実行するためのしきい値が小さくなります。テーブルログに使用されている領域が、割り当てられたストレージ領域の 10% を超えるか、すべてのログの合計サイズが 5 GB を超えると、ログテーブルのローテーションが実行されます。 ログテーブルのローテーションが実行されると、現在のログテーブルがバックアップのログテーブルにコピーされ、現在のログテーブル内にあるエントリは削除されます。バックアップのログテーブルがすでに存在する場合は、現在のログテーブルをバックアップにコピーする前に、削除されます。バックアップのログテーブルは、必要に応じて照会することができます。mysql.general_log テーブルに対するバックアップのログテーブルは、mysql.general_log_backup という名前になります。mysql.slow_log テーブルに対するバックアップのログテーブルは、mysql.slow_log_backup という名前になります。 mysql.general_log テーブルのローテーションは、mysql.rds_rotate_general_log プロシージャを呼び出すことで実行できます。mysql.slow_log テーブルのローテーションは、mysql.rds_rotate_slow_log プロシージャを呼び出すことで実行できます。 データベースバージョンのアップグレード時にも、テーブルログのローテーションが実行されます。
テーブルの場合にはローテーションは自動で行う仕組み自体は用意されているが、ストレージ領域と比較した値が閾値となっているので、うっかり放置しておくとテーブルのサイズが肥大化してクエリを投げても結果を得るまでの時間が掛かったり、それ自体の負荷が大きくなってしまう懸念があるので、個人的にはテーブルよりもファイル記録の方が良いと考えている。(そもそも、スロークエリが肥大化する前にスロークエリの対策を行うべきだと思うし、クエリログを取り続ける運用を行うかどうか悩みどころである)
ファイルに記録されたログを読み込む際の注意点
aws cli や SDK を使ってファイルに記録されたログを読み込むことが出来るが、読み込む際には以下の点で注意が必要。
- 一回でダウンロードすることが出来るログファイルサイズは 1 MB(という認識だが、ドキュメントの読み違いの可能性があるので注意)
- 一回の API コールによるログ取得で最大 10000 行までログを取得出来る(10000 行以上取得したい場合には marker オプションを利用する)
- ログファイルの先頭から読み込みたい場合には marker パラメータの値を 0 にする
AWS SDK for Ruby でログを取得する場合には以下のように取得することで、ログファイルの冒頭から 10000 行以上のログを取得出来る。(はず)
rawlog = "" opts = { db_instance_identifier: @db_instance_identifier, log_file_name: @log_file_name, marker: "0" } additional_data_pending = true while additional_data_pending do res = @rds.download_db_log_file_portion(opts) unless check_marker(res[:marker]) then opts[:marker] = res[:marker] additional_data_pending = res[:additional_data_pending] rawlog << res[:log_file_data] write_marker(opts[:marker]) else return "already imported." break end end
尚、ログファイルの取り扱いについては以下の記事を参考にさせて頂いた。
dev.classmethod.jp
有難うございます。
fluentd インプットプラグイン
ということで、雑な fluentd インプットプラグインを作ってファイルからログを読み込んでみることにした。
色々と課題があるので、gem 化は見送り…。スローログを JSON にパースするのは以下の gem を利用させて頂いた。
github.com
有難うございます。
作成したプラグインは plugins ディレクトリにコピー。
% tree ./plugins ./plugins └── in_rds_mysqlslowlog_stream.rb 0 directories, 1 file
fluentd.conf は以下のように設定する。
@type copy @type stdout @type elasticsearch type_name mysqlslowquery host 192.168.99.100 port 9200 logstash_format true logstash_prefix mysqlslowquery include_tag_key true
fluentd は以下のように起動する。
# # fluentd.conf を stream.conf とリネームした # plugins ディレクトリに作成したオレオレプラグインを放り込んでおく # % bundle exec fluentd -c stream.conf -l stream.log -p plugins
Elasticsearch と Kibana は前の記事で利用した Docker Compose on MacOS X 上で動かしている。
可視化
ログファイルをテーブルに保存する設定とは一部のカラムが異なるので微調整が必要になるが、前の記事で利用した Kibana テンプレートがほぼそのまま利用出来る。
スロークエリの数を見ると大杉漣だが、これはあくまでもサンプルということで…。
一応、Docker-Compose も
以下のような感じで docker-compose.yml も書いてみたが、fluentd コンテナのビルドでちょっと詰まって調整中。
elasticsearch: image: elasticsearch ports: - 9200:9200 - 9300:9300 fluentd: build: . links: - elasticsearch volumes: - .:/home/fluent environment: - FLUENTD_CONF=stream.conf kibana: image: kibana ports: - 5601:5601 links: - elasticsearch
後ほど、github にアップしておく。
以上
前回の課題に上げていた RDS(MySQL) スローログをファイルに記録する設定で EFK スタックを使った可視化環境を考察してみた。テーブルに記録する場合とやることは殆ど変わらないが、ファイル記録の場合には一回で取得出来るログファイルサイズや行数、ローテーション等を気にする必要がありそう。
ということで、スローログが出来るだけ吐かれることの無いアプリケーションを目指して…。
おやすみなさい。
元記事はこちら
「RDS(MySQL) のスロークエリを EFK スタック + Docker で出来るだけ手軽に可視化する考察(2)〜 log_output: FILE の場合 〜」