magのOSS備忘録

使ったOSSソフトウェアについて書いていきます。

Keycloak (Quarkus版) でアクセスログを出力し、任意の名前でローテートする

概要

Quarkus版のKeycloak (バージョン17からのデフォルト) にて、ログローテーションしながらアクセスログを出す方法を記載する。 本エントリでは、logrotateなどの外部プログラムを使用せず、Keycloakの設定のみで行う方法を扱う。

このエントリの結論としては、以下のことができた (できなかった)。

  • アクセスログを任意のファイル名で出力する。
  • ログファイルの日次ローテートを行い、任意のサフィックスを付けたファイル名で保存する。
  • ローテートしたファイルについて、任意の世代数だけ保持する (古いものを削除する) ことはできなかった。

動機

Quarkus版のKeycloak (バージョン17からのデフォルト) にて、アクセスログを任意のログファイルに出力したい。 さらに、そのログファイルを日次でローテーションしたい、となったときに設定方法を探したところ、なかなか設定方法にたどり着かなかったため、書き残すことにした。

実行環境・前提条件

目次

アクセスログ周りの動作

以前のWildFly版Keycloakと同様に、ログの設定はアプリケーションサーバー側 (Quarkus) で設定することになる。

KeycloakはベースとなるQuarkusの機能を使ってログをファイルに出力するようになっている。 そのため、Quarkusでアプリケーションを構築するときと同様に、JBoss Loggingの設定を行うことになる。

蛇足だが、QuarkusはHTTPサーバーとしてundertowを使用しているのだと思っていたら、Vert.xというライブラリを使用するようになっているそうだ。アクセスログを出力しているのはHTTPサーバーの機能を持っている部分であり、そこに対しての設定を行うため少し触れた。

Quarkus の HTTP レイヤーのスレッドプールについて - 赤帽エンジニアブログ

シンプルにアクセスログを出力しようとする場合は、以下の参考サイトで説明している、

QuarkusベースのKeycloakが出力するログについて #Java - Qiita

下記の設定を行うことで、Keycloakの最上位のディレクトリで、quarkus.logという名称のファイルにアクセスログが出力される。

quarkus.http.access-log.enabled=true
quarkus.http.access-log.log-to-file=true

これらのデフォルト値や設定できる項目は、以下の公式ドキュメントにて確認できる。アクセスログのファイル名は公式ドキュメントでも触れられており、簡単に指定できる。

HTTPリファレンス - Quarkus

アクセスログを出力したファイルのローテートを行う場合は、quarkus.http.access-log.rotatetrueにすると良さそうだが、ローテートの細かい設定はできないようだ。 quarkus.http.access-log.rotatetrueにすると、日次でローテートされ、以下のような名称のファイルが作られる (accessや.logは設定で変更可能)。また、調査をしていないが、公式ドキュメントには保持するログファイルの世代数が設定できるかは明記されておらず、できるかどうかが不明だった。

access2024-01-26.log

これだと以下のようなお決まりのことをやりたい場合は機能が足りない。

  • 日次でローテートする。
  • 保持する世代数を指定する (ある世代数を超える場合は古いファイルを削除する)。
  • ログファイルのファイルサイズが一定を超えたらローテートする。

これらを設定するためには以下で説明があるロギングの機能と組み合わせが必要になる。次は具体的な設定方法を記載する。

ロギング設定 - Quarkus

設定方法

設定箇所 (設定ファイル等)

Quarkusの設定を行うため、以下のファイルに対して設定値を指定する。 ビルドして設定値を反映する以外にも、システムプロパティ(-Dオプション)などを指定することもできるようだ。

lib\quarkus\build-system.properties

設定リファレンスガイド - Quarkus

設定後は以下のようにビルドを実施し、Keycloakを起動する。

bin\kc.bat build
bin\kc.bat start

設定値

具体的な設定値は以下。

quarkus.http.access-log.enabled=true
quarkus.http.access-log.log-to-file=false
quarkus.http.access-log.rotate=false

quarkus.log.category."io.quarkus.http.access-log".level=INFO
quarkus.log.category."io.quarkus.http.access-log".use-parent-handlers=false
quarkus.log.category."io.quarkus.http.access-log".handlers=access-log-handler

quarkus.log.handler.file.access-log-handler.enable=true
quarkus.log.handler.file.access-log-handler.path=logs/access.log
quarkus.log.handler.file.access-log-handler.format=%s%n
quarkus.log.handler.file.access-log-handler.rotation.file-suffix=.yyyy-MM-dd
quarkus.log.handler.file.access-log-handler.rotation.rotate-on-boot=false

設定値の解説

アクセスログの設定

まず、一番のポイントはquarkus.http.access-log.log-to-filefalseを指定するところ。 冒頭のシンプルにアクセスログを出そうとした場合はtrueを指定していたが、この設定を行うとアクセスログ独自のファイル出力処理が動作し、そのあとで設定しているハンドラなどが動作に反映されなかった。

この部分は公式ドキュメントには書いてなく、Quarkusのソースコードを読んでみて分かった。以下の箇所の近辺で分岐している。ここは少し不親切だと思う。

quarkus/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java at e29a90cba8a5ab240cf5b1db1a7cc9ceb7272dd9 · quarkusio/quarkus · GitHub

また、HTTPサーバー機能側でのローテートは不要なのでquarkus.http.access-log.rotatefalseにする。

カテゴリとハンドラの関連付け

次に以下のようにしてカテゴリとハンドラを関連付ける。ここでのポイントは、カテゴリにio.quarkus.http.access-logを指定するところ。アクセスログ側のquarkus.http.access-log.categoryの値と合わせる必要がある。

quarkus.log.category."io.quarkus.http.access-log".level=INFO
quarkus.log.category."io.quarkus.http.access-log".use-parent-handlers=false
quarkus.log.category."io.quarkus.http.access-log".handlers=access-log-handler

ちなみに公式ドキュメントのquarkus.http.access-log.categoryの説明に、base-file-nameに何も設定されていない場合は標準ログメカニズムが使用されるとある。最初にそこを読んでbase-file-nameに何も設定しないよう試行錯誤したのだが、base-file-nameは空にできないというエラーが発生し、結局Keycloakを起動できなかった。

ハンドラの定義

最後に以下のようにハンドラを定義する。

quarkus.log.handler.file.access-log-handler.enable=true
quarkus.log.handler.file.access-log-handler.path=logs/access.log
quarkus.log.handler.file.access-log-handler.format=%s%n
quarkus.log.handler.file.access-log-handler.rotation.file-suffix=.yyyy-MM-dd
quarkus.log.handler.file.access-log-handler.rotation.rotate-on-boot=false

カテゴリとの関連付けで指定したハンドラaccess-log-handlerに対して設定を行う。

ここで説明しておくのはquarkus.log.handler.file.access-log-handler.formatだが、既にアクセスログとしてフォーマットされているため、ここでは%sだけを指定している。何も設定しないと日付が2重で付与されたりする。なお、アクセスログ側の設定でフォーマットを制御できるため、ここでは特に指定しないのが良いと思う。

また、quarkus.log.handler.file.access-log-handler.rotation.file-suffixにて任意のサフィックスを指定することができる。

所感

ログに限らず全般的な設定だが、WildFlyの頃のXML形式での設定に比べれば分かりやすいと感じた。

そういえば、YAML形式などで書けるのだろうか。

参考