Ktor 不记录异常

Ktor doesn't log exceptions

Ktor (1.4.2) 似乎正在抑制异常。根据 documentation 我需要像这样重新抛出异常

install(StatusPages) {
    exception<Throwable> { ex ->
        val callstack: String = ....
        call.respond(HttpStatusCode.InternalServerError,
                ApiError(ex.javaClass.simpleName, ex.message ?: "Empty Message", callstack)
        )
        throw ex
    }
}

我围绕 Logger 接口编写了包装器以确保它正在调用 Logger.error()(它没有)并像这样配置它

install(CallLogging) {
            level = org.slf4j.event.Level.INFO
            logger = Log4j2Wrapper(logger2)
        }

我可以看到 INFO 级别的日志。我错过了什么?

原来问题出在ktor的相当笨拙的设计上api。我的发现总结:

与查看指定日志级别 及更高 的日志事件的普遍期望相反,CallLogging 并非如此。 It expects 日志记录级别完全匹配,最大限度地减少了此功能的用处。

您需要覆盖 ApplicationEnvironment.log 中指定的记录器。但是如果你按照官方的 ktor 例子去做的话

val server = embeddedServer(Netty, port) {
  applicationEngineEnvironment {
      log = YOUR_LOGGER
  }
}

它不会工作,因为函数 io.ktor.server.engine.defaultEnginePipeline(env) 中的值 call.application.environment 仍然是原始值,从配置文件或 NOP 记录器中的记录器名称创建。

因此您需要像这样初始化您的服务器

val env = applicationEngineEnvironment {
    log = YOUR_LOGGER
    module {
        install(CallLogging) {
            level = org.slf4j.event.Level.INFO
        }
        install(StatusPages) {
            exception<Throwable> { ex ->
                val callstack: String = ...
                call.respond(HttpStatusCode.InternalServerError,
                        ApiError(ex.javaClass.simpleName, ex.message ?: "Empty Message", callstack)
                )
                throw ex
            }
        }

        routing {
        }
    }

    connector {
        host = "0.0.0.0"
        port = ...
    }
}

val server = embeddedServer(Netty, env)