When using `HttpCallValidator` ```install(HttpCal...
# ktor
u
When using
HttpCallValidator
Copy code
install(HttpCallValidator) {
    validateResponse { response ->
        if (!response.status.isSuccess()) {
            throw ApiException(
                ...
            )
        }
    }
}
then when used prints
Copy code
16:56:43.963  W  sk.foo.net.ApiException: verb 'POST', path '/api/service/2.0.0', code '400', requestBody 'LOL', message 'ROFL'
                    at sk.foo.net.di.NetModule$baseKtorConfig$1$3$1.invokeSuspend(NetModule.kt:110)
                    at sk.foo.net.di.NetModule$baseKtorConfig$1$3$1.invoke(Unknown Source:8)
                    at sk.foo.net.di.NetModule$baseKtorConfig$1$3$1.invoke(Unknown Source:4)
                    at io.ktor.client.plugins.HttpCallValidator.validateResponse(HttpCallValidator.kt:51)
                    at io.ktor.client.plugins.HttpCallValidator.access$validateResponse(HttpCallValidator.kt:43)
                    at io.ktor.client.plugins.HttpCallValidator$Companion$install$3.invokeSuspend(HttpCallValidator.kt:152)
                    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
                    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
                    at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:111)
                    at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:99)
                    at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
i.e. no callsite reference. This means all requests that fail will throw from that line - meaning all stacktraces will point to same exact line. That is not really helpful for debugging & it messes up crashlytics grouping. Is there a way around that, other than having custom
bodyWithChecks()
and calling it manually everywhere?
u
Copy code
HttpClient(OkHttp) {
    developmentMode = true
    engine {
        preconfigured = okHttpClient
    }
    install(DefaultRequest) {
        url(EnvironmentConfig.baseApiUrl)
    }
    install(ContentNegotiation) {
        json(json)
    }
    install(HttpCallValidator) {
        validateResponse { response ->
            if (!response.status.isSuccess()) {
                throw ApiException(
                    ...
                )
            }
        }
    }
}
Am I doing it right? If so, then unfortunately, same stacktrace 😕
e
Thanks you for checking, it looks like a big between ktor and coroutines
u
does ktor manipulate stacktraces? since I've seen couple of odd things when having the
bodyWithMyChecks()
e
nope, it doesn't (except ktor-io module, which is not the case here)
It should work if
-ea
flag is provided
u
actually, the
developmentMode
fixed another issue for me, when having
bodyWithMyChecks
the functions needs to be inline due to reification, but the body is rather large for inling, so I did the usual thing
Copy code
suspend inline fun <reified T> HttpResponse.bodyWithMyChecks(): T {
    return bodyWithMyChecks(typeInfo<T>())
}

suspend fun <T> HttpResponse.bodyWithMyChecks(typeInfo: TypeInfo): T {
   ....
}
but using that instead of "big" inline, caused the stacktrace to be missing my callsites again
so..what does
devleopmentMode
actually do? how come it works as expected now?
would it be bad to turn that on for production? (crashlytics will collapse all the exceptions from callsites all over the app into single issue since the traces are the same
e
It disables some low level pipeline optimization which may erase plugins stack traces in certain cases
It usually ok to enable it if you have less than 20k rps
u
im a client
e
So it should be fine
u
gotcha, thanks!