金曜日, 6月 13, 2025
- Advertisment -
ホームニューステックニュースKtorでCallIdを使ってクライアントを一意に特定する #Kotlin - Qiita

KtorでCallIdを使ってクライアントを一意に特定する #Kotlin – Qiita



KtorでCallIdを使ってクライアントを一意に特定する #Kotlin - Qiita

タイトルについてまず捕捉する。

そもそもログインしていないアカウントに関しては、サーバーで発行したセッションIDをCookieに持っていない。

これで困るのがロギングのシーンである。未ログイン状態でアクセスしてくるユーザーが入り混じるため、とあるユーザーの行動をログから追跡することができない。

このようなシチュエーションに有用なのがCallIdである。

まずはbuild.gradle.ktsにインストール。

dependencies {
    // 略

    // for call id
    implementation("io.ktor:ktor-server-call-id:$ktor_version")

    //略
}

次にApplication.ktからKtorにプラグインをインストールする。installの中のverifyなどについては後ほど詳しく説明する。

package example.koin

import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.plugins.callid.*
import io.ktor.server.plugins.callloging.*

fun main(args: ArrayString>) {
    io.ktor.server.tomcat.EngineMain.main(args)
}

fun Application.module() {
    settingKoin()
    configureRouting()
    install(CallId) {
        header(HttpHeaders.XRequestId)
        verify { callId: String ->
            callId.isNotEmpty()
        }
    }
    install(CallLogging) {
        callIdMdc("call-id")
    }
}

最後にlogback.xmlX-Request-IDとして付与されるCallIdを出力するための設定をいれる。%X{call-id}がそう。


     name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        
            %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %X{call-id} %-5level %logger{36} - %msg%n
        
    
     level="debug">
         ref="STDOUT"/>
    

まずはX-Request-IDの有無によるログ出力やレスポンスをみてみる。今回はinorinrinrinというCallIdをマニュアルで付与する。

するとレスポンスヘッダにも同じものが設定されているのがわかる。これはheader()が取得→送信をひとまとめにしてくれているからである。

image.png

ログをみると、X-Request-IDに紐づいたCallIdが出力されているのがわかる。

image.png

今度はX-Request-IDを外してリクエストを送信する。

image.png

すると今度はログにCallIdが出力されていないことがわかる。

image.png

これはverifyX-Request-IDの妥当性を検証しているからである。それを確認するため、verifyの条件をinoから始まる文字列にした場合にどうなるかをみてみる。

    install(CallId) {
        header(HttpHeaders.XRequestId)
        verify { callId: String ->
+            callId.startsWith("ino")
        }
    }

X-Request-IDayaneruとしてみた。このとき、レスポンスヘッダにX-Request-IDが返ってこない。ログにもCallIdは出ていない。

image.png

image.png

以上から、X-Request-IDが付与されていれば以降の通信でそれを使いまわせること。ログに出力できることを確認できた。

あとはX-Request-IDを初回リクエスト時に発行してあげればよい。CallIdを生成しX-Request-IDに設定するにはgenerateを使う。

生成方法にはドキュメントに記載があるとおり、文字の種類を渡して適当な長さのIDを生成させるか、自前で生成する方法がある。

今回は自前生成関数generateRandomStringを定義してみる。

fun generateRandomString(length: Int): String {
    val charPool = ('a'..'z') + ('A'..'Z') + ('0'..'9') // 小文字、大文字、数字
    return (1..length)
        .map { Random.nextInt(charPool.size) }
        .map(charPool::get)
        .joinToString("")
}

これをgenerateに渡す。

    install(CallId) {
        header(HttpHeaders.XRequestId)
+        generate { generateRandomString(10) }
        verify { callId: String ->
            callId.isNotEmpty()
        }
    }

ではX-Request-IDを付与しない初回のリクエストを見てみる。すると10文字のCallIdが生成され、レスポンスヘッダに付与されたのがわかる。

image.png

Ktorがロギングまで気を配ってくれているので非常にありがたい。この手の仕組みを数行で実現できるのは利用者からするとかなり楽。





Source link

Views: 0

RELATED ARTICLES

返事を書く

あなたのコメントを入力してください。
ここにあなたの名前を入力してください

- Advertisment -