@spanhq/bullmq
v0.1.0
Published
Distributed tracing SDK for BullMQ background jobs
Maintainers
Readme
@spanhq/bullmq
Distributed tracing SDK for BullMQ background jobs. Automatically captures job execution traces, retry timelines, and failure details without modifying your processor code.
Installation
npm install @spanhq/bullmq
# or
bun add @spanhq/bullmq
# or
yarn add @spanhq/bullmqPeer dependency: bullmq >= 4.0.0
Quick Start
import { createTracer } from '@spanhq/bullmq'
import { Worker, Queue } from 'bullmq'
const tracer = createTracer({ apiKey: 'jt_live_xxxx' })
const worker = tracer.traceWorker(new Worker('my-queue', async (job) => {
// your existing processor logic — no changes needed
}, { connection: redis }))
const queue = tracer.traceQueue(new Queue('my-queue', { connection: redis }))
// On shutdown:
process.on('SIGTERM', async () => {
await tracer.shutdown()
process.exit(0)
})That's it. Every job processed by the worker will automatically generate tracing spans.
API Reference
createTracer(config)
Creates a new tracer instance.
const tracer = createTracer({
apiKey: 'jt_live_xxxx', // required
endpoint: 'https://api.spanhq.dev', // optional (default: production)
debug: false, // optional (default: false)
})| Option | Type | Required | Default | Description |
|------------|----------|----------|----------------------------------|---------------------------------|
| apiKey | string | Yes | process.env.SPANHQ_API_KEY | Your project API key |
| endpoint | string | No | https://api.spanhq.dev | Backend URL (for self-hosted) |
| debug | boolean| No | false | Enable console logging |
tracer.traceWorker(worker)
Instruments a BullMQ Worker to capture lifecycle events.
const worker = tracer.traceWorker(new Worker('queue', processor, opts))Events captured:
active— Job starts processing. Generates trace ID if not inherited.completed— Job finishes successfully. Records duration.failed— Job fails. Records error message and stack trace. Marks asdeadif all retries exhausted.stalled— Job stalled. Records as a failure event.
Returns the same worker instance (pass-through).
tracer.traceQueue(queue)
Instruments a BullMQ Queue to propagate trace context to child jobs.
const queue = tracer.traceQueue(new Queue('child-queue', opts))When queue.add() is called inside a traced worker processor, the SDK automatically injects __trace_id and __parent_id into the child job's data. This enables distributed trace propagation across job chains.
Returns the same queue instance (pass-through).
tracer.shutdown()
Gracefully shuts down the tracer. Flushes all buffered spans to the backend.
await tracer.shutdown()Important: Always await shutdown() before exiting the process to prevent span loss.
How Trace Context Propagation Works
Job A (Worker 1)
└─ queue.add('child-job', data)
└─ Job B (Worker 2) ← inherits trace_id from Job A
└─ queue.add('grandchild', data)
└─ Job C (Worker 3) ← inherits trace_id from Job A- When a root job starts, the SDK generates a unique
trace_id - If the worker processor calls
queue.add(), the SDK injects__trace_idand__parent_idinto the child job data - When the child job starts, the SDK reads
__trace_idfrom the job data and continues the trace - This works across any number of job chain levels
AsyncLocalStorage: The SDK uses Node.js AsyncLocalStorage to maintain context across async boundaries within a single worker processor execution.
Batching & Performance
- Spans are buffered in memory and flushed every 2 seconds
- If the buffer reaches 10 spans, an immediate flush is triggered
- The SDK never blocks your job processing
- All network errors are silently caught (logged in debug mode)
Environment Variables
| Variable | Description |
|-----------------------|------------------------------------------|
| SPANHQ_API_KEY | API key (alternative to config) |
| SPANHQ_ENDPOINT | Backend URL (alternative to config) |
Safety Guarantees
The SDK is designed to never crash your application:
- All event handlers are wrapped in try-catch blocks
- Network failures are silently caught and optionally logged
- The SDK uses fire-and-forget for span delivery
- If the backend is unreachable, spans are dropped (not queued indefinitely)
- The
traceWorkerandtraceQueuefunctions return the original instances
Troubleshooting
Spans not appearing in the dashboard
- Check your API key: Ensure
apiKeyis correct and the project exists - Enable debug mode: Set
debug: trueto see SDK logs in the console - Check the endpoint: If self-hosted, ensure
endpointpoints to your backend - Verify network access: The SDK needs to reach the backend via HTTP POST
Debug mode output
const tracer = createTracer({ apiKey: '...', debug: true })Debug mode logs:
- Every span buffered
- Every flush (with span count)
- Backend responses
- Errors (network, validation, etc.)
Self-hosted setup
const tracer = createTracer({
apiKey: 'jt_live_xxxx',
endpoint: 'http://localhost:3000',
})License
MIT
