Tracing

Distributed-tracing seam — W3C trace-context propagation, OpenTelemetry-shaped span lifecycle, sampling routed through OTel when installed.

The framework keeps zero npm runtime deps, so the OTel SDK isn't bundled. b.tracing.create() detects @opentelemetry/api at first use: when it's installed, every span call flows into the operator's tracer (Jaeger / Zipkin / OTLP / console — whatever exporter they wired) and OTel's sampler decides per-span sampled flag from the configured TraceIdRatioBased / ParentBased rules. When OTel is absent every call falls through a pass-through tracer that still executes the wrapped function, propagates return values and exceptions, and emits no span data.

contextHeaders() and extractContext() always parse and emit the W3C traceparent format (00-<32-hex traceId>-<16-hex spanId>-<2-hex flags>) regardless of whether OTel is loaded — so operators get trace-ID per request as a free correlation baseline even without a tracer SDK. Span shape mirrors OTel: setAttribute / addEvent / recordException / setStatus / end / updateName.

b.tracing.tap("audit.record", attributes, fn) mirrors b.metrics.tap for tracing — wraps fn in a span if a registry is active, passes through otherwise. requestMiddleware() opens one span per inbound request, extracts any incoming traceparent, and promotes http.route to the matched route template at response time.

b.tracing.create(opts) #

stable0.4.0
{
  instrumentationName:    string,  // OTel tracer name; default "blamejs"
  instrumentationVersion: string,  // OTel tracer version; default "0.0.0"
}

Build a tracing registry. The returned registry exposes span, spanSync, currentSpan, setAttributes, recordException, contextHeaders / extractContext for W3C traceparent propagation, requestMiddleware() for per-request auto-spans, and tap() for framework hot-path wrapping. Detects @opentelemetry/api once at first use; without OTel installed the registry runs in pass-through mode but still propagates trace IDs over HTTP.

var t = b.tracing.create({
  instrumentationName:    "myapp",
  instrumentationVersion: "1.2.3",
});

var users = await t.span("load-users", async function (span) {
  span.setAttribute("user_id", "abc");
  span.addEvent("cache-miss");
  return await db.query("SELECT id, email FROM users");
}, { kind: "internal", attributes: { route: "/users" } });

// Outbound — propagate the active trace.
var headers = t.contextHeaders();
// → { traceparent: "00-<32 hex>-<16 hex>-01" } when a span is active

b.tracing.tap(name, attributes, fn) #

0.4.0

Framework hot-path tracing tap. Modules call tap("audit.record", { action: "login" }, fn) without importing a registry. Until b.tracing.create() runs the call passes fn(null) through directly (zero overhead, no span); afterwards the active registry wraps fn in a span named name with the supplied attributes. The two-arg form tap(name, fn) is permitted when no attributes are needed.

// Module-level — passthrough until a registry exists.
var rows = b.tracing.tap("db.query", { table: "users" }, function () {
  return db.queryAll("SELECT id FROM users");
});

// Two-arg — no attributes:
b.tracing.tap("queue.enqueue", function () { return enqueueJob(); });

Last updated 2026-08-08T16:39:49.652Z by seeder.