Skip to content

Schedule Observability

Structured Log Events

All log events are emitted via IAppLoggerService as structured JSON.

Event keyLevelWhenKey fields
schedule.enqueuedINFOJob accepted and enqueuedscheduledJobId, topic, kind, runAt/pattern, correlationId, clientRequestId
schedule.firedINFOWorker callback enteredscheduledJobId, topic, attempt, maxAttempts, drift_seconds
schedule.completedINFOJob finishes successfullyscheduledJobId, topic
schedule.cancelledINFOcancel() completesscheduledJobId, topic, cancelledAt
schedule.no_listenerWARNFired but no listener registered for the topicscheduledJobId, topic, attempt
schedule.retryWARNWorker threw; BullMQ will retryscheduledJobId, topic, attempt, maxAttempts, error
schedule.failed.terminalERRORmaxAttempts exhaustedscheduledJobId, topic, attempts, lastError
schedule.rescheduledINFOreschedule() completesoldJobId, newJobId, topic
schedule.reconciler.summaryINFOBoot reconciler finishesscanned, healed, skipped

Metrics

All metrics use the app_ prefix following the project convention (via getAppMeter(appConfigService)).

Metric nameTypeLabelsDescription
app_schedule_job_enqueued_totalCountertopic, kindJobs successfully enqueued
app_schedule_job_fired_totalCountertopicWorker callback entered
app_schedule_job_failed_totalCountertopic, terminalWorker failures; terminal=true after last attempt
app_schedule_job_no_listener_totalCountertopicFirings with no registered listener
app_schedule_job_drift_secondsHistogramtopic, kindSeconds between originalScheduledAt and firedAt
app_schedule_job_listener_duration_secondsHistogramtopicWall-clock time of emitAsync (all listeners)

Tracing Spans

Spans are created via TracingService.runInSpan. W3C traceparent is stored in the BullMQ job data so that the worker span can be linked to the original enqueue span.

Span nameKindWhere
schedule.enqueue.one_shotPRODUCERScheduleAtUseCase.execute
schedule.enqueue.repeatPRODUCERScheduleRepeatUseCase.execute
schedule.cancelPRODUCERCancelScheduleUseCase.execute
schedule.reschedulePRODUCERRescheduleUseCase.execute
schedule.processCONSUMERScheduleProcessor.process (root)
schedule.listener.emitINTERNALInside process, wrapping emitArrived
schedule.reconciler.bootstrapINTERNALScheduleReconcilerService.onApplicationBootstrap

Standard attributes on enqueue spans: messaging.system="bullmq", messaging.destination="schedule", messaging.message.name=<topic>, schedule.kind, schedule.timezone, app.correlation_id.