OpenTelemetry Integration
A span per task execution with W3C trace context carried across enqueue and execution.
A span per task execution with W3C trace context carried across enqueue and execution.
Optional dependency: io.opentelemetry:opentelemetry-api (the SDK compiles
against it as compileOnly; add it to your build). FlexiQOtel is a
middleware that creates one OpenTelemetry
span per execution attempt and propagates trace context through the job, so a
trace that crosses an enqueue stays one trace.
import org.byteveda.flexiq.contrib.FlexiQOtel;
flexiq.use(new FlexiQOtel(openTelemetry));Each execution attempt starts a span from the tracer org.byteveda.flexiq:
flexiq.execute.<task>, kind CONSUMERflexiq.job_id, flexiq.task_nameOKERROR and the exception recordedstep.sleep ends the attempt with no status, the attribute
flexiq.slept=true, and a sleep event carrying flexiq.wake_atThe span is current while the handler runs, so spans and enqueues the handler makes are its children.
On enqueue, onEnqueue injects the current context into
EnqueueOptions.metadata as traceparent / tracestate, following the
merge rule on Trace context across SDKs.
At execution the context is extracted from the job's metadata, so the execute
span is a child of the enqueuer's span, whichever SDK enqueued it.
FlexiQOtel never configures an exporter or a tracer provider. Build the
OpenTelemetry instance the standard way, with a W3C propagator:
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
import io.opentelemetry.context.propagation.ContextPropagators;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import org.byteveda.flexiq.contrib.FlexiQOtel;
OpenTelemetrySdk otel = OpenTelemetrySdk.builder()
.setTracerProvider(SdkTracerProvider.builder()
.addSpanProcessor(BatchSpanProcessor.builder(OtlpGrpcSpanExporter.getDefault()).build())
.build())
.setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
.build();
flexiq.use(new FlexiQOtel(otel));The two-argument constructor adds a task filter:
flexiq.use(new FlexiQOtel(
otel,
task -> !task.startsWith("internal."))); // Predicate<String> task filter| Parameter | Type | Default | Description |
|---|---|---|---|
openTelemetry | OpenTelemetry | — | The instance your app configures; supplies the tracer and propagators |
taskFilter | Predicate<String> | all tasks | Return false to skip a task — applies to both enqueue injection and execute spans |
FlexiQObservation (see Micrometer)
remains the choice for metrics plus spans from one Micrometer
instrumentation. It does not propagate trace context across SDKs; use
FlexiQOtel for that.
EnqueueOptions has a public metadata() getter. In a middleware's
onEnqueue, EnqueueContext.metadata() is layered over the options metadata
when that is a JSON object (hook keys win) rather than replacing it.