# ktor


08/10/2020, 9:26 AM
Hey everyone, not sure if this is the right place to ask (my apologies if this is not the right place) - has anyone tried using Koin with Ktor, and creating a scope that lasts for the duration of a request? For example, if I wanted to be able to inject something like a trace id, how would I go about doing that? Thanks!

Eric Grimsborn

08/10/2020, 10:19 AM
Not sure about Koin but I use this for traceId:


08/10/2020, 11:05 AM
Yep, I'm aware of CallId, but I would like to attach more than just a call id, and be able to use it from areas of code that are not dependent on Ktor classes/functions

Eric Grimsborn

08/10/2020, 12:10 PM
Could you do something like
Copy code
import io.ktor.application.ApplicationCall
import io.ktor.application.ApplicationCallPipeline
import io.ktor.application.ApplicationFeature
import io.ktor.util.AttributeKey
import io.ktor.util.pipeline.PipelineContext

class DiInstance

val DIAttributeKey = AttributeKey<DiInstance>("dependency-injection")

class DIFeature(val configuration: Configuration) {
    class Configuration {
        var di: DiInstance? = null

    // Body of the feature
    private fun intercept(context: PipelineContext<Unit, ApplicationCall>) {
        // Make the di instance avaliable on the call
        configuration.di?.let {
  , it)

    companion object Feature : ApplicationFeature<ApplicationCallPipeline, Configuration, DIFeature> {
        override val key = AttributeKey<DIFeature>("DI Feature")
        override fun install(pipeline: ApplicationCallPipeline, configure: Configuration.() -> Unit): DIFeature {

            // Call user code to configure a feature
            val configuration = Configuration().apply(configure)
            if (configuration.di == null) {
                throw  IllegalStateException("Must supply instance of DI")
            // Create a feature instance
            val feature = DIFeature(configuration)

            // Install an interceptor that will be run on each call and call feature instance
            pipeline.intercept(ApplicationCallPipeline.Call) {

            // Return a feature instance so that client code can use it
            return feature

 * install(DIFeature){
 *     di = DiInstance()
 * }
Then you can:
Copy code
val di: DiInstance = call.attributes[DIAttributeKey]
in your request handlers


08/11/2020, 12:35 AM
Thank you for sharing this! I did try out something similar. Problem is, if I have a class which executes database queries, that does not have access to
, I wouldn't be able to inject request specific stuff in there. If I had access to
, I wouldn't need the DI at all - I'd use
directly as you've done above.


08/12/2020, 7:49 AM
“be able to use it from areas of code that are not dependent on Ktor classes/functions” this sounds like you can extract CallId from route definition and send it through your architecture as any other parameter. How is your code structured? do you have any architecture?