Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ktor doesn't log exceptions

Ktor (1.4.2) seems to be suppresing exceptions. According to documentation I need to re-throw exception like this

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

I wrote wrapper around Logger interface to make sure it's calling Logger.error() (it doesn't) and configured it like this

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

I can see INFO-level logs. What am I missing ?

like image 362
expert Avatar asked Oct 22 '25 02:10

expert


1 Answers

Turned out the problem is in rather akward design of ktor api. Summary of my findings:

Contrary to common expectation to see log events of specified log level and above it doesn't that way with CallLogging. It expects exact match of the logging level which minimizes usefulness of this feature.

You need to overwrite logger specified in ApplicationEnvironment.log. But if you follow official ktor examples and do it like this

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

it won't work because value call.application.environment inside function io.ktor.server.engine.defaultEnginePipeline(env) is still original one, created from logger name in config file or NOP logger.

Hence you'll need to initialize your server like this

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)
like image 50
expert Avatar answered Oct 24 '25 21:10

expert



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!