Skip to content

Distributed Tracing

OJS defines standardized distributed tracing conventions that enable end-to-end visibility across the full job lifecycle — from SDK client through backend to worker — even across languages and services.

This specification extends the Observability spec with detailed requirements for span naming, attributes, context propagation, and error recording.

All OJS spans follow the pattern {queue} {operation} for client-facing operations (per OTel messaging conventions) and ojs.{operation} for system operations.

OperationSpan NameSpan Kind
Enqueue{queue} enqueuePRODUCER
Batch enqueue{queue} enqueue_batchPRODUCER
Fetch{queue} fetchCONSUMER
Process{queue} processCONSUMER
Ackojs.ackCLIENT
Nackojs.nackCLIENT
Cancelojs.cancelCLIENT
OperationSpan NameSpan Kind
Scheduler pollojs.scheduler.pollINTERNAL
Cron triggerojs.cron.triggerINTERNAL
Dead worker reapojs.reaper.checkINTERNAL
Workflow advanceojs.workflow.advanceINTERNAL
Retry evaluationojs.retry.evaluateINTERNAL

Every OJS span MUST include:

AttributeTypeExample
messaging.systemstring"ojs"
ojs.job.idstring"019503e1-7b2a-..."
ojs.job.typestring"email.send"
ojs.job.queuestring"email"
AttributeTypeDescription
ojs.job.attemptintCurrent attempt number (1-indexed)
ojs.job.statestringJob state after the operation
ojs.worker.idstringWorker identifier

Required when the job is part of a workflow:

AttributeTypeDescription
ojs.workflow.idstringWorkflow identifier
ojs.workflow.typestringchain, group, or batch
ojs.workflow.stepintCurrent step (0-indexed)
AttributeTypeValues
ojs.backend.typestringredis, postgres, nats, kafka, sqs, lite
ojs.backend.versionstringImplementation version

OJS uses W3C Trace Context propagated through the job meta field to enable end-to-end tracing:

{
"type": "email.send",
"args": [{"to": "user@example.com"}],
"meta": {
"traceparent": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
"tracestate": "ojs=p:8;r:62"
}
}

When enqueuing a job, the SDK injects the current trace context into meta.traceparent.

When processing a job, the SDK extracts the trace context from meta.traceparent and creates a span link (not a parent-child relationship) to the enqueue span.

For workflow jobs, each step carries both the previous step’s trace context and the original workflow initiator’s context:

{
"meta": {
"traceparent": "00-4bf92f3577b34da6a3ce929d0e0e4736-a1b2c3d4e5f60718-01",
"ojs.workflow.trace_origin": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"
}
}

A complete OJS trace flows across three components:

Service A (HTTP handler)
└─ POST /api/signup (SERVER)
└─ email enqueue (PRODUCER)
│ injects meta.traceparent
└─ HTTP POST to OJS backend
OJS Backend
└─ ojs.enqueue (SERVER)
└─ store job
... time passes ...
Worker B
└─ email process (CONSUMER)
│ link → enqueue PRODUCER span
├─ user handler logic
└─ ojs.ack (CLIENT)
OutcomeStatus Code
Job completedOK
Job failed (retryable)ERROR
Job failed (discarded)ERROR
Job cancelledOK
Enqueue succeededOK
Enqueue failedERROR
Fetch timeout (no jobs)OK

On failure, spans record an error event via the OTel RecordError API with exception.type, exception.message, and optionally exception.stacktrace.

OJS supports W3C Baggage for passing cross-service context:

{
"meta": {
"traceparent": "00-...-01",
"baggage": "userId=12345,tenantId=acme"
}
}

Reserved OJS baggage keys: ojs.priority.override, ojs.trace.sample_rate, ojs.tenant.id.

All metrics use the ojs. prefix with OTel semantic conventions:

MetricTypeUnitDescription
ojs.job.enqueuedCounter{job}Total jobs enqueued
ojs.job.completedCounter{job}Jobs completed successfully
ojs.job.failedCounter{job}Jobs that failed
ojs.job.durationHistogramsProcessing duration
ojs.job.queue_timeHistogramsTime from enqueue to process
ojs.queue.depthGauge{job}Current jobs per queue/state
RequirementLevel
Inject/extract W3C traceparent via job metaRequired
Standard span naming ({queue} {operation})Required
Required span attributes on all spansRequired
Error recording with RecordErrorRequired
Workflow attributes when applicableRequired
Baggage propagationRecommended
Backend system spansRecommended