Kotlin

【Ktor】MDCでリクエスト情報を出力する【logback】

KtorはCallLoggingプラグインにより、MDC (Mapped Diagnostic Context) の管理/出力をサポートしています。

MDCとは、リクエストを受けたスレッドごとのコンテキスト情報を管理する仕組みのことで、これによりスレッド内で行われた一連の処理のログを紐付けることができます。(https://logback.qos.ch/manual/mdc.html)

サーバサイドアプリケーションでは、同時に複数のクライアントを相手に処理を行うことが求められるため、クライアント(=スレッド)単位のログ管理ができると便利です。
MDCを使うことによって、クライアントを識別するための traceId や、リクエストされた HTTP METHOD / URI などをログに出力することができます。

Ktorはデフォルトで logback によるログ出力に対応しているため、logback.xmlを使ったMDC追加情報の出力例を紹介します。

サンプルコード

CallLogging 設定

MDC用の設定をコードで行うためのサンプルコードです。

requestInfo としてリクエストされたHTTPメソッドとURI情報、traceId としてスレッド内の一連のログを紐づけるための乱数を生成します。

必要な依存関係や、プラグインのインストール方法の詳細は以下の公式ページを参考にして下さい。
https://ktor.io/docs/call-logging.html

import io.ktor.server.plugins.callloging.*
import io.ktor.server.request.*
import io.ktor.server.application.*
import java.util.*

fun Application.configureMonitoring() {
    install(CallLogging) {
        mdc("requestInfo") { call ->
            "${call.request.httpMethod.value} ${call.request.uri}"
        }

        mdc("traceId") {
            UUID.randomUUID().toString().replace("-".toRegex(), "")
        }
    }
}

logback 設定

MDC情報をログに出力するための logback.xml 設定例です。

[%X{requestInfo}] [%X{traceId}] の箇所で、requestInfotraceId を指定して出力しています。

これによりリクエストしてきたユーザを識別することが出来ます。

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg [%X{requestInfo}] [%X{traceId}] %n</pattern>
        </encoder>
    </appender>
    <root level="trace">
        <appender-ref ref="STDOUT"/>
    </root>
    <logger name="org.eclipse.jetty" level="INFO"/>
    <logger name="io.netty" level="INFO"/>
</configuration>

まとめ

最後にこの記事の内容をまとめます。

要点

  • MDCとは、スレッドごとのコンテキスト情報を管理する仕組みのこと
  • Ktorでは CallLoggingプラグインを使ってMDC情報を管理することが出来る
  • logback.xmlと連携することで任意の情報をログに含めることが出来る

KtorでMDCの設定方法を説明したページは少ないと思ったので今回紹介しました。

Ktorは公式ドキュメントも充実しているし、一般的なWebアプリケーションで求められている機能は一通り持っているので、特に小さなアプリケーションにはオススメ出来ます。

MDCは便利ですが、スレッド単位で情報を管理しているため以下の様な注意点もあります。

注意

Spring WebFluxなどのリアクティブスタイルのフレームワークでは、1スレッド=1クライアントになっておらず、ごく少数のスレッドを使って複数のクライアントを処理しています。

そのため、スレッド単位で情報を管理しているMDCは基本的に利用できません。

これらのフレームワークを使用する場合には、別の仕組みを使ってクライアントを識別する方法を考えなければなりません。

小ネタの様な記事でしたが、Ktorを試してみたい方の参考になれば幸いです。

この記事は役に立ちましたか?

  • この記事を書いた人
アバター画像

ゴイチ

ソフトウェアエンジニア歴20年。 C/C++, C#, Java, Kotlinが得意で、組込系・スマホ・大規模なWebサービスなど幅広いプログラミング経験があります。 現在は某SNSの会社でWebエンジニアをしています。

-Kotlin
-,