Skip to content

Observability

Every queue event the framework emits targets nest_rs::queue. One target, every transport-layer log filterable by RUST_LOG=nest_rs::queue=debug, every span attaching the same structured fields. The service-level logs your #[process] method emits keep their own target (e.g. features::audio) — same convention as the rest of the framework.

TargetWhatDefault level
nest_rs::queueFramework events: discovery, registration, job start/end, retries, fails.info on success, warn on retry, error on terminal failure.
nest_rs::transportBoot: attached module-contributed transport transport=QueueWorker.info.
features::<feature>Your service-level logs inside the #[process] method.Your call.

The level guarantee from the project’s posture: hot paths respect RUST_LOG=info. Per-job framework logs sit at info (one line per ack), debug lines exist for the dispatch path you only want under investigation. Failures are warn/error so they survive aggressive filtering.

Every framework log carries the same field set so a downstream processor can group, count, or alert without parsing strings:

FieldTypeNotes
processor&'static strThe processor host name, e.g. AudioProcessor::transcode.
queue&'static strThe Redis queue name.
concurrencyusizeFetch buffer (the in-flight ceiling), present on boot lines.
retriesusizeThe configured budget, present on boot lines.
job_idStringapalis-assigned id, present on per-job lines.
attemptu32Attempt counter (1 on first try).
elapsed_msu64Wall time of the handler call.

Prefer the structured form (queue = %name, job_id = %id) over formatted strings. The OTLP appender propagates them as span attributes.

Terminal window
2026-06-03T10:18:41Z INFO nest_rs::transport: attached module-contributed transport transport=QueueWorker
2026-06-03T10:18:41Z INFO nest_rs::queue: registered queue processor processor=AudioProcessor::transcode queue=audio concurrency=5 retries=3
2026-06-03T10:18:41Z DEBUG nest_rs::queue: skipped #[process] method: provider unreachable from app's module tree processor=ReportJobs::weekly queue=reports

Two lines per active processor (one attached, one registered) plus one debug skip for each #[process] method that compiled in but wasn’t imported into this app — useful to confirm a shared features crate isn’t accidentally activating handlers the binary doesn’t want.

A successful job, one info line at start, one at end:

Terminal window
2026-06-03T10:18:46Z INFO nest_rs::queue: job started processor=AudioProcessor::transcode queue=audio job_id=01HFEX… attempt=1
2026-06-03T10:18:46Z INFO features::audio: transcoded file=track-1717405126521.mp3
2026-06-03T10:18:46Z INFO nest_rs::queue: job ok processor=AudioProcessor::transcode queue=audio job_id=01HFEX… attempt=1 elapsed_ms=342

A retried job:

Terminal window
2026-06-03T10:19:02Z INFO nest_rs::queue: job started processor=AudioProcessor::transcode queue=audio job_id=01HFFA… attempt=1
2026-06-03T10:19:02Z WARN nest_rs::queue: job failed; retrying processor=AudioProcessor::transcode queue=audio job_id=01HFFA… attempt=1 elapsed_ms=12 error="connection refused"
2026-06-03T10:19:02Z INFO nest_rs::queue: job started processor=AudioProcessor::transcode queue=audio job_id=01HFFA… attempt=2
2026-06-03T10:19:02Z INFO nest_rs::queue: job ok processor=AudioProcessor::transcode queue=audio job_id=01HFFA… attempt=2 elapsed_ms=298

A job that exhausts its budget:

Terminal window
2026-06-03T10:19:30Z WARN nest_rs::queue: job failed; retrying processor=AudioProcessor::transcode queue=audio job_id=01HFFB… attempt=3 error="…"
2026-06-03T10:19:30Z ERROR nest_rs::queue: job failed; budget exhausted processor=AudioProcessor::transcode queue=audio job_id=01HFFB… attempts=4 error="…"

The error line is the one to alert on — the budget is gone, the job is now in apalis’s failed list, no further attempt is coming on its own.

The worker opens one span per job, target nest_rs::queue, name job. The handler runs inside it, so any tracing::info! your service emits is automatically tagged with the job’s job_id, processor, queue, attempt. The OTLP appender from nest-rs-opentelemetry exports them as span attributes — the OpenTelemetry / traces page covers attribute mapping. The corresponding log-to-OTLP path is in OpenTelemetry / logs.

Terminal window
RUST_LOG=info,nest_rs::queue=debug nestrs run dev worker

info everywhere, debug on the queue path: gives you the boot-time skip lines plus the per-job dispatch decisions without turning the rest of the framework loud.

Terminal window
RUST_LOG=nest_rs::queue=warn nestrs run dev worker

Strictly retries and failures — useful for tailing a healthy worker where the only thing you care about is “did anything go wrong.”