Skip to content

Logging

Queuert emits structured log entries for every lifecycle event — worker start/stop, job creation, attempts, failures, completions, chain lifecycle, blockers, and adapter errors. Logging is part of queuert core and does not require the @queuert/otel package.

Pass a log function to createClient to receive log entries:

import { createClient, type Log } from "queuert";
const log: Log = (entry) => {
console.log(`[${entry.level}] ${entry.message}`, entry.data);
};
const client = await createClient({
stateAdapter,
notifyAdapter,
log,
jobTypeRegistry,
});

Every log entry is a typed object with the following shape:

{
type: string; // Machine-readable event identifier (e.g. "job_created")
level: LogLevel; // "info" | "warn" | "error"
message: string; // Human-readable description
data: { ... }; // Structured data specific to the event
error?: unknown; // Present only on error/warn entries that carry an error
}

All entries are strongly typed — the type field determines the exact shape of data, the level, and the message. This means consumers can switch on type for type-safe handling.

TypeLevelMessageData
worker_startedinfoStarted workerworkerId, jobTypeNames
worker_errorerrorWorker errorworkerId, error
worker_stoppinginfoStopping worker…workerId
worker_stoppedinfoWorker has been stoppedworkerId
TypeLevelMessageData
job_createdinfoJob createdid, typeName, chainId, chainTypeName, input, blockers, scheduledAt?, scheduleAfterMs?
job_completedinfoJob completedid, typeName, chainId, chainTypeName, status, attempt, output?, continuedWith?, workerId
job_reapedinfoReaped expired job leaseid, typeName, chainId, chainTypeName, leasedBy, leasedUntil, workerId
job_blockedinfoJob blocked by incomplete chainsid, typeName, chainId, chainTypeName, blockedByChains
job_triggeredinfoJob triggeredid, typeName, chainId, chainTypeName
job_unblockedinfoJob unblockedid, typeName, chainId, chainTypeName, unblockedByChain
TypeLevelMessageData
job_attempt_startedinfoJob attempt startedid, typeName, chainId, chainTypeName, status, attempt, workerId
job_attempt_completedinfoJob attempt completedid, typeName, chainId, chainTypeName, status, attempt, output?, continuedWith?, workerId
job_attempt_failederrorJob attempt failedid, typeName, chainId, chainTypeName, status, attempt, rescheduledAfterMs?, rescheduledAt?, workerId, error
job_attempt_taken_by_another_workerwarnJob taken by another workerid, typeName, chainId, chainTypeName, status, attempt, leasedBy, leasedUntil, workerId
job_attempt_already_completedwarnJob already completed by another workerid, typeName, chainId, chainTypeName, status, attempt, completedBy, workerId
job_attempt_lease_expiredwarnJob lease expiredid, typeName, chainId, chainTypeName, status, attempt, leasedBy, leasedUntil, workerId
job_attempt_lease_renewedinfoJob lease renewedid, typeName, chainId, chainTypeName, status, attempt, leasedBy, leasedUntil, workerId
TypeLevelMessageData
job_chain_createdinfoJob chain createdid, typeName, input
job_chain_completedinfoJob chain completedid, typeName, output
job_chain_deletedinfoJob chain deletedid, typeName
TypeLevelMessageData
notify_adapter_errorwarnNotify adapter erroroperation, error
state_adapter_errorwarnState adapter erroroperation, error
TypeLevelMessageData
job_type_validation_errorerror(dynamic)code, typeName, error, plus error-specific details

Log entry data fields compose from a few base shapes:

  • JobBasicDataid, typeName, chainId, chainTypeName
  • JobProcessingData — extends JobBasicData with status, attempt
  • JobChainDataid, typeName

The log function and the ObservabilityAdapter are independent. The internal ObservabilityHelper calls both on each event, ensuring logs and metrics/traces stay consistent. You can use either or both:

  • log only — structured logging without OTel dependency
  • ObservabilityAdapter only — metrics and traces without logging
  • Both — full observability
  • OTEL Metrics — OpenTelemetry counters, histograms, and gauges
  • OTEL Tracing — Span hierarchy and distributed tracing
  • Adapters — Overall adapter design philosophy