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

尚、ログファイルの取り扱いについては以下の記事を参考にさせて頂いた。

はじめに 藤本です。 今年もあと3週間です。忘年会の時期になりましたね。今年はプライベートの忘年会の予定がないことに気づきました(アハハ 概要 Amazon RDSはOS上にあるログファイルをAPIを通して閲覧することが

dev.classmethod.jp

有難うございます。

fluentd インプットプラグイン

ということで、雑な fluentd インプットプラグインを作ってファイルからログを読み込んでみることにした。

gist.github.com

色々と課題があるので、gem 化は見送り…。スローログを JSON にパースするのは以下の gem を利用させて頂いた。

Contribute to mysql-slowquery-parser development by creating an account on GitHub.

github.com

有難うございます。

作成したプラグインは plugins ディレクトリにコピー。

% tree ./plugins
./plugins
└── in_rds_mysqlslowlog_stream.rb

0 directories, 1 file

fluentd.conf は以下のように設定する。


  @type rds_mysqlslowlog_stream
  tag rds-slowlog
  db_instance_identifier demo-db
  marker_file /tmp/log_marker.txt



  @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 テンプレートがほぼそのまま利用出来る。

20160505232300

スロークエリの数を見ると大杉漣だが、これはあくまでもサンプルということで…。

一応、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 の場合 〜