Is it possible to get the matched route in a inter...
# ktor
j
Is it possible to get the matched route in a intercepting feature. For metrics purposes it would be good if I could get /user/{name} not user/Jozef for response time metrics?
šŸ“ 1
āœ… 1
d
Route has a
toString
method that you can use, or to help you see how to build your own string based on the tree: https://github.com/ktorio/ktor/blob/0a45746af0db0457a6e1e988c27d9364cf064962/ktor-server/ktor-server-core/src/io/ktor/routing/Route.kt#L98 An interceptor for a route would look like this: https://ktor.io/advanced/pipeline/route.html There you have access to the Route node tree
You can access to a Route from a call by casting the call to
RoutingApolicationCall
I have updated the doc to reflect this: https://ktor.io/advanced/pipeline/route.html#route-from-call
šŸ™Œ 1
v
@Deactivated User i just tried casting it, but i get the following error:
Copy code
java.lang.ClassCastException: io.ktor.server.jetty.JettyApplicationCall cannot be cast to io.ktor.routing.RoutingApplicationCall: Ljava/lang/ClassCastException;
d
can you show the relevant code plz?
v
https://gist.github.com/vonox7/2c61ca29cb059c67c101a4db092f5e03 Line 22 is always printing
null
, as the cast won’t succeed
the same is with
embeddedServer(Netty, ...)
d
(I’m asking, and checking myself)
but maybe you have to configure the phase to be explicitly after the Routing
our using the event: Routing.RoutingCallFinished (I’m checking)
Maybe for your case, this would be better?
Copy code
environment.monitor.subscribe(Routing.RoutingCallFinished) {
	println(it.route)
}
because you are not intercepting a route like the link I put
but trying to put a global interceptor
v
Never saw the subscribe-api šŸ˜„ The thing is: I don’t get callbacks for this when the route did not match
d
Mmm. I think with the other approach either if you plan to get the route. Maybe you can do a mixed approach
intercepting fallback
+ event subscribing
v
I’m logging all requests (request time and route) to analyze possible issues. An issue might be that the 95-percentile of a route is too high or that after a deployment the average count of non-matched routes gets too high
Are there some docs to read for ā€œintercepting fallbackā€?
d
Copy code
fun Application.registerMyRouteLogging() {
    fun log(path: String, handled: Boolean) {
        println("path=$path, handled=$handled")
    }

    environment.monitor.subscribe(Routing.RoutingCallFinished) { routingApplicationCall ->
        log(routingApplicationCall.route.toString(), handled = true)
    }
    intercept(ApplicationCallPipeline.Fallback) {
        log(call.request.uri, handled = false)
    }
}
v
Ok, but one problem with this approach is that i can’t log the processing time of the routing-handler…
d
Yes, you can. 1 sec
Copy code
val StartTimeAttribute = AttributeKey<Long>("StartTimeAttribute")

fun Application.registerMyRouteLogging() {
    fun log(call: ApplicationCall, path: String, handled: Boolean) {
        val elapsedTime = System.currentTimeMillis() - call.attributes[StartTimeAttribute]
        println("path=$path, handled=$handled, elapsedTime=$elapsedTime")
    }

    intercept(ApplicationCallPipeline.Infrastructure) {
        call.attributes.put(StartTimeAttribute, System.currentTimeMillis())
    }

    environment.monitor.subscribe(Routing.RoutingCallFinished) { call ->
        log(call, call.route.toString(), handled = true)
    }
    intercept(ApplicationCallPipeline.Fallback) {
        log(call, call.request.uri, handled = false)
    }
}
I guess it should be nice to update the Metrics feature: https://ktor.io/features/metrics.html to allow to configure it to measure final urls, routing urls, or both
in fact
I think it already does what you want
v
Wow, thanks, thats a very clean solution! Seems like I don’t understand the 3 phases of the application very much. Maybe you could create a small chart when what Phase is triggered? For me it seems that the Fallback-Phase is always triggered:
Copy code
path=/route/one/(method:GET), handled=true, elapsedTime=84
path=/route/one, handled=false, elapsedTime=84
d
First infrastructure, then call, then fallback in order until the call has been processed, usually that happens in call, but the fallback can also resolve it, (for example the StatusPages feature)
still, can’t you use the Metrics feature?
from what you said, it seems that it is what you are trying to do, and it is already done
if you miss something, we can add it
v
I already took a look into the Metrics feature, but I think I haven’t understood the power of it and the extensibility (ā€œOther reportersā€ section).
d
what do you need?
printing to the terminal?
where are you sending the reportS?
v
I’m sending the data to an InfluxDb where I analyze the data with Grafana
But it seems that creating a custom reporter is the way to go, thank you!
d
and you are sending raw requests, right?
okay
v
yes