Skip to content

Observability and health

Export Immediate.Jobs traces, metrics and structured logs, and register scheduler health checks.

2 min read

Immediate.Jobs exposes both an ActivitySource and Meter named Immediate.Jobs:

builder.Services.AddOpenTelemetry()
	.WithTracing(tracing => tracing.AddSource("Immediate.Jobs"))
	.WithMetrics(metrics => metrics.AddMeter("Immediate.Jobs"));

Each execution creates a consumer activity named job {job.name} with job.name, job.queue, job.id and job.attempt. Enqueue trace context is persisted and linked to the execution rather than used as its parent, so asynchronous work remains causally visible without pretending to be a single synchronous span. The execution trace/span IDs and start time are persisted for dashboard links.

Metrics

InstrumentType/unitTags
jobs.enqueuedCounterjob.name, job.queue
jobs.succeededCounterjob.name, job.queue
jobs.failedCounterjob.name, job.queue
jobs.retriedCounterjob.name, job.queue
job.durationHistogram, secondsjob.name, job.queue, outcome
queue.depthObservable gaugenone
workers.activeObservable gaugenone

The gauges are local runtime observations, not authoritative cluster totals. Use provider monitoring snapshots for durable/cluster state. Alert on growing queue depth, exhausted failures, retries and stale server heartbeats; interpret duration by job name and outcome.

Structured logs

Worker logs carry the scope properties JobName, QueueName, JobId and Attempt. Events cover scheduler iteration failure, shutdown-drain timeout, unhandled worker errors, completion, retry, attempt exhaustion and disabled optional capabilities. Include scopes in the logging exporter to make these fields queryable.

Health checks

builder.Services.AddMyAppJobs(options => options.UseEntityFrameworkCore<AppDbContext>())
	.AddHealthCheck(name: "my-app-jobs", tags: ["ready"]);

app.MapHealthChecks("/health/ready");

The check combines scheduler liveness with provider connectivity. Choose a failureStatus when degraded versus unhealthy behavior matters to orchestration. The Aspire sample uses the same OpenTelemetry sources, health registration and dashboard telemetry-link hooks; Immediate.Jobs does not require Aspire and does not ship an Aspire-specific runtime package.