OpenTelemetry
Distributed tracing — each procedure call becomes a span with automatic error recording.
OpenTelemetry (OTel) is the standard for distributed tracing. Katman's otelWrap creates a span for each procedure call, so you can see every RPC call in your tracing dashboard (Jaeger, Zipkin, Honeycomb, Datadog, etc.).
How it works
otelWrap is a wrap middleware. It creates a span, runs your procedure inside it, then closes the span. If the procedure throws, the span records the error before rethrowing.
Setup
Install OpenTelemetry
npm install @opentelemetry/apiYou'll also need an OTel SDK and exporter for your backend (Jaeger, OTLP, etc.) — but that's standard OTel setup, not Katman-specific.
Create the wrap
import { } from "katman/otel"
import { } from "@opentelemetry/api"
const = (.getTracer("my-service"))Add it to procedures
const = k.query({
: [tracing],
: ({ }) => .db.users.findMany(),
})
const = k.mutation({
: [auth, tracing],
: ({ , }) => .db.users.create(),
})Each call to these procedures now produces a span in your tracing backend.
What gets recorded
Every span includes:
| Attribute | Value |
|---|---|
rpc.system | "katman" |
| Status code | 0 (OK) on success, 2 (ERROR) on failure |
On errors, the span also includes an exception event:
Event: exception
exception.message: "Not found"This means errors are automatically visible in your tracing dashboard — you don't need to add manual error reporting to each procedure.
Custom span name
The default span name is "rpc.call". You can change it:
import { } from "katman/otel"
const = (tracer, "api.procedure")Combining with other middleware
otelWrap is a regular wrap middleware. Stack it with guards and other wraps normally:
const = k.mutation({
: [auth, rateLimit, tracing],
// guards first, then wraps
: ({ , }) => .db.users.create(),
})Guards (auth, rateLimit) run before the span wraps around the resolver. If you want the span to include guard execution time, put tracing before the guards in the array.
Katman has zero OpenTelemetry dependency. The plugin defines a lightweight Tracer and Span interface. You bring @opentelemetry/api yourself, which means Katman never pins you to a specific OTel version.
What's next?
- Pino Logging — structured logging for requests and responses
- Middleware — learn about guards and wraps
- Plugins — all available plugins