AWS RDS PostgreSQLのクエリログをawscliで取得するワンライナー

事前の設定

AWS RDS PostgreSQLでクエリのログをすべてログに残すには、パラメータグループで以下のように設定します。

log_statement=all
log_min_duration_statement=0

log_statement=allはすべての種類のクエリログを記録するという指示で、log_min_duration_statement=0はクエリ実行にかかった時間によらずすべてのクエリをログに記録するという指示です。

log_min_duration_statementはミリ秒単位で1000にすれば処理に1秒以上かかったクエリのみをログに残すということになります。

RDSでないPostgreSQLであれば postgresql.conf に書く内容です。

ログの取得

ログはPostgreSQLの動いているインスタンスにファイルとして保存されているのですが、RDSの中のファイルにはアクセスできません。awscliであればaws rds describe-db-log-filesコマンドとaws rds download-db-log-file-portionコマンドでログファイルを取得できます。

ファイル名を取得

まずログのファイル名を調べます。aws rds describe-db-log-filesコマンドです。DB_IDENTIFIERのところにはRDSのインスタンス名を入れます。

$ aws rds describe-db-log-files --db-instance-identifier DB_IDENTIFIER

awscliの設定がデフォルトであればJSONで以下のように表示されます。

{
  "DescribeDBLogFiles": [
    {
      "LogFileName": "error/postgresql.log.2020-04-25-11",
      "LastWritten": 1587815792000,
      "Size": 3912
    },
    {
      "LogFileName": "error/postgresql.log.2020-04-25-12",
      "LastWritten": 1587819393000,
      "Size": 3912
    },
    {
      "LogFileName": "error/postgresql.log.2020-04-25-13",
      "LastWritten": 1587822994000,
      "Size": 3912
    },

jqがインストールされていれば、jqを使ってカラー表示するにはこんな感じ。

$ aws rds describe-db-log-files --db-instance-identifier DB_IDENTIFIER | jq .

長くてページャーを入れたい場合は、こんな感じ。jq-Cが、less-Rが必要です。

$ aws rds describe-db-log-files --db-instance-identifier DB_IDENTIFIER | jq . -C | less -R

ログファイルの中身を取得

ファイル名がわかったら次はaws rds download-db-log-file-portionコマンドを使います。ファイル名を指定してその中身を取得できます。

$ aws rds download-db-log-file-portion --db-instance-identifier DB_IDENTIFIER --log-file-name error/postgresql.log.2020-05-02-11
{
    "LogFileData": "2020-05-02 11:25:00 UTC:172.31.30.61(35058):postgres@postgres:[25683]:LOG:  statement: select * from tbla;\n........................\n"
}

なんとファイルの中身全体を1つの文字列として包んだJSONが返ってきてしまいます。とても見づらいです。

こんなときはjqを使えばよいです。jq-rを付けます。

$ aws rds download-db-log-file-portion --db-instance-identifier DB_IDENTIFIER --log-file-name error/postgresql.log.2020-04-25-11 | jq .LogFileData -r
2020-05-02 11:25:00 UTC:172.31.30.61(35058):postgres@postgres:[25683]:LOG:  statement: select * from tbla;
2020-05-02 11:25:00 UTC:172.31.30.61(35058):postgres@postgres:[25683]:LOG:  duration: 4.193 ms

全ログファイルを結合

ファイル名を1つずつ指定してダウンロードしないといけないのが面倒で、保存されているログファイルを時系列で並べて全部結合したい場合は、ワンライナーですと次のようになります。

$ for f in $(aws rds describe-db-log-files --db-instance-identifier DB_IDENTIFIER | jq ".DescribeDBLogFiles[] | .LogFileName" -r | grep 'error/postgresql.log.' | sort); do aws rds download-db-log-file-portion --db-instance-identifier DB_IDENTIFIER --log-file-name $f | jq .LogFileData -r; done

2020/11/06追記

上記ワンライナーですと途中でログが途切れてしまう問題や日本語が文字化けする問題がありましたので、以下の記事に改良版を書きました。ワンライナーではなくなってしまいますが。