just wanted to share this little cool snippet. Sup...
# coroutines
a
just wanted to share this little cool snippet. Super easy to add a very simple homemade function that logs an error if a database query (or any async operation, really) takes more than 10 seconds 🙂 Coroutines ftw!
Copy code
suspend fun <T> CoroutineScope.logSlowQueries(
    timeoutSeconds: Long?,
    block: suspend () -> T
): T {
    val slowQueryDetectorJob = async {
        delay(Duration.ofSeconds(timeoutSeconds ?: 10))
        val otelCtx = Span.current().spanContext

        if (otelCtx.isValid) {
            log.error("Query not completed after $timeoutSeconds seconds - traceId=${otelCtx.traceId} spanId=${otelCtx.spanId}")
        } else {
            log.error("Query not completed after $timeoutSeconds seconds - NO OTEL CTX AVAILABLE")
        }
    }

    return try {
        block()
    } finally {
        slowQueryDetectorJob.cancel()
    }
}
mother of god 2
s
I'm a little late to the party, but wouldn't using something like
measureTimedValue
be much simpler for the purpose or am I missing something?
Copy code
inline fun <T> logSlowQueries(
    timeoutSeconds: Long = 10,
    block: suspend () -> T
): T {
    val (result, duration) = measureTimedValue { block() }
    if (duration > timeoutSeconds.seconds) {
        [logging]
    }
    return result
}
Also, above function would work both for coroutines and normal sync code due to being
inline
a
cool, never heard of
measureTimedValue
👍
I like the idea that it logs immediately after 10 seconds though, and doesn’t wait until the query has fully completed and then logs, in case it waits for multiple minutes
👍 1
s
aaah yeah you're right, I must had been tired that I missed it 😄
l
This shouldn't be an extension of
CoroutineScope
. wrap the function content with a local
coroutineScope { … }
instead.