@reactionary/otel
v0.0.51
Published
OpenTelemetry instrumentation for the Reactionary framework. Provides decorators and utilities for tracing function execution and performance monitoring.
Downloads
31
Readme
@reactionary/otel
OpenTelemetry instrumentation for the Reactionary framework. Provides decorators and utilities for tracing function execution and performance monitoring.
Important: SDK Initialization Required
This library provides instrumentation only. The host application is responsible for initializing the OpenTelemetry SDK. Without proper SDK initialization, traces will be created as NonRecordingSpan instances with zero trace/span IDs.
Features
- Tracing Decorators: Automatic span creation for decorated methods
- Manual Instrumentation: Utilities for custom tracing
- Framework Integration: Built-in support for tRPC and providers
- Zero Dependencies: Only requires OpenTelemetry API
- Graceful Degradation: Works without SDK initialization (produces no-op spans)
Installation
pnpm add @reactionary/otelImportant: You must also install and configure the OpenTelemetry SDK in your host application.
Usage
Basic Tracing with Decorators
import { traced } from '@reactionary/otel';
class MyService {
@traced()
async fetchData(id: string): Promise<Data> {
// This method will be automatically traced
return await dataSource.get(id);
}
@traced({
spanName: 'custom-operation',
captureResult: false
})
processData(data: Data): void {
// Custom span name and no result capture
}
}Manual Instrumentation
import { withSpan, getTracer } from '@reactionary/otel';
// Using withSpan helper
const result = await withSpan('my-operation', async (span) => {
span.setAttribute('operation.id', operationId);
return await performOperation();
});
// Using tracer directly
const tracer = getTracer();
const span = tracer.startSpan('manual-span');
try {
// Your code here
span.setStatus({ code: SpanStatusCode.OK });
} catch (error) {
span.setStatus({ code: SpanStatusCode.ERROR });
span.recordException(error);
} finally {
span.end();
}Setting Up OpenTelemetry SDK
Next.js Applications
- Create an
instrumentation.tsfile in your project root:
// instrumentation.ts
export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs') {
const { NodeSDK } = await import('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = await import('@opentelemetry/auto-instrumentations-node');
const sdk = new NodeSDK({
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
}
}- Enable instrumentation in
next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
instrumentationHook: true,
},
};
module.exports = nextConfig;- Configure environment variables:
# .env.local
OTEL_SERVICE_NAME=my-nextjs-app
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobufNode.js Applications
// Initialize at the very beginning of your application
import { NodeSDK } from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
const sdk = new NodeSDK({
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
// Now import and use your application code
import './app';Environment Variables
The OpenTelemetry SDK can be configured using environment variables:
# Service identification
OTEL_SERVICE_NAME=my-app
OTEL_SERVICE_VERSION=1.0.0
# OTLP Exporter (for Jaeger, etc.)
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
# Console exporter (for development)
OTEL_TRACES_EXPORTER=console
# Sampling (optional)
OTEL_TRACES_SAMPLER=always_on
# Debug logging
OTEL_LOG_LEVEL=debugTroubleshooting
ProxyTracer with NonRecordingSpan
If you see logs like:
tracer: ProxyTracer { _provider: ProxyTracerProvider {} }
ending span: NonRecordingSpan { _spanContext: { traceId: '00000000000000000000000000000000' } }This means the OpenTelemetry SDK has not been initialized. Ensure you have:
- Created an
instrumentation.tsfile (Next.js) - Initialized the SDK at application startup (Node.js)
- Set the required environment variables
Missing Traces
If the decorator is being applied but you don't see traces:
- Verify the OTEL exporter is configured correctly
- Check that your tracing backend is running
- Ensure sampling is enabled (
OTEL_TRACES_SAMPLER=always_on)
API Reference
Decorators
@traced(options?)
Decorates a method to automatically create spans for its execution.
Options:
captureArgs?: boolean- Capture function arguments (default: true)captureResult?: boolean- Capture return value (default: true)spanName?: string- Custom span name (default: ClassName.methodName)spanKind?: SpanKind- OpenTelemetry span kind (default: INTERNAL)
Utility Functions
getTracer(): Tracer- Get the library's tracer instancestartSpan(name, options?, context?): Span- Start a new spanwithSpan<T>(name, fn, options?): Promise<T>- Execute function within a spansetSpanAttributes(span, attributes): void- Set multiple span attributescreateChildSpan(parent, name, options?): Span- Create child span
Constants
SpanKind- OpenTelemetry span kindsSpanStatusCode- OpenTelemetry span status codes
Examples
Console Output (Development)
OTEL_SERVICE_NAME=my-service-dev
OTEL_TRACES_EXPORTER=consoleJaeger (Local)
OTEL_SERVICE_NAME=my-service
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobufHoneycomb (Production)
OTEL_SERVICE_NAME=my-service
OTEL_EXPORTER_OTLP_ENDPOINT=https://api.honeycomb.io
OTEL_EXPORTER_OTLP_HEADERS=x-honeycomb-team=your-api-key