Skip to content

Traces

BullMQ provides comprehensive distributed tracing support through OpenTelemetry. Traces allow you to track the flow of jobs through your system, identify bottlenecks, and debug issues across distributed services.

Enabling Traces

To enable tracing, pass a telemetry instance when creating Queue, Worker, or FlowProducer:

typescript
import { Queue, Worker } from 'bullmq';
import { BullMQOtel } from 'bullmq-otel';

const telemetry = new BullMQOtel({
  tracerName: 'my-app',
  version: '1.0.0',
});

const queue = new Queue('myQueue', {
  connection: {
    host: '127.0.0.1',
    port: 6379,
  },
  telemetry,
});

const worker = new Worker(
  'myQueue',
  async job => {
    return 'some value';
  },
  {
    connection: {
      host: '127.0.0.1',
      port: 6379,
    },
    telemetry,
  },
);

Span Kinds

BullMQ uses different span kinds to categorize operations:

Span KindDescription
PRODUCEROperations that add jobs to a queue (producing work)
CONSUMEROperations that process jobs from a queue (consuming work)
INTERNALInternal operations like pausing, resuming, or managing queue state

Available Traces

BullMQ automatically creates spans for the following operations:

Queue Class

OperationSpan NameSpan KindDescription
add{queueName}.addPRODUCERAdding a single job to the queue
addBulk{queueName}.addBulkPRODUCERAdding multiple jobs to the queue
pause{queueName}.pauseINTERNALPausing the queue
resume{queueName}.resumeINTERNALResuming the queue
close{queueName}.closeINTERNALClosing the queue connection
rateLimit{queueName}.rateLimitINTERNALSetting rate limit on the queue
removeRepeatable{queueName}.removeRepeatableINTERNALRemoving a repeatable job by options
removeRepeatableByKey{queueName}.removeRepeatableByKeyINTERNALRemoving a repeatable job by key
removeDebounceKey{queueName}.removeDebounceKeyINTERNALRemoving a debounce key
removeDeduplicationKey{queueName}.removeDeduplicationKeyINTERNALRemoving a deduplication key
remove{queueName}.removeINTERNALRemoving a job from the queue
updateJobProgress{queueName}.updateJobProgressINTERNALUpdating job progress
drain{queueName}.drainINTERNALDraining the queue
clean{queueName}.cleanINTERNALCleaning jobs from the queue
obliterate{queueName}.obliterateINTERNALObliterating the queue (all data)
retryJobs{queueName}.retryJobsPRODUCERRetrying failed jobs
promoteJobs{queueName}.promoteJobsINTERNALPromoting delayed jobs
trimEvents{queueName}.trimEventsINTERNALTrimming events from the queue

Worker Class

OperationSpan NameSpan KindDescription
getNextJob{queueName}.getNextJobINTERNALFetching the next job to process
rateLimit{queueName}.rateLimitINTERNALWorker rate limiting
processJob{queueName}.{jobName}CONSUMERProcessing a job (main processor span)
pause{queueName}.pauseINTERNALPausing the worker
resume{queueName}.resumeINTERNALResuming the worker
close{queueName}.closeINTERNALClosing the worker
startStalledCheckTimer{queueName}.startStalledCheckTimerINTERNALStarting stalled job check timer
moveStalledJobsToWait{queueName}.moveStalledJobsToWaitINTERNALMoving stalled jobs back to waiting
extendLocks{queueName}.extendLocksINTERNALExtending locks on active jobs

Job Class

OperationSpan NameSpan KindDescription
moveToCompleted{queueName}.completeINTERNALCompleting a job successfully
moveToFailed{queueName}.{state}INTERNALJob failure handling (state: fail, delay, retry)

JobScheduler Class

OperationSpan NameSpan KindDescription
add{queueName}.upsertJobSchedulerPRODUCERUpserting a job scheduler

FlowProducer Class

OperationSpan NameSpan KindDescription
add{queueName}.addFlowPRODUCERAdding a flow (tree of jobs)
addBulkaddBulkFlowsPRODUCERAdding multiple flows
addNode{queueName}.addNodePRODUCERAdding a node in a flow (internal)

Trace Attributes

Traces include various attributes for filtering and debugging:

Common Attributes

AttributeKeyDescription
Queue Namebullmq.queue.nameName of the queue
Queue Operationbullmq.queue.operationType of operation being performed

Job Attributes

AttributeKeyDescription
Job Namebullmq.job.nameName of the job
Job IDbullmq.job.idUnique identifier of the job
Job Keybullmq.job.keyRedis key of the job
Job IDsbullmq.job.idsMultiple job IDs (bulk ops)
Job Optionsbullmq.job.optionsSerialized job options
Job Progressbullmq.job.progressCurrent job progress value
Job Typebullmq.job.typeType/state of the job
Job Attempts Madebullmq.job.attempts.madeNumber of attempts made
Job Resultbullmq.job.resultResult returned by the job
Job Failed Reasonbullmq.job.failed.reasonReason for job failure
Job Attempt Finishedbullmq.job.attempt_finished_timestampWhen the processing attempt ended
Job Finished Timestampbullmq.job.finished.timestampWhen the processing attempt ended (deprecated)
Job Processed Timestampbullmq.job.processed.timestampWhen the job was processed
Deduplication Keybullmq.job.deduplication.keyDeduplication key if set

Bulk Operation Attributes

AttributeKeyDescription
Bulk Countbullmq.job.bulk.countNumber of jobs in bulk operation
Bulk Namesbullmq.job.bulk.namesComma-separated job names

Worker Attributes

AttributeKeyDescription
Worker Namebullmq.worker.nameName of the worker
Worker IDbullmq.worker.idUnique identifier of the worker
Worker Optionsbullmq.worker.optionsSerialized worker options
Worker Rate Limitbullmq.worker.rate.limitRate limit duration
Do Not Wait Activebullmq.worker.do.not.wait.activeWhether to wait for active jobs
Force Closebullmq.worker.force.closeWhether closing is forced
Stalled Jobsbullmq.worker.stalled.jobsNumber of stalled jobs detected
Failed Jobsbullmq.worker.failed.jobsNumber of failed stalled jobs
Jobs to Extend Locksbullmq.worker.jobs.to.extend.locksJobs needing lock extension

Queue Operation Attributes

AttributeKeyDescription
Drain Delaybullmq.queue.drain.delayWhether to delay drain
Grace Periodbullmq.queue.graceGrace period for clean op
Clean Limitbullmq.queue.clean.limitMaximum jobs to clean
Clean Countbullmq.queue.clean.countNumber of jobs cleaned
Rate Limitbullmq.queue.rate.limitRate limit settings
Queue Optionsbullmq.queue.optionsSerialized queue options
Event Max Lengthbullmq.queue.event.max.lengthMaximum event stream length

Flow Attributes

AttributeKeyDescription
Flow Namebullmq.flow.nameName of the flow

Scheduler Attributes

AttributeKeyDescription
Job Scheduler IDbullmq.job.scheduler.idID of the job scheduler

Context Propagation

BullMQ automatically propagates trace context when jobs are added and processed. This allows you to track jobs across services:

  1. Producer side: When adding a job, the trace context is captured and stored with the job data
  2. Consumer side: When processing a job, the trace context is extracted and used to continue the trace

Controlling Context Propagation

You can control context propagation per job using the telemetry job option:

typescript
// Include trace context (default behavior)
await queue.add('job', data);

// Explicitly include context
await queue.add('job', data, {
  telemetry: {
    omitContext: false,
  },
});

// Omit trace context (start fresh trace when processing)
await queue.add('job', data, {
  telemetry: {
    omitContext: true,
  },
});

// Provide custom metadata
await queue.add('job', data, {
  telemetry: {
    metadata: customContextData,
  },
});

Exporting Traces

To export traces to an observability backend, configure an OpenTelemetry trace exporter:

typescript
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { trace } from '@opentelemetry/api';

// Configure the trace exporter
const traceExporter = new OTLPTraceExporter({
  url: 'http://localhost:4318/v1/traces',
});

const provider = new NodeTracerProvider();
provider.addSpanProcessor(new SimpleSpanProcessor(traceExporter));
provider.register();

// Now BullMQOtel will automatically use the registered provider

Example Trace Visualization

When properly configured, you can see traces in your observability platform showing the complete lifecycle of jobs:

├─ myQueue.add (PRODUCER)
│  └─ myQueue.myJob (CONSUMER)
│     └─ myQueue.complete (INTERNAL)

For flows with parent-child relationships:

├─ myQueue.addFlow (PRODUCER)
│  ├─ childQueue.addNode (PRODUCER)
│  │  └─ childQueue.childJob (CONSUMER)
│  │     └─ childQueue.complete (INTERNAL)
│  └─ parentQueue.addNode (PRODUCER)
│     └─ parentQueue.parentJob (CONSUMER)
│        └─ parentQueue.complete (INTERNAL)

Released under the MIT License.