@moostjs/otel
@moostjs/otel integrates OpenTelemetry with Moost, providing automatic distributed tracing and metrics collection for every event your application handles. It hooks into Moost's context injector system to wrap each lifecycle phase — interceptors, argument resolution, handler execution — in spans, without any manual instrumentation in your handler code.
What you get
- Automatic spans for every event lifecycle phase (interceptors, arg resolution, handler call)
- Event duration metrics with route, event type, and error status attributes
- Trace propagation helpers for passing context to downstream services
- Custom span & metric attributes from within your handlers
- Selective filtering — suppress spans or metrics for health checks, internal endpoints, etc.
- Drop-in span processors that respect filtering decorators
Installation
npm install @moostjs/otel @opentelemetry/api @opentelemetry/sdk-trace-baseYou will also need an exporter for your tracing backend (Jaeger, Zipkin, OTLP, etc.):
# Example: OTLP exporter (works with Jaeger, Grafana Tempo, etc.)
npm install @opentelemetry/exporter-trace-otlp-httpQuick start
The only Moost-specific step is calling enableOtelForMoost() before creating your app. Everything else — tracer providers, exporters, span processors — is standard OpenTelemetry SDK configuration that varies by project and infrastructure.
TIP
The OpenTelemetry SDK setup below is just one possible configuration. Your project may use different providers, exporters, or initialization patterns depending on your tracing backend and deployment environment. Refer to the OpenTelemetry JS documentation for the full range of options.
import { Moost } from 'moost'
import { MoostHttp } from '@moostjs/event-http'
import { enableOtelForMoost, MoostBatchSpanProcessor } from '@moostjs/otel'
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'
// 1. Configure OpenTelemetry SDK (your setup may differ)
const provider = new NodeTracerProvider()
provider.addSpanProcessor(
new MoostBatchSpanProcessor(new OTLPTraceExporter())
)
provider.register()
// 2. Enable Moost instrumentation (before creating the app)
enableOtelForMoost()
// 3. Create and start your app as usual
const app = new Moost()
app.adapter(new MoostHttp()).listen(3000)
await app.init()Every incoming event now produces spans and metrics automatically — no decorator annotations needed on your handlers.
How it works
Incoming event
└─ Event:start span (wraps entire lifecycle)
├─ Interceptors:before
│ └─ Interceptor:MyGuard (per-interceptor span)
│ └─ Arguments:resolve (if interceptor has params)
├─ Arguments:resolve (handler params)
├─ Handler:/users/:id (handler execution)
└─ Interceptors:after
└─ Interceptor:MyGuard (per-interceptor span)Moost's context injector system powers this. When you call enableOtelForMoost(), it replaces the default no-op injector with a SpanInjector that wraps every lifecycle phase in an OpenTelemetry span. The injector also:
- Sets span attributes with controller name, handler method, route, and event type
- Records exceptions and sets error status on spans
- Collects event duration metrics via an OpenTelemetry histogram
- Applies custom attributes you add from handler code
What to read next
| Page | What you'll learn |
|---|---|
| Setup & Configuration | Full SDK setup, exporters, span processors, and @OtelIgnoreSpan / @OtelIgnoreMeter decorators |
| Automatic Spans | Every span Moost creates, their names, attributes, and how they map to the event lifecycle |
| Composables | useOtelContext(), useSpan(), useOtelPropagation(), child spans, and custom attributes |
| Metrics | Auto-collected duration histogram, recorded attributes, and custom metric attributes |