
タイトルについてまず捕捉する。
そもそもログインしていないアカウントに関しては、サーバーで発行したセッション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.xmlにX-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()が取得→送信をひとまとめにしてくれているからである。
ログをみると、X-Request-IDに紐づいたCallIdが出力されているのがわかる。
今度はX-Request-IDを外してリクエストを送信する。
すると今度はログにCallIdが出力されていないことがわかる。
これはverifyがX-Request-IDの妥当性を検証しているからである。それを確認するため、verifyの条件をinoから始まる文字列にした場合にどうなるかをみてみる。
install(CallId) {
header(HttpHeaders.XRequestId)
verify { callId: String ->
+ callId.startsWith("ino")
}
}
X-Request-IDをayaneruとしてみた。このとき、レスポンスヘッダにX-Request-IDが返ってこない。ログにもCallIdは出ていない。
以上から、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が生成され、レスポンスヘッダに付与されたのがわかる。
Ktorがロギングまで気を配ってくれているので非常にありがたい。この手の仕組みを数行で実現できるのは利用者からするとかなり楽。
Views: 0







