PostgreSQLの拡張モジュールを書いたので紹介記事を作っておきます。
SQLログを取得している場合の問題
PostgreSQL では log_statements、log_min_error_statement、log_min_duration_statement といった設定を使って、サーバログに実行したSQL文を記録できます。例えば、log_statement = 'mod' と設定して、DDLとデータ更新については全てログに記録するという運用をすることができます。
このとき問題となるのが長いSQL文のログ出力です。log_statement = 'mod' でデータを一括投入するするときにログに巨大な出力が生じてしまいます。
- 数KBになる長いログメッセージは適当なところで後ろを切り捨てる
- 長いSQLのログ記録も切り捨てる
ということができないかというニーズがあって、残念ながら標準機能ではできそうに無く(※1)、また、これだけを行うというシンプルな拡張モジュールは無いため(※2)、自分で単純なモジュールを書いてみました。
※1:非スーパーユーザに対してでも ALTER USER ... SET ...文で log_statement等の設定を与えることができます。これも有力です。ただし、アプリ側での使うDBユーザを変えてもらう対処が必要となります。
※2:監査ログ機能を提供する拡張モジュールを導入して、その拡張モジュールの機能で長いSQLのログは捨てるという設定が可能であるかもしれません。
pg_truncate_log_message
pg_truncate_log_message は pg_truncate_log_message.max_length で指定した長さ(バイト)を上限としてログメッセージを切り捨てます。また、そのときには対応する STATEMENT: 出力もスキップします。すなわち、長い SQL文の全体をログ出力するケースでログを一部切り捨てる働きをします。
課題点
現時点での pg_truncate_log_message は文字エンコーディングを識別していません。したがって、マルチバイト文字の途中で切ってしまって、文字化けを起こす可能性があります。ここは直さないといけません。
→ 2019/2/20 マルチバイト文字に対応しました。また、PostgreSQL 10.x以下の旧バージョンでもビルドできるようにしました。