如何覆盖 logRequest/logResponse 以在 Ktor 客户端日志记录中记录自定义消息?

Posted

技术标签:

【中文标题】如何覆盖 logRequest/logResponse 以在 Ktor 客户端日志记录中记录自定义消息?【英文标题】:How can I override logRequest/logResponse to log custom message in Ktor client logging? 【发布时间】:2021-01-24 21:33:58 【问题描述】:

目前,ktor client logging 实现如下,它按预期工作,但不是我想要的。


public class Logging(
    public val logger: Logger,
    public var level: LogLevel,
    public var filters: List<(HttpRequestBuilder) -> Boolean> = emptyList()
)
....
   private suspend fun logRequest(request: HttpRequestBuilder): OutgoingContent? 
        if (level.info) 
            logger.log("REQUEST: $Url(request.url)")
            logger.log("METHOD: $request.method")
        

        val content = request.body as OutgoingContent

        if (level.headers) 
            logger.log("COMMON HEADERS")
            logHeaders(request.headers.entries())

            logger.log("CONTENT HEADERS")
            logHeaders(content.headers.entries())
        

        return if (level.body) 
            logRequestBody(content)
         else null
    

上面在查看日志时会造成一场噩梦,因为它会在每一行中记录。由于我是 Kotlin 和 Ktor 的初学者,我很想知道如何改变这种行为。由于在 Kotlin 中,除非特别打开,否则所有类都是最终类,我不知道如何修改 logRequest 函数行为。我理想地想要实现的是下面的示例。

....
private suspend fun logRequest(request: HttpRequestBuilder): OutgoingContent? 

        ...
        if (level.body) 
            val content = request.body as OutgoingContent
        return logger.log(value("url", Url(request.url)),
                          value("method", request.method),
                          value("body", content))


    

任何帮助将不胜感激

【问题讨论】:

【参考方案1】:

没有办法真正覆盖非开放类中的私有方法,但如果您只是希望日志以不同的方式工作,最好使用管道中同一阶段的自定义拦截器:

       val client = HttpClient(CIO) 
            install("RequestLogging") 
                sendPipeline.intercept(HttpSendPipeline.Monitoring) 
                    logger.info(
                        "Request:    ",
                        context.method,
                        Url(context.url),
                        context.headers.entries(),
                        context.body
                    )
                
            
        
        runBlocking 
            client.get<String>("https://google.com")
        

这将产生您想要的日志记录。当然,要正确记录POST,您需要做一些额外的工作。

【讨论】:

以上是关于如何覆盖 logRequest/logResponse 以在 Ktor 客户端日志记录中记录自定义消息?的主要内容,如果未能解决你的问题,请参考以下文章

如何:获取代码覆盖率数据

你好,LABVIEW复制文件,如何做到不覆盖?

如何自动给文件命名,避免覆盖同名文件?

安卓软件升级软件如何覆盖旧版

如何在代码覆盖率报告 Laravel 8 中覆盖异常?

如何配置 SonarQube 让我们增加覆盖范围?