【问题标题】:Ktor Server/Application request/response body loggingKtor 服务器/应用程序请求/响应正文日志记录
【发布时间】:2021-06-20 14:57:42
【问题描述】:

有什么方法可以记录来自 ktor 服务器通信的请求和响应正文? 内置 CallLogging 功能仅记录呼叫的元数据。我尝试编写自己的日志记录功能,如下例所示:https://github.com/Koriit/ktor-logging/blob/master/src/main/kotlin/korrit/kotlin/ktor/features/logging/Logging.kt

class Logging(private val logger: Logger) {

    class Configuration {
        var logger: Logger = LoggerFactory.getLogger(Logging::class.java)
    }

    private suspend fun logRequest(call: ApplicationCall) {
        logger.info(StringBuilder().apply {
            appendLine("Received request:")
            val requestURI = call.request.path()
            appendLine(call.request.origin.run { "${method.value} $scheme://$host:$port$requestURI $version" })

            call.request.headers.forEach { header, values ->
                appendLine("$header: ${values.firstOrNull()}")
            }

            try {
                appendLine()
                appendLine(String(call.receive<ByteArray>()))
            } catch (e: RequestAlreadyConsumedException) {
                logger.error("Logging payloads requires DoubleReceive feature to be installed with receiveEntireContent=true", e)
            }
        }.toString())
    }

    private suspend fun logResponse(call: ApplicationCall, subject: Any) {
        logger.info(StringBuilder().apply {
            appendLine("Sent response:")
            appendLine("${call.request.httpVersion} ${call.response.status()}")
            call.response.headers.allValues().forEach { header, values ->
                appendLine("$header: ${values.firstOrNull()}")
            }
            when (subject) {
                is TextContent -> appendLine(subject.text)
                is OutputStreamContent -> appendLine() // ToDo: How to get response body??
                else -> appendLine("unknown body type")
            }
        }.toString())
    }

    /**
     * Feature installation.
     */
    fun install(pipeline: Application) {
        pipeline.intercept(ApplicationCallPipeline.Monitoring) {
            logRequest(call)
            proceedWith(subject)
        }
        pipeline.sendPipeline.addPhase(responseLoggingPhase)
        pipeline.sendPipeline.intercept(responseLoggingPhase) {
            logResponse(call, subject)
        }
    }

    companion object Feature : ApplicationFeature<Application, Configuration, Logging> {

        override val key = AttributeKey<Logging>("Logging Feature")
        val responseLoggingPhase = PipelinePhase("ResponseLogging")

        override fun install(pipeline: Application, configure: Configuration.() -> Unit): Logging {
            val configuration = Configuration().apply(configure)

            return Logging(configuration.logger).apply { install(pipeline) }
        }
    }
}

它适用于使用 DoubleReceive 插件记录请求正文。如果响应是纯文本,我可以将响应记录为 sendPipeline 拦截中的主题将是 TextContent 类型或类似于示例 ByteArrayContent 中的类型。

但就我而言,我正在使用 Jackson ContentNegotiation 响应数据类实例。在这种情况下,主题是 OutputStreamContent 类型,我看不到从中获取序列化正文的选项。

知道如何在我的日志记录功能中记录序列化响应 json 吗?或者也许还有另一个使用 ktor 服务器的选项?我的意思是我可以手动序列化我的对象并响应纯文本,但这是一种丑陋的方式。

【问题讨论】:

  • 你看到这个属性了吗? /** * 是否记录请求/响应负载。 * 警告:有效载荷可能包含敏感数据。 */ var logBody = false 。您还可以自定义记录器:ktor.io/docs/call-logging.html#format install(CallLogging) { format { call -> val status = call.response.status() val httpMethod = call.request.httpMethod.value val userAgent = call.request.headers[" User-Agent"] "状态:$status,HTTP 方法:$httpMethod,用户代理:$userAgent" } } 您也可以设置记录器级别。

标签: kotlin logging ktor


【解决方案1】:

我不确定这是否是最好的方法,但它是:

public fun ApplicationResponse.toLogString(subject: Any): String = when(subject) {
is TextContent -> subject.text
is OutputStreamContent -> {
    val channel = ByteChannel(true)
    runBlocking {
        (subject as OutputStreamContent).writeTo(channel)
        val buffer = StringBuilder()
        while (!channel.isClosedForRead) {
            channel.readUTF8LineTo(buffer)
        }
        buffer.toString()
    }
}
else -> String()

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-07
    • 1970-01-01
    • 2011-11-02
    • 1970-01-01
    • 1970-01-01
    • 2021-07-21
    • 1970-01-01
    相关资源
    最近更新 更多