OTel tracing adapter
otelTracer(...) is the production-grade tracer. It bridges the
framework’s Tracer
interface to the OpenTelemetry API, so spans flow to whatever
backend you’ve configured (Jaeger, Tempo, Honeycomb, Datadog,
New Relic, Grafana Cloud).
It’s a function, not a class — you hand it the
@opentelemetry/api namespace (via
OtelAdapterOptions) and install the result on
the tracing extension:
import * as otel from '@opentelemetry/api';import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';import { ActorSystem, TracingExtensionId, otelTracer, OtelAdapterOptions } from 'actor-ts';
// 1. Set up the OTel SDK (exports spans to your backend)const provider = new NodeTracerProvider({ spanProcessors: [new BatchSpanProcessor( new OTLPTraceExporter({ url: 'https://otel-collector.example.com/v1/traces' }), )],});provider.register();
// 2. Build the framework tracer from the @opentelemetry/api namespaceconst system = ActorSystem.create('my-app');const otelAdapterOptions = OtelAdapterOptions.create() .withApi(otel) .withTracerName('actor-ts') .withTracerVersion('1.0.0');system.extension(TracingExtensionId).enable(otelTracer(otelAdapterOptions));With this set up, the framework’s auto-spans (one per actor
message) flow to your tracing backend, joined with W3C
traceparent context across cluster nodes.
Configuration
Section titled “Configuration”otelTracer takes an OtelAdapterOptions — the builder or the
plain object. withApi is mandatory: the adapter delegates to
whatever you pass, and structural typing means the framework never
imports @opentelemetry/api itself.
type OtelAdapterOptionsType = { api: OtelApiLike; // the @opentelemetry/api namespace (required) tracer?: OtelTracerLike; // pre-built tracer; else api.trace.getTracer(...) tracerName?: string; // passed to getTracer; default 'actor-ts' tracerVersion?: string; // passed to getTracer};The OTel SDK does the heavy lifting (export, sampling, batching);
the adapter just translates between the framework’s Tracer and
the OTel API. You can also pass a pre-built tracer instead of a
name/version:
const otelAdapterOptions = OtelAdapterOptions.create() .withApi(otel) .withTracer(otel.trace.getTracer('actor-ts', '1.0.0'));Sampling
Section titled “Sampling”import { ParentBasedSampler, TraceIdRatioBasedSampler } from '@opentelemetry/sdk-trace-base';
const provider = new NodeTracerProvider({ sampler: new ParentBasedSampler({ root: new TraceIdRatioBasedSampler(0.1), // sample 10 % of traces }),});For high-throughput systems, sampling is essential. It’s configured on the OTel SDK, not the adapter:
TraceIdRatioBasedSampler(0.1)— 10 % of traces.AlwaysOnSampler()— every trace (dev / low-volume).AlwaysOffSampler()— none (debugging only).ParentBasedSampler(...)— defer to parent’s sampling decision; samples downstream of an already-sampled trace.
The framework records spans at full rate; the SDK decides which to export. Unsampled spans still propagate context for correlation but don’t export — zero backend cost.
Exporters
Section titled “Exporters”OTel SDK supports many exporters:
| Exporter | Backend |
|---|---|
@opentelemetry/exporter-trace-otlp-http | OTLP (Tempo, Jaeger, generic collectors) |
@opentelemetry/exporter-trace-otlp-grpc | OTLP via gRPC |
@opentelemetry/exporter-jaeger | Jaeger native |
@opentelemetry/exporter-zipkin | Zipkin |
| Vendor-specific | Datadog, New Relic, Honeycomb, … |
Pick by your backend’s preferred protocol. OTLP-over-HTTP is the most general — works with the OpenTelemetry Collector, which then routes to any backend.
Resource attributes
Section titled “Resource attributes”import { Resource } from '@opentelemetry/resources';
const provider = new NodeTracerProvider({ resource: new Resource({ 'service.name': 'my-app', 'service.version': '1.2.3', 'deployment.environment': 'production', 'host.name': process.env.HOSTNAME, }),});Resource attributes are stamped on every span and the most useful place to put global context (service name, version, region, pod name).
Peer dependencies
Section titled “Peer dependencies”npm install @opentelemetry/api @opentelemetry/sdk-trace-node# Plus an exporter:npm install @opentelemetry/exporter-trace-otlp-httpBring your own SDK + exporter combo — the framework doesn’t bundle
either. It only needs the @opentelemetry/api namespace you pass
to withApi.
Metrics and logs
Section titled “Metrics and logs”The OTel SDK ties traces, metrics, and logs together via shared context — but the framework ships no OTel metrics bridge. For metrics, use the framework’s Prometheus exporter (scrape it into an OpenTelemetry Collector if you want it in your OTLP pipeline) or the prom-client adapter.
For logs, there is an OTel bridge — otelLogger(...), the
logging counterpart to otelTracer, with the same
pass-in-the-namespace shape.
Where to next
Section titled “Where to next”- Tracer API — the interface this adapter implements.
- Recording tracer — test alternative.
- Actor tracing — the framework’s auto-spans.
- Prometheus exporter — the metrics path (there is no OTel metrics bridge).
