Skip to content

Limitations

This page documents known limitations of Tracy and recommended workarounds.

Span Context Propagation

OpenTelemetry context propagation works automatically in structured coroutines (e.g., withContext, launch, async). However, certain concurrency patterns create execution boundaries that require manual context propagation.

For complete examples, see ContextPropagationExample.kt.

Kotlin Coroutines with runBlocking

Using runBlocking inside a suspend function creates a new execution boundary. Without manual propagation, child spans become detached and appear as separate traces.

Workaround: Use currentSpanContextElement to propagate context:

@Trace
suspend fun handleRequestInCoroutine(requestId: String) {
    // runBlocking without context propagation would detach the trace
    runBlocking(currentSpanContextElement(currentCoroutineContext())) {
        processUserRequest(requestId)
    }
}

Multi-Threading

Threads created via thread { ... } do not inherit the OpenTelemetry context.

Workaround: Capture and propagate the context manually:

suspend fun handleRequestInThread() {
    val context = currentSpanContext(currentCoroutineContext())
    thread {
        context.makeCurrent().use {
            // Code here will be part of the same trace
        }
    }
}

Local Functions

The @Trace annotation should not be used on local (nested) functions:

fun outer() {
    @Trace  // Not supported
    fun inner() { /* ... */ }
}

Reason: References to local functions do not implement the KCallable interface correctly in Kotlin. See KT-64873.

Inline Lambda Parameters

When tracing inline functions, inline lambda parameters are replaced with null in the captured arguments array.

Reason: Inline lambdas do not exist as objects at runtime — they are inlined directly into the call site.

Java Interoperability

The Tracy compiler plugin only transforms Kotlin code. Java methods cannot be annotated with @Trace.

Workaround: Use Manual Tracing for Java code:

import org.jetbrains.ai.tracy.core.instrumentation.processor.TracingUtilsKt;

public class MyService {
    public String process(String input) {
        return TracingUtilsKt.withSpan("process", span -> {
            // Your code here
            return "result";
        });
    }
}