Skip to content

Debug Tracing

A request returns an unexpected status code and you need to identify which middleware in the pipeline rejected it.

Enable debug mode to populate a _trace object on error responses. The trace shows which middleware ran and which one triggered the pipeline break.

import http from 'node:http';
import {
handler, compose, logger, authorization, body,
} from '@centralping/ergo';
const pipeline = compose(
logger(),
authorization({strategies}),
body(),
(req, res, acc) => ({
response: {body: acc.body.parsed, statusCode: 200},
}),
);
const server = http.createServer(
handler(pipeline, {debug: true}),
);
server.listen(3000);

When a request is rejected (e.g. missing authorization), the error response body includes a _trace field:

{
"type": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401",
"title": "Unauthorized",
"status": 401,
"_trace": {
"steps": ["log", "auth"],
"breakAt": "auth"
}
}

When debug is true, the pipeline initializes a trace object on the response accumulator before running middleware:

responseAcc._trace = {steps: [], breakAt: undefined};

As each middleware executes, its label (the intrinsic setPath on built-in middleware, an explicit setPath on custom {fn, setPath} wrappers, or the function name) is pushed onto steps. When a middleware sets responseAcc.statusCode and triggers a pipeline break, breakAt records that middleware’s label.

Field Type Description
steps string[] Middleware labels in execution order
breakAt string | undefined Label of the middleware that caused the pipeline break

_trace is not in send()’s reserved key set. On error responses (statusCode ≥ 400), it appears as an RFC 9457 extension member in the response body alongside type, title, status, and detail. On success responses (2xx), _trace is not included in the body.

When debug is false (the default), no trace object is created and the pipeline skips all label-tracking logic. There is no performance cost in production.

Pipeline debug tracing (_trace) is unrelated to the OpenTelemetry tracing middleware. OTel tracing populates domainAcc.trace with distributed trace context (trace ID, span ID) for production observability. Debug tracing populates responseAcc._trace with pipeline execution details for local debugging. Both can be active simultaneously without conflict.