PostgreSQL 18がやってくる(12) Increase the logging granularity of server variable log_connections

# はじめに
にゃーん。
今回は以前から調べようと思って手つかずだった、接続ログ出力指定の変更についてやっと調べて書いてみました。

# 改善項目概要
この改善項目は「接続」に関するログ出力をより詳細に指定可能にする、という項目である。
PostgreSQL 17までは、接続に関するログ出力は、``log_connections``というパラメータで制御していた。この``log_connections``の設定方法が大きく変わった。

|バージョン|データ型|値域|デフォルト値|パラメータ反映契機|
|:--|:--|:--|:--|:--|
|PostgreSQL 17|boolean |on, off, 1, 0, true, false,yes, no|off|superuser-backend|
|PostgreSQL 18 |string |(後述)|(空文字列) |superuser-backend|

PostgreSQL 18ではboolean型ではなく、文字列型を設定するようになった。
以下に示す値をカンマ区切りのリストで設定する、ということらしい。

|文字列|意味|
|:--|:--|
|(空文字列)|接続に関するログを全く出力しなくなる。<br>PostgreSQL 17までの``off``設定と同様の挙動になる。|
|receipt|受信ログ出力。<br>接続の受信をログに記録する。|
|authentication|認証ログ。<br>認証方式がユーザを識別するために使用した元のIDをログに記録する。<br>ほとんどの場合、ID文字列はPostgreSQLのユーザ名と一致するが、サードパーティの認証方法の中には、サーバが保存する前に元のユーザ識別子を変更してしまうものもある。<br>認証に失敗した場合は、この設定の値に関係なく常にログに記録される。|
|authorization|認可(認証成功)ログ。<br>認証が正常に完了したことをログに記録する。<br>この時点で接続は確立されているが、バックエンドはまだ完全にセットアップされていない。<br>ログメッセージには、認証されたユーザ名、データベース名、アプリケーション名 (もしあれば) が含まれる。|
|setup_durations|バックエンド起動時間ログ。<br>接続が最初の問い合わせを実行する準備ができた時点で、接続の確立とバックエンドの設定に費やされた時間をログに記録する。<br>このログメッセージには、postmaster が接続を受け付けてからクエリの準備が完了するまでの、セットアップにかかった時間が含まれる。また、新しいバックエンドをフォークするのにかかった時間と、ユーザを認証するのにかかった時間も含まれる。|
|all|すべてのオプションを指定するのと同等の便利なエイリアス。<br>他のオプションのリストで``all``を指定すると、すべての接続の側面がログに記録される。|


PostgreSQL 17までの後方互換性のために、以下の設定値も許容している。
|設定値|挙動|
|:--|:--|
|on,true,yes,``1``|受信、認証、認可の各オプションを指定と同等。<br>``all``指定と同等ではないことに注意が必要。|
|``off``,``false``,``no``,``0``|接続関連のログ出力をしない。<br>空文字列指定と同等。|

# 動作確認
動作確認のために、一般ユーザ``foo``が``testdb``データベースに``scram-sha-256``認証方式で接続する環境でログ出力動作を色々と確認してみる。

## 空文字

``log_connections``に空文字を設定した場合、接続ログは出力されない。
``log_connections``のデフォルトの設定はこの挙動となる。

## all指定

``all``を設定した場合の例を以下に示す（見やすくするため``log_line_prefix``はあえて空値にしている）。

以下のようにpsqlによる接続を試みる。
``foo``ユーザによる接続はパスワード入力を要求される。
```bash
$ psql -p 18001 -U foo testdb
Password for user foo:
```
この時点でサーバログには以下の1行が出力される。
```sql
LOG:  connection received: host=[local]
```

誤ったパスワード入力した場合には、以下のようにサーバログが出力される。
```sql
LOG:  connection received: host=[local]
LOG:  connection received: host=[local]
FATAL:  password authentication failed for user "foo"
DETAIL:  Connection matched file "/tmp/pg18/pg_hba.conf" line 117: "local   all             foo                                     scram-sha-256"
```

正しいパスワードを入力して接続に成功した場合には、以下のようにサーバログが出力される。
```sql
LOG:  connection received: host=[local]
LOG:  connection received: host=[local]
LOG:  connection authenticated: identity="foo" method=scram-sha-256 (/tmp/pg18/pg_hba.conf:117)
LOG:  connection authorized: user=foo database=testdb application_name=psql
LOG:  connection ready: setup total=10.991 ms, fork=0.352 ms, authentication=8.419 ms
```

## receipt/authentication/authorization/setup_durations
次に接続の各フェーズを出力する指定を、それぞれ設定した状態での接続成功時のログを見る。

### log_connections = receipt
```sql
LOG:  connection received: host=[local]
LOG:  connection received: host=[local]
```
同じメッセージが2回出力されているが、これはpsqlの接続方法によるものである。

### log_connections = authentication

```sql
LOG:  connection authenticated: identity="foo" method=scram-sha-256 (/tmp/pg18/pg_hba.conf:117)
```

### log_connections = authorization
```sql
LOG:  connection authorized: user=foo database=testdb application_name=psql
```

### log_connections = setup_durations
```sql
LOG:  connection ready: setup total=10.687 ms, fork=0.361 ms, authentication=8.255 ms
```

### log_connectionsに全フェーズの指定を記述（順序不定）
``log_connections = 'setup_durations,receipt,authorization,authentication'``と指定する。
この例のように、カンマ区切りのリストとして設定する場合には、単一引用符による引用をしないと設定エラーとなる（カンマがひっかかる）

```sql
LOG:  connection received: host=[local]
LOG:  connection received: host=[local]
LOG:  connection authenticated: identity="foo" method=scram-sha-256 (/tmp/pg18/pg_hba.conf:117)
LOG:  connection authorized: user=foo database=testdb application_name=psql
LOG:  connection ready: setup total=10.749 ms, fork=0.373 ms, authentication=8.243 ms
```
特にリストの記載順序は関係しないようだ。

## 後方互換性設定
前に説明したように、後方互換性のために、on, off等の指定も許容している。
on, off等の値は単一引用符で引用する必要はない。

``log_connections = on``と指定した場合は以下のなログになる。

```sql
LOG:  connection received: host=[local]
LOG:  connection received: host=[local]
LOG:  connection authenticated: identity="foo" method=scram-sha-256 (/tmp/pg18/pg_hba.conf:117)
LOG:  connection authorized: user=foo database=testdb application_name=psql
```
``on``指定の場合、``all``の指定では出力されていた、``setup_durations``指定で出力されるログは出力されないことに注意。

また、on, off等のbool値の場合、単一引用符で引用してカンマ区切りで書くとエラーになるので注意（まあ、そんな無意味な指定はしないと思うけど）
例えば、``log_connections = 'on,true'``と指定した場合には、以下のような設定エラーになる。
```sql
LOG:  received SIGHUP, reloading configuration files
LOG:  invalid value for parameter "log_connections": "on,true"
DETAIL:  Cannot specify log_connections option "on" in a list with other options.
LOG:  configuration file "/tmp/pg18/postgresql.conf" contains errors; unaffected changes were applied
```

## 不正な値の設定
例えば、``log_connections = 'hoge,authorization'``のような不正な値(``hoge``)を含む文字列を設定した場合にはエラーとなる。
不正な指定を無視して動作する、という挙動ではないようだ。

```sql
LOG:  received SIGHUP, reloading configuration files
LOG:  invalid value for parameter "log_connections": "hoge,authorization"
DETAIL:  Invalid option "hoge".
LOG:  configuration file "/tmp/pg18/postgresql.conf" contains errors; unaffected changes were applied
```

# 接続切断のログは？
接続切断のログは``log_disconnections``で制御するが、これは従来のまま``boolean``型で設定する。
PostgreSQL 17/PostgreSQL 18でのログ出力設定の差異はない。

# おわりに
今回はlog_connections設定の大幅な変更について調べてみました。
大幅な変更、とは書いたけどPostgreSQL 17までの後方互換性はしっかりと維持しているのはありがたいですね。