Observability

Carlquist is OpenTelemetry-native. Every request through the platform generates distributed traces, structured logs, and Prometheus-compatible metrics. Correlation IDs flow end-to-end from adapter query through delivery.

Distributed Tracing

Carlquist propagates W3C Trace Context (traceparent header) on all outbound requests. If your system sends a traceparent header, Carlquist creates child spans under your existing trace. If no trace context is provided, Carlquist generates a root trace automatically.

Every response also includes an X-Request-Id header for correlation in logs and support requests.

Trace Spans

Carlquist creates the following span hierarchy for each request flowing through the pipeline:

adapter.query          (source system query)
└── mapping.transform  (schema transformation)
    └── policy.evaluate (auth, rate limit, masking)
        └── delivery.send (target delivery)
            └── delivery.retry (if needed)

Span Attributes

Each span carries structured attributes for filtering and analysis:

Metrics

Carlquist exposes Prometheus-compatible metrics. All metrics use the carlquist_ prefix and include labels for filtering and aggregation.

MetricTypeDescription
carlquist_adapter_query_duration_secondshistogramAdapter query latency
carlquist_adapter_query_totalcounterTotal adapter queries (labels: adapter, status)
carlquist_delivery_duration_secondshistogramEnd-to-end delivery latency
carlquist_delivery_totalcounterDeliveries (labels: stream, target, status)
carlquist_delivery_retry_totalcounterRetry attempts (labels: stream, attempt)
carlquist_dlq_depthgaugeCurrent DLQ depth (labels: stream)
carlquist_mapping_duration_secondshistogramSchema transformation time
carlquist_policy_evaluation_duration_secondshistogramPolicy check time
carlquist_endpoint_request_totalcounterAPI endpoint requests (labels: path, method, status)
carlquist_endpoint_request_duration_secondshistogramAPI response time

Example Prometheus query for delivery error rate over the last hour:

rate(carlquist_delivery_total{status!="2xx"}[1h])
  / rate(carlquist_delivery_total[1h])

Structured Logs

All Carlquist logs are JSON-formatted with consistent fields across the platform:

{
  "timestamp": "2026-02-25T14:32:01.847Z",
  "level": "info",
  "message": "delivery.success",
  "request_id": "req_7f3a9b2c",
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "span_id": "00f067aa0ba902b7",
  "adapter": "orders-db",
  "stream": "orders.created",
  "delivery_target": "https://your-app.com/hooks/orders",
  "status_code": 200,
  "duration_ms": 142
}

Log levels follow standard severity:

Export

Traces

Export traces via OTLP/gRPC or OTLP/HTTP to your OpenTelemetry collector:

carlquist config set observability.traces.exporter otlp
carlquist config set observability.traces.endpoint \
  https://otel-collector.internal:4317

Metrics

Metrics are available via a Prometheus scrape endpoint at /metrics (Enterprise plans) or can be pushed to your OTLP endpoint:

carlquist config set observability.metrics.exporter otlp
carlquist config set observability.metrics.endpoint \
  https://otel-collector.internal:4317

Logs

Logs are written to stdout in containerized deployments. Forward them to your log aggregator (Datadog, Elastic, Splunk) using your container runtime's log driver or a sidecar collector.

Dashboard

Carlquist includes built-in observability views in the dashboard for:

Correlation: Every dashboard view supports filtering by request_id or trace_id, making it straightforward to investigate a single request across traces, metrics, and logs.