js/opentelemetry/sdk
js/opentelemetry/sdk.ts
fino:opentelemetry/sdk - SDK wiring, exporters, resources, and propagation.
This module contains the cross-signal OpenTelemetry SDK surface. Stable
application-facing exports are SDK classes, processors, readers, exporters,
resources, propagation helpers, and runtime instrumentation classes. The
lower-level runtime topic helpers re-exported here are compatibility support
for advanced integrations; prefer the task APIs documented in
opentelemetry/guide.md for application code.
Use this module to start telemetry collection, configure processors and metric readers, export records to memory or OTLP/HTTP JSON, install runtime instrumentations, manage resources, and propagate trace context through carriers.
OtelSDK.start() is idempotent. flush() drains queued span and log
processors, collects observable metrics, and exports reader batches.
shutdown() flushes first, then disposes instrumentations and readers. The
OTLP exporter defaults to http://127.0.0.1:4318 with signal-specific
/v1/traces, /v1/logs, and /v1/metrics paths.
import { BatchSpanProcessor, InMemoryExporter, OtelSDK } from 'fino:opentelemetry/sdk';
const memory = new InMemoryExporter();
const sdk = new OtelSDK({
exporters: [memory],
spanProcessors: [new BatchSpanProcessor(memory)],
});
sdk.start();
await sdk.flush();
See OpenTelemetry SDK configuration: https://opentelemetry.io/docs/concepts/sdk-configuration/
Classes
class BatchLogRecordProcessor extends LogRecordProcessor {
A log-record processor that applies attribute limits and exports in batches.
Logs are buffered on onEmit after attributeCountLimit and
attributeValueLengthLimit (both unbounded by default) are enforced, then
flushed to the exporter in slices of maxExportBatchSize (default 512).
Records arriving when the queue is at maxQueueSize (default 2048) are
silently dropped. As with the span processor, scheduledDelayMillis of 0
means no automatic flush — call forceFlush() or sdk.flush().
import { BatchLogRecordProcessor, InMemoryExporter, OtelSDK } from 'fino:opentelemetry/sdk';
const exporter = new InMemoryExporter();
const sdk = new OtelSDK({
logRecordProcessors: [
new BatchLogRecordProcessor(exporter, { attributeValueLengthLimit: 1024 }),
],
}).start();
Constructors
constructor(exporter: OtelExporter, options: {
maxQueueSize?: number;
maxExportBatchSize?: number;
scheduledDelayMillis?: number;
attributeCountLimit?: number;
attributeValueLengthLimit?: number;
} = {})
Constructs a batch log processor around an exporter with optional limits.
Sizing defaults match BatchSpanProcessor; attribute-count and value-length
limits default to unbounded (Number.POSITIVE_INFINITY).
Methods
onEmit(log: LogRecord): void
Applies attribute limits and enqueues the record, dropping it if full.
Arms the flush timer when a positive scheduledDelayMillis is configured
and none is pending.
async forceFlush(): Promise<void>
Cancels any pending timer and exports the whole queue in batches.
async shutdown(): Promise<void>
Flushes remaining logs; the exporter itself is not closed here.
class BatchSpanProcessor extends SpanProcessor {
A span processor that queues finished spans and exports them in batches.
Spans are buffered on onEnd and flushed to the exporter in slices of
maxExportBatchSize (default 512). Once the queue reaches maxQueueSize
(default 2048), further spans are dropped and counted in droppedSpanCount.
When scheduledDelayMillis is greater than zero a timer flushes the queue
after that delay; with the default of 0 no timer is armed and you must call
forceFlush() (or sdk.flush()) to export — which is what tests typically
want for determinism.
import { BatchSpanProcessor, InMemoryExporter } from 'fino:opentelemetry/sdk';
const exporter = new InMemoryExporter();
const processor = new BatchSpanProcessor(exporter, {
maxQueueSize: 4096,
maxExportBatchSize: 256,
scheduledDelayMillis: 5000,
});
Constructors
constructor(exporter: OtelExporter, options: {
maxQueueSize?: number;
maxExportBatchSize?: number;
scheduledDelayMillis?: number;
} = {})
Constructs a batch processor around an exporter with optional sizing.
maxQueueSize defaults to 2048, maxExportBatchSize to 512, and
scheduledDelayMillis to 0 (manual flush only).
Getters
get droppedSpanCount(): number
How many spans have been dropped because the queue was full.
Methods
onEnd(span: SpanRecord): void
Enqueues a finished span, dropping it if the queue is at capacity.
When a positive scheduledDelayMillis is configured and no flush is
pending, this arms the flush timer.
async forceFlush(): Promise<void>
Cancels any pending timer and exports the whole queue in batches.
Drains the queue in slices of maxExportBatchSize, awaiting each
exportSpans call in turn, so it resolves only once everything buffered
has been handed to the exporter.
async shutdown(): Promise<void>
Flushes remaining spans; the exporter itself is not closed here.
class InMemoryExporter {
An exporter that retains every span, log, and metric it receives in memory.
This is the exporter to reach for in tests and assertions: nothing leaves the
process, and the getFinished* accessors return defensive copies of what has
been exported so far. Its export* methods always resolve with a success
result, so it never exercises retry or failure paths — pair it with a real
exporter if you need to test those.
import { BatchSpanProcessor, InMemoryExporter, OtelSDK } from 'fino:opentelemetry/sdk';
const memory = new InMemoryExporter();
const sdk = new OtelSDK({
spanProcessors: [new BatchSpanProcessor(memory, { scheduledDelayMillis: 0 })],
}).start();
await sdk.flush();
for (const span of memory.getFinishedSpans()) console.log(span.name);
Methods
async exportSpans(spans: SpanRecord[]): Promise<ExportResult>
Appends the given spans to the in-memory store and resolves with success.
async exportLogs(logs: LogRecord[]): Promise<ExportResult>
Appends the given log records to the in-memory store and resolves with success.
async exportMetrics(metrics: MetricRecord[]): Promise<ExportResult>
Appends the given metric records to the in-memory store and resolves with success.
getFinishedSpans(): SpanRecord[]
Returns a shallow copy of every span exported so far.
The returned array is a snapshot; later exports do not mutate it. Assert
against its length and contents after calling sdk.flush().
getFinishedLogs(): LogRecord[]
Returns a shallow copy of every log record exported so far.
getFinishedMetrics(): MetricRecord[]
Returns a shallow copy of every metric record exported so far.
class LogRecordProcessor {
Base class for log-record processors; the no-op default that subclasses override.
A log processor is notified once per emitted log record via onEmit. The
base implementation is a null processor. Subclass it to batch or forward logs
— see BatchLogRecordProcessor.
import { LogRecordProcessor } from 'fino:opentelemetry/sdk';
import type { LogRecord } from 'fino:opentelemetry';
class ConsoleLogProcessor extends LogRecordProcessor {
onEmit(log: LogRecord): void {
console.log(log.severityText, log.body);
}
}
Methods
onEmit(_log: LogRecord): void
Called for each emitted log record. No-op by default.
async forceFlush(): Promise<void>
Exports anything the processor has buffered. Resolves immediately by default.
async shutdown(): Promise<void>
Flushes and releases resources. Resolves immediately by default.
class ManualMetricReader extends MetricReader {
A metric reader that buffers the latest batch for synchronous collect().
Unlike PeriodicMetricReader, this reader never exports on its own — it holds
the most recent batch the SDK delivered and hands it out when you call
collect(). This is the building block behind metricsSignal and any pull-
based integration (a scrape endpoint, a dashboard poll). Under 'delta'
temporality, receiving an empty batch after having seen data emits zeroed
copies of the last series so downstream consumers observe the reset.
import { ManualMetricReader, OtelSDK } from 'fino:opentelemetry/sdk';
const reader = new ManualMetricReader({ temporality: 'delta' });
const sdk = new OtelSDK({ metricReaders: [reader] }).start();
await sdk.flush(); // SDK delivers a batch to the reader
const metrics = reader.collect(); // drains and returns it
Methods
receive(metrics: MetricRecord[]): void
Stores the delivered batch for the next collect().
Each call replaces the buffered batch rather than appending. When a delta reader receives an empty batch after previously seeing data, the buffer is filled with zeroed copies of the last series so the reset is visible.
collect(): MetricRecord[]
Returns and clears the buffered batch as cloned records.
The buffer is emptied, so a second call before the next receive() returns
an empty array. Records are cloned, so mutating them does not affect SDK
state.
class MetricReader {
Base class for metric readers; carries the reader's aggregation temporality.
A metric reader is the sink the SDK delivers aggregated metric batches to.
Its temporality — 'cumulative' (default) or 'delta' — selects which of
the SDK's two aggregate stores feeds it, and stamps aggregationTemporality
on each record. The base class is a null reader; subclass it to collect
(ManualMetricReader) or export on a timer (PeriodicMetricReader).
import { MetricReader } from 'fino:opentelemetry/sdk';
const reader = new MetricReader({ temporality: 'delta' });
console.log(reader.temporality); // 'delta'
Constructors
constructor(options: {
temporality?: MetricTemporality;
} = {})
Constructs a reader with the given temporality, defaulting to 'cumulative'.
Getters
get temporality(): MetricTemporality
The aggregation temporality this reader reports metrics with.
Methods
record(_metric: MetricRecord): void
Records a single metric. No-op by default.
receive(_metrics: MetricRecord[]): void
Receives a batch of aggregated metrics from the SDK. No-op by default.
async forceFlush(): Promise<void>
Exports anything buffered. Resolves immediately by default.
async shutdown(): Promise<void>
Stops collection and releases resources. Resolves immediately by default.
class OtelSDK {
The cross-signal collection engine that turns runtime telemetry into exports.
An OtelSDK ties together processors, readers, exporters, a sampler, a
propagator, metric views, span/log limits, a cardinality limit, and a
resource. Once start() runs it subscribes to the runtime metric/log/
observable topics and drives any periodic readers; span recording is driven
by instrumentations calling recordSpanStart/recordSpan. Records flow
through the pipeline — sampling and limits for spans, limits for logs, views
and cardinality capping for metrics — with the configured resource merged in
along the way, before reaching processors and readers.
Construction fills in defaults for anything omitted: an OTLP HTTP JSON
exporter, one BatchSpanProcessor, no log processors or metric readers, an
AlwaysOnSampler, a W3CTraceContextPropagator, no views, an unbounded
cardinality limit, empty span limits, and no resource. Multiple exporters are
automatically wrapped in a fan-out exporter.
import {
BatchSpanProcessor,
InMemoryExporter,
OtelSDK,
PeriodicMetricReader,
} from 'fino:opentelemetry/sdk';
const exporter = new InMemoryExporter();
const sdk = new OtelSDK({
resource: { 'service.name': 'checkout' },
spanProcessors: [new BatchSpanProcessor(exporter, { scheduledDelayMillis: 0 })],
metricReaders: [new PeriodicMetricReader(exporter, { intervalMs: 0 })],
}).start();
await sdk.flush();
await sdk.shutdown();
Constructors
constructor(options: {
exporters?: OtelExporter[];
instrumentations?: Instrumentation[];
spanProcessors?: SpanProcessor[];
logRecordProcessors?: LogRecordProcessor[];
metricReaders?: MetricReader[];
sampler?: Sampler;
propagator?: TextMapPropagator;
views?: MetricView[];
metricCardinalityLimit?: number;
spanLimits?: SpanLimits;
resource?: Resource | Record<string, unknown> | null;
} = {})
Constructs an SDK, filling in defaults for any omitted option.
When no exporters are given a single OTLP HTTP JSON exporter is used; when
several are given they are wrapped in a fan-out exporter feeding the default
BatchSpanProcessor. A plain object passed as resource is normalized into
a Resource.
Getters
get propagator(): TextMapPropagator
The configured trace-context propagator, for injecting/extracting carriers.
get resource(): Resource | null
The configured resource merged into emitted records, or null when unset.
Methods
start(): this
Starts collection: subscribes to runtime topics and enables instrumentations.
Idempotent — a second call while already started is a no-op and returns
this. Subscribes to the metric, log, and observable-registration topics,
arms periodic metric readers, and enables each instrumentation, tracking any
returned disposables for shutdown(). Returns the SDK so start() can be
chained onto construction.
import { OtelSDK } from 'fino:opentelemetry/sdk';
const sdk = new OtelSDK().start();
recordSpanStart(span: SpanRecord): void
Records the start of a span, applying limits and sampling.
The span is limit-clamped and resource-enriched, then the sampler decides
whether to keep it. Dropped spans return immediately; kept spans have their
id remembered so the matching recordSpan skips re-sampling, and every span
processor's onStart is invoked.
recordSpan(span: SpanRecord): void
Records the end of a span and delivers it to the processors.
If the span was sampled at start its remembered id is consumed and the span
is passed straight to each processor's onEnd. A span with no prior
recordSpanStart (a direct end) is sampled here first, and dropped if the
sampler declines.
recordLog(log: LogRecord): void
Records a log, enriches it with the resource, and emits to log processors.
This is the handler bound to the otel:log:record topic on start(), but
it can also be called directly.
recordMetric(metric: MetricRecord): void
Records a metric, applying views, cardinality limits, and aggregation.
The metric is view-shaped and resource-enriched, then dropped if it would
introduce a new attribute set beyond the per-instrument cardinality limit.
Surviving metrics are accumulated into both the cumulative and delta
aggregate stores keyed by series. This is the handler bound to the
otel:metric:record topic on start().
async flush(): Promise<void>
Collects observable metrics and drains all processors and readers.
Each registered observable callback is invoked (errors are swallowed and the
observable skipped) and its observations recorded. Then, for every reader,
the aggregate store matching its temporality is delivered via receive(),
and all span processors, log processors, and readers are flushed in
parallel. Delta aggregates are cleared afterward so the next window starts
fresh.
import { BatchSpanProcessor, InMemoryExporter, OtelSDK } from 'fino:opentelemetry/sdk';
const exporter = new InMemoryExporter();
const sdk = new OtelSDK({
spanProcessors: [new BatchSpanProcessor(exporter, { scheduledDelayMillis: 0 })],
}).start();
await sdk.flush();
console.log(exporter.getFinishedSpans().length);
async shutdown(): Promise<void>
Flushes, then shuts down processors, readers, and instrumentations.
Runs a final flush(), then shuts down every span processor, log processor,
and reader in parallel, disposes all tracked disposables (topic
subscriptions and instrumentation handles, errors ignored), clears the
sampled-span and aggregate state, and marks the SDK stopped. After this the
SDK can be start()ed again.
import { OtelSDK } from 'fino:opentelemetry/sdk';
const sdk = new OtelSDK().start();
await sdk.shutdown();
class PeriodicMetricReader extends MetricReader {
A metric reader that periodically collects aggregates and exports them.
Once OtelSDK.start() wires it up, this reader exports on a fixed interval
(intervalMs, default 60000). Each cycle the SDK collects the aggregate
store matching the reader's temporality, delivers it via receive(), and the
reader exports the buffered batch. A non-positive interval disables the timer,
leaving the reader flush-on-demand. Use PeriodicExportingMetricReader as the
stable alias for this class.
import { OTLPHttpJsonExporter, OtelSDK, PeriodicMetricReader } from 'fino:opentelemetry/sdk';
const sdk = new OtelSDK({
metricReaders: [
new PeriodicMetricReader(new OTLPHttpJsonExporter(), { intervalMs: 15000 }),
],
}).start();
Constructors
constructor(exporter: OtelExporter, options: {
temporality?: MetricTemporality;
intervalMs?: number;
} = {})
Constructs a periodic reader around an exporter.
temporality is passed through to MetricReader (default 'cumulative')
and intervalMs defaults to 60000.
Methods
_startPeriodicCollection(collectAndFlush: () => Promise<void>): void
Called by OtelSDK.start() to begin the periodic collection cycle.
collectAndFlush is the SDK-supplied callback that collects accumulated
metrics, delivers them via receive(), and calls forceFlush() to export.
A non-positive interval disables scheduling, and repeated calls are ignored
once a timer is active. This is an internal wiring hook, not part of the
public reader contract.
import { OTLPHttpJsonExporter, PeriodicMetricReader } from 'fino:opentelemetry/sdk';
const reader = new PeriodicMetricReader(new OTLPHttpJsonExporter(), { intervalMs: 1000 });
reader._startPeriodicCollection(async () => {});
receive(metrics: MetricRecord[]): void
Buffers a batch of aggregated metrics for the next flush.
async forceFlush(): Promise<void>
Exports and clears the buffered metrics; a no-op when empty.
async shutdown(): Promise<void>
Stops the collection timer and flushes any remaining metrics.
class SpanProcessor {
Base class for span processors; the no-op default that subclasses override.
A span processor is the stage the SDK notifies when a span starts
(onStart) and ends (onEnd). The base implementation does nothing, which
makes it a valid null processor and a convenient superclass. Subclass it to
batch, filter, or forward spans — see BatchSpanProcessor.
import { SpanProcessor } from 'fino:opentelemetry/sdk';
import type { SpanRecord } from 'fino:opentelemetry';
class LoggingProcessor extends SpanProcessor {
onEnd(span: SpanRecord): void {
console.log('finished span', span.name);
}
}
Methods
onStart(_span: SpanRecord): void
Called when a span starts, after sampling and limits are applied. No-op by default.
onEnd(_span: SpanRecord): void
Called when a span ends, after limits are applied. No-op by default.
async forceFlush(): Promise<void>
Exports anything the processor has buffered. Resolves immediately by default.
async shutdown(): Promise<void>
Flushes and releases resources. Resolves immediately by default.
class Baggage {
An immutable W3C baggage set — string key/value pairs that propagate alongside trace context.
Every mutating operation (set, delete) returns a new Baggage rather than
modifying the receiver, so instances are safe to share across async scopes.
toString produces a spec-compliant baggage header value and
Baggage.fromString parses one back.
W3C Baggage: https://www.w3.org/TR/baggage/
import { Baggage } from 'internal:opentelemetry/common';
const baggage = new Baggage({ tenant: 'acme' }).set('region', 'us');
baggage.get('tenant'); // 'acme'
baggage.toString(); // 'tenant=acme,region=us'
Constructors
constructor(entries: Record<string, string> = {})
Creates a baggage set from an initial record of entries, defaulting to empty.
const baggage = new Baggage({ tenant: 'acme' });
Methods
get(key: string): string | undefined
Returns the value for a key, or undefined when the key is absent.
new Baggage({ tenant: 'acme' }).get('tenant'); // 'acme'
set(key: string, value: string): Baggage
Returns a new baggage with the key set to the given value, leaving the receiver unchanged.
const base = new Baggage({ tenant: 'acme' });
const next = base.set('region', 'us'); // base still has only tenant
delete(key: string): Baggage
Returns a new baggage without the given key, leaving the receiver unchanged.
Deleting an absent key is a no-op that still returns a fresh copy.
new Baggage({ tenant: 'acme', region: 'us' }).delete('region');
entries()
Returns an iterator over the [key, value] pairs in insertion order.
for (const [key, value] of new Baggage({ tenant: 'acme' }).entries()) {
console.log(key, value);
}
toString(): string
Serializes the baggage to a W3C baggage header value.
Keys and values are percent-encoded and joined with commas. An empty baggage serializes to the empty string.
new Baggage({ tenant: 'acme', region: 'us' }).toString(); // 'tenant=acme,region=us'
isEmpty(): boolean
True when the baggage contains no entries.
new Baggage().isEmpty(); // true
Static Methods
static fromString(text: string | null | undefined): Baggage
Parses a W3C baggage header into an immutable Baggage value.
Empty, null, or undefined input returns an empty baggage object. Invalid
comma segments without = are ignored, and duplicate decoded keys keep the
last parsed value.
const baggage = Baggage.fromString('tenant=acme,region=us');
class BaseProvider {
Shared base for the tracer, meter, and logger providers, holding a normalized Resource.
Subclasses inherit resource handling for free: the constructor runs the
supplied resource option through normalizeResource so every provider
exposes a fully-populated resource (defaults merged in) via the read-only
resource getter.
import { BaseProvider } from 'internal:opentelemetry/common';
class TracerProvider extends BaseProvider {}
const provider = new TracerProvider({ resource: { 'service.name': 'api' } });
provider.resource.attributes['service.name']; // 'api'
Constructors
constructor(options: ProviderOptions = {})
Normalizes the resource option into a Resource, defaulting to the SDK resource.
const provider = new BaseProvider({ resource: { 'service.name': 'api' } });
Getters
get resource(): Resource
The normalized resource describing the entity this provider produces telemetry for.
new BaseProvider().resource.attributes['telemetry.sdk.name']; // 'fino'
class Resource {
An immutable description of the entity producing telemetry.
Holds a copied attribute map plus optional entity references, a schema URL,
and a dropped-attribute count. All state is private and every getter returns a
defensive copy, so a Resource cannot be mutated after construction. Prefer
normalizeResource to build one with the default SDK attributes merged in.
import { Resource } from 'internal:opentelemetry/common';
const resource = new Resource(
{ 'service.name': 'checkout', 'service.version': '4.2.0' },
{ schemaUrl: 'https://opentelemetry.io/schemas/1.24.0' },
);
resource.attributes['service.name']; // 'checkout'
Constructors
constructor(attributes: Attributes = {}, options: ResourceOptions = {})
Builds a resource from an attribute map and optional secondary options.
The attributes are shallow-copied, entityRefs are deep-copied with their
idKeys normalized to arrays, and a missing schemaUrl becomes null. Both
arguments default to empty, so new Resource() yields an attribute-free
resource.
const resource = new Resource({ 'service.name': 'api' });
Getters
get attributes(): Attributes
A fresh shallow copy of the resource's attributes.
Mutating the returned object never affects the resource; read the value each time you need it.
const resource = new Resource({ 'service.name': 'api' });
resource.attributes['service.name']; // 'api'
get droppedAttributesCount(): number
The number of attributes dropped before this resource was constructed, or 0.
new Resource({}, { droppedAttributesCount: 3 }).droppedAttributesCount; // 3
get entityRefs(): Array<{
schemaUrl?: string;
type?: string;
idKeys: string[];
}>
A deep copy of the resource's entity references.
Each returned entry carries its own fresh idKeys array, so the internal
state stays immutable. Empty when no entity references were supplied.
const resource = new Resource({}, {
entityRefs: [{ type: 'service', idKeys: ['service.name'] }],
});
resource.entityRefs[0].type; // 'service'
get schemaUrl(): string | null
The semantic-convention schema URL for this resource, or null if none was set.
new Resource({}, { schemaUrl: 'https://opentelemetry.io/schemas/1.24.0' }).schemaUrl;
class TextMapPropagator {
Base class for text-map propagators — the no-op default that subclasses override.
On its own, inject does nothing and extract always returns null, so the
base class is a safe null-object when no propagation format is configured.
W3CTraceContextPropagator is the concrete implementation. Both methods accept
an optional CarrierApi so a subclass can work with non-object carriers.
import { TextMapPropagator } from 'internal:opentelemetry/common';
class NoopPropagator extends TextMapPropagator {}
new NoopPropagator().extract({}); // null
Methods
inject<TCarrier = CarrierLike>(
_carrier: TCarrier,
_context: TraceContext | null | undefined,
_carrierApi?: CarrierApi<TCarrier>
): void
Injects trace context into a carrier.
The base propagator is a no-op for subclasses to override. It accepts a custom carrier API for non-object carriers and never throws for missing context.
new TextMapPropagator().inject({}, null);
extract<TCarrier = CarrierLike>(
_carrier: TCarrier,
_carrierApi?: CarrierApi<TCarrier>
): TraceContext | null
Extracts trace context from a carrier.
The base propagator cannot decode any format and always returns null.
Subclasses return a TraceContext only when required carrier fields are
present and valid.
const context = new TextMapPropagator().extract({});
class W3CTraceContextPropagator extends TextMapPropagator {
Propagator implementing W3C traceparent, tracestate, and baggage headers.
This is the default propagator returned by Propagation.getPropagator. It
injects a version-00 traceparent, adds tracestate and baggage when
present, and on extraction validates the header strictly (rejecting all-zero
IDs, the reserved ff version, and v00 headers with trailing data) while
parsing unknown lowercase versions permissively for forward compatibility.
W3C Trace Context: https://www.w3.org/TR/trace-context/
import { W3CTraceContextPropagator } from 'internal:opentelemetry/common';
const propagator = new W3CTraceContextPropagator();
const headers = new Headers();
propagator.inject(headers, {
traceId: '00000000000000000000000000000001',
spanId: '0000000000000001',
traceFlags: 1,
});
const context = propagator.extract(headers);
Methods
inject<TCarrier = CarrierLike>(
carrier: TCarrier,
context: TraceContext | null | undefined,
carrierApi?: CarrierApi<TCarrier>
): void
Writes W3C traceparent and optional tracestate values into a carrier.
Missing traceId or spanId leaves the carrier untouched. traceFlags are
masked to one byte and encoded as two lowercase hexadecimal digits.
new W3CTraceContextPropagator().inject({}, { traceId: '0'.repeat(31) + '1', spanId: '0'.repeat(15) + '1' });
extract<TCarrier = CarrierLike>(
carrier: TCarrier,
carrierApi?: CarrierApi<TCarrier>
): TraceContext | null
Reads W3C trace context from traceparent and optional tracestate.
Returns null for malformed headers, all-zero trace IDs, all-zero span IDs,
or v00 headers with trailing data. Unknown versions are parsed
permissively for forward compatibility.
const context = new W3CTraceContextPropagator().extract({ traceparent: '00-00000000000000000000000000000001-0000000000000001-01' });
Constants
const PeriodicExportingMetricReader
Stable OpenTelemetry-spec alias for PeriodicMetricReader.
Provided so code written against the standard SDK naming works unchanged; it is the same constructor, not a subclass.
import { OTLPHttpJsonExporter, PeriodicExportingMetricReader } from 'fino:opentelemetry/sdk';
const reader = new PeriodicExportingMetricReader(new OTLPHttpJsonExporter());
const OTEL_SCHEMA_VERSION
Version stamp written into the schemaVersion field of runtime event payloads.
Consumers can branch on this to stay compatible as the internal event shape
evolves. It is the runtime's own event-schema version, unrelated to an OTel
semantic-convention schemaUrl.
import { OTEL_SCHEMA_VERSION } from 'internal:opentelemetry/common';
if (OTEL_SCHEMA_VERSION >= 1) {
// handle the current runtime event shape
}
const OTEL_TOPIC_SUFFIXES
The frozen catalog of valid topic suffixes for each signal family.
Maps each family (trace, log, metric, runtime) to the lifecycle/level
suffixes it may append to a scoped topic name — for example a trace topic can
end in start/end/error, while a log topic ends in a severity like
info/warn. Deeply frozen so the vocabulary cannot be mutated at runtime.
import { OTEL_TOPIC_SUFFIXES } from 'internal:opentelemetry/common';
OTEL_TOPIC_SUFFIXES.trace; // ['start', 'end', 'error', 'event', ...]
OTEL_TOPIC_SUFFIXES.log; // ['emit', 'debug', 'info', 'warn', 'error']
const Propagation
The process-global propagation facade used to inject and extract trace context.
getPropagator lazily creates a W3CTraceContextPropagator on first use, and
setPropagator swaps in a custom one. inject writes the active span's
context (from the getter registered via registerActiveSpanContextGetter)
when no context is passed explicitly, and extract reads context off an
inbound carrier. Both delegate to the current propagator.
import { Propagation } from 'internal:opentelemetry/common';
const headers = new Headers();
Propagation.inject(headers); // writes traceparent from active span
const incoming = Propagation.extract(headers);
Methods
getPropagator(): TextMapPropagator
setPropagator(propagator: TextMapPropagator): void
inject<TCarrier = CarrierLike>(
carrier: TCarrier,
context?: TraceContext | null,
carrierApi?: CarrierApi<TCarrier>
): void
extract<TCarrier = CarrierLike>(
carrier: TCarrier,
carrierApi?: CarrierApi<TCarrier>
): TraceContext | null
Functions
function metricsSignal(reader: ManualMetricReader, options: {
intervalMs?: number;
} = {}): ReadonlySignal<MetricRecord[]>
Wraps a ManualMetricReader in a cold signal that re-collects on an interval.
The returned signal starts empty, collects once immediately when it gains its
first subscriber, then polls reader.collect() every intervalMs
(default 1000). Empty collections are skipped, so the signal only updates
when there is new metric data. Being cold, the polling timer is only active
while the signal has subscribers and is cleared when the last one leaves.
import { ManualMetricReader, OtelSDK, metricsSignal } from 'fino:opentelemetry/sdk';
const reader = new ManualMetricReader();
new OtelSDK({ metricReaders: [reader] }).start();
const metrics = metricsSignal(reader, { intervalMs: 5000 });
const stop = metrics.subscribe((batch) => console.log('metrics', batch.length));
// later: stop();
function bytesEqual(a: Uint8Array, b: Uint8Array): boolean
Compares two byte arrays for equal length and identical contents.
Returns false immediately when the lengths differ, otherwise compares every
byte. This is a plain value comparison, not a constant-time one, so it is not
suitable for comparing secrets.
import { bytesEqual, hexToBytes } from 'internal:opentelemetry/common';
bytesEqual(hexToBytes('0001', 2), hexToBytes('0001', 2)); // true
function carrierApiFor<TCarrier>(
carrier: TCarrier,
carrierApi?: CarrierApi<TCarrier>
): CarrierApi<TCarrier>
Returns the caller-supplied CarrierApi if given, otherwise derives one with defaultCarrierApiFor.
This is the entry point propagators use so an explicit strategy always wins
over the sniffed default. Passing a custom API lets you propagate through a
carrier that does not match CarrierLike.
import { carrierApiFor } from 'internal:opentelemetry/common';
const api = carrierApiFor({} as Record<string, unknown>);
function consumeRequestContext(requestId: string): ActiveTelemetryContext | null
Removes and returns the context previously stashed for a request id, or null.
The entry is deleted whether or not it existed, so a context can be adopted
exactly once. Returns null when no context was installed or it was already
consumed. Pair with runWithActiveContext to activate the result.
import { consumeRequestContext, runWithActiveContext } from 'internal:opentelemetry/common';
const ctx = consumeRequestContext('req-1');
if (ctx) runWithActiveContext(ctx, () => handleRequest());
function currentActiveTelemetryContext(): ActiveTelemetryContext | undefined
Returns the active telemetry context installed by runWithActiveContext, or undefined.
undefined means no context has been made active in the current async scope —
typically outside any instrumented request handler.
import { currentActiveTelemetryContext } from 'internal:opentelemetry/common';
const traceId = currentActiveTelemetryContext()?.traceId;
function defaultCarrierApiFor<TCarrier extends CarrierLike>(carrier: TCarrier): CarrierApi<TCarrier>
Picks a CarrierApi for a carrier by sniffing whether it exposes get/set methods.
When the carrier has both get and set functions (as Headers or a Map
does), the returned API routes through them and reads keys via keys() if
available. Otherwise it treats the carrier as a plain record, using property
access and Object.keys. Callers usually reach this through carrierApiFor.
import { defaultCarrierApiFor } from 'internal:opentelemetry/common';
const api = defaultCarrierApiFor(new Headers());
api.set(new Headers(), 'traceparent', '00-...-01');
function encodeSegment(value: unknown): string
Percent-encodes a value for safe use as a single colon-delimited topic segment.
Stringifies the input then applies encodeURIComponent, so any : or other
delimiter inside a scope name or suffix cannot break the otel:... topic
grammar. This is the escaping used throughout topicNames/otelTopic.
import { encodeSegment } from 'internal:opentelemetry/common';
encodeSegment('my:service'); // 'my%3Aservice'
function getActiveBaggage(): Baggage
Returns the baggage currently in scope, falling back through context stores to an empty set.
Prefers the dedicated active-baggage store, then the baggage attached to the
active telemetry context, and finally a fresh empty Baggage. Always returns
a value, so callers never need to null-check.
import { getActiveBaggage } from 'internal:opentelemetry/common';
const tenant = getActiveBaggage().get('tenant');
function hexToBytes(hex: string, size: number): Uint8Array
Decodes a hex string into a fixed-size byte array, left-padding or truncating to fit.
Always returns exactly size bytes: shorter input is zero-padded on the left,
longer input is truncated, and any non-hex pair decodes to 0 rather than
throwing. Useful for turning a trace/span ID into its binary form for
comparison with bytesEqual.
import { hexToBytes } from 'internal:opentelemetry/common';
hexToBytes('0001', 2); // Uint8Array [0, 1]
hexToBytes('1', 2); // Uint8Array [0, 1] (left-padded)
function installRequestContext(requestId: string, context: ActiveTelemetryContext): void
Stashes a trace context under a request id so a handler can later adopt it.
This decouples the point where instrumentation extracts context (on the socket
thread) from where the handler runs, without coupling serve to OTel types.
Retrieve and remove the entry with consumeRequestContext. The pending map is
bounded: entries older than five minutes are evicted on overflow, and if it is
still full the oldest entry is dropped, so an id that is never consumed leaks
only transiently.
import { installRequestContext } from 'internal:opentelemetry/common';
installRequestContext('req-1', {
traceId: '0'.repeat(31) + '1',
spanId: '0'.repeat(15) + '1',
});
function limitAttributeEntries(attributes: Attributes, limits: {
attributeCountLimit?: number;
attributeValueLengthLimit?: number;
}): {
attrs: Attributes;
dropped: number;
}
Applies span-attribute limits, returning the kept attributes and how many were dropped.
Keeps the first attributeCountLimit entries in insertion order (excess
counted in dropped) and truncates each kept string value to
attributeValueLengthLimit via truncateAttributeValue. An omitted limit is
treated as unlimited for that dimension, so with no limits nothing is dropped.
import { limitAttributeEntries } from 'internal:opentelemetry/common';
const { attrs, dropped } = limitAttributeEntries(
{ a: 1, b: 2, c: 3 },
{ attributeCountLimit: 2 },
);
// attrs = { a: 1, b: 2 }, dropped = 1
function mergeAttributes(a?: Attributes, b?: Attributes): Attributes
Shallow-merges two attribute maps into a new object, with the second winning on key conflicts.
Either argument may be omitted; the result is always a fresh object, so
neither input is mutated. Keys present in b override the same keys in a.
import { mergeAttributes } from 'internal:opentelemetry/common';
mergeAttributes({ a: 1, b: 2 }, { b: 3 }); // { a: 1, b: 3 }
function normalizeResource(resource?: Resource | Attributes | null): Resource
Coerces any resource-ish input into a Resource with the default SDK attributes merged in.
Accepts an existing Resource, a plain attribute map, or null/undefined.
The result always includes the defaults (service.name = unknown_service,
telemetry.sdk.name = fino, telemetry.sdk.language = javascript), with
the caller's attributes taking precedence. When passed a Resource, its
dropped-count, entity refs, and schema URL are preserved.
import { normalizeResource } from 'internal:opentelemetry/common';
const resource = normalizeResource({ 'service.name': 'checkout' });
resource.attributes['telemetry.sdk.name']; // 'fino'
function normalizeScope(
name: string,
version?: string,
schemaUrl?: string | null,
attributes?: Attributes,
droppedAttributesCount?: number
): ScopeInfo
Builds a validated ScopeInfo, omitting empty optional fields and copying attributes.
The name is run through requireNonEmptyName (throwing a TypeError when
blank). Falsy version, schemaUrl, attributes, and droppedAttributesCount
are left off the result entirely rather than set to undefined, and the
attributes object is shallow-copied so later mutation of the caller's map does
not leak in.
import { normalizeScope } from 'internal:opentelemetry/common';
const scope = normalizeScope('my-app/db', '2.1.0');
// { name: 'my-app/db', version: '2.1.0' }
function nowUnixNano(): number
Returns the current wall-clock time as Unix-epoch nanoseconds.
Combines performance.timeOrigin with performance.now() for sub-millisecond
resolution, then scales to nanoseconds — the timestamp unit every record in
this module uses. Because the result is a double, it exceeds 2^53 and loses
single-nanosecond precision; it is accurate to roughly the microsecond.
import { nowUnixNano } from 'internal:opentelemetry/common';
const span = { startTimeUnixNano: nowUnixNano() };
function otelRuntimeEvent<TPayload extends Record<string, unknown>>(domain: string, operation: string, phase: string, payload: TPayload = {} as TPayload): TPayload & {
schemaVersion: number;
topic: string;
family: string;
domain: string;
operation: string;
phase: string;
correlationId: unknown;
}
Wraps a runtime event payload with standard envelope fields for publishing.
Merges the caller's payload with schemaVersion (OTEL_SCHEMA_VERSION), the
resolved topic, a family of 'runtime', the domain/operation/phase,
and a correlationId derived from the first present of requestId,
lookupId, connectId, handshakeId, or spanId (else null). Payload keys
are spread last, so an explicit topic or correlationId in the payload wins.
import { otelRuntimeEvent, otelRuntimeTopic } from 'internal:opentelemetry/common';
import { topic } from 'internal:opentelemetry/common';
const event = otelRuntimeEvent('dns', 'lookup', 'start', {
lookupId: 'dns-1',
hostname: 'example.com',
});
topic(otelRuntimeTopic('dns', 'lookup', 'start')).publish(event);
function otelRuntimeTopic(domain: string, operation: string, phase: string): string
Builds the topic name for a runtime instrumentation event.
Produces otel:runtime:<domain>:<operation>:<phase> with each part
percent-encoded — for example ('http.server', 'request', 'start'). These are
the topics that the runtime publishes network/DNS/TLS lifecycle events on and
that the built-in instrumentations subscribe to.
import { otelRuntimeTopic } from 'internal:opentelemetry/common';
otelRuntimeTopic('dns', 'lookup', 'start'); // 'otel:runtime:dns:lookup:start'
function otelTopic(signal: string, scope: ScopeInfo, ...suffixes: string[]): string
Builds the single versioned topic name for a scoped signal.
Produces otel:<signal>:<scopeSegment>[:<suffixes>], where the scope segment
includes @version when the scope is versioned and any suffixes are joined
with :. Unlike topicNames this returns exactly one name (the versioned
form), which is what publishers and subscribers key on.
import { otelTopic } from 'internal:opentelemetry/common';
otelTopic('trace', { name: 'mysql' }, 'start'); // 'otel:trace:mysql:start'
function publishScoped<TPayload>(
signal: SignalName,
scope: ScopeInfo,
suffixes: string[],
payload: TPayload
): void
Publishes one payload to every topic name that topicNames derives for a scope.
Delivers the same payload to both the bare and versioned topic forms so subscribers at either granularity see it. Publication is synchronous through the topic bus.
import { publishScoped } from 'internal:opentelemetry/common';
publishScoped('trace', { name: 'db', version: '2.1.0' }, ['start'], {
traceId: '00000000000000000000000000000001',
spanId: '0000000000000001',
});
function randomHex(length: number): string
Generates a cryptographically random lowercase hex string of the given length.
Draws random bytes from crypto.getRandomValues and truncates to exactly
length characters, so odd lengths are supported. Used to mint trace and span
IDs (32 and 16 hex chars respectively).
import { randomHex } from 'internal:opentelemetry/common';
const traceId = randomHex(32);
const spanId = randomHex(16);
function registerActiveSpanContextGetter(getter: () => TraceContext | null): void
Installs the callback that resolves the currently active span's trace context.
The trace SDK registers a getter here so that Propagation.inject (called
without an explicit context) can read the active span without this module
depending on the tracer. Registering again replaces the previous getter; until
one is set the default returns null.
import { registerActiveSpanContextGetter } from 'internal:opentelemetry/common';
registerActiveSpanContextGetter(() => currentSpan()?.spanContext() ?? null);
function requireNonEmptyName(kind: string, value: unknown): string
Validates and trims a required name string, throwing when it is blank.
Coerces the value to a string, trims surrounding whitespace, and throws a
TypeError naming kind if the result is empty. Used to guarantee scopes and
instruments always carry a usable name.
import { requireNonEmptyName } from 'internal:opentelemetry/common';
requireNonEmptyName('scope', ' db '); // 'db'
requireNonEmptyName('scope', ' '); // throws TypeError
function requireRecord(kind: string, value: unknown): Record<string, unknown>
Coerces a value to a plain record, tolerating nullish input but rejecting non-objects.
Returns an empty object for null/undefined, returns the value unchanged
when it is a non-array object, and throws a TypeError (using kind in the
message) for primitives and arrays. Handy for validating optional options bags.
import { requireRecord } from 'internal:opentelemetry/common';
requireRecord('attributes', undefined); // {}
requireRecord('attributes', { a: 1 }); // { a: 1 }
requireRecord('attributes', [1, 2]); // throws TypeError
function runWithActiveContext<R>(context: ActiveTelemetryContext, fn: () => R): R
Runs a function with the given telemetry context installed as active for its async scope.
Normalizes the context first: only truthy traceId/spanId/traceState are
carried, traceFlags defaults to 1 (sampled) when absent, and a plain
baggage object is upgraded to a Baggage. When the context carries baggage it
is also installed in the active-baggage store so getActiveBaggage sees it.
The function's return value is passed through.
import { runWithActiveContext } from 'internal:opentelemetry/common';
runWithActiveContext(
{ traceId: '0'.repeat(31) + '1', spanId: '0'.repeat(15) + '1' },
() => handleRequest(),
);
function runWithBaggage<R>(baggage: Baggage, fn: () => R): R
Runs a function with the given baggage active, layering it onto any active telemetry context.
When a telemetry context is already active, its baggage is replaced with the supplied set for the duration of the call; otherwise only the active-baggage store is set. Nested calls override outer baggage within their scope. The function's return value is passed through.
import { runWithBaggage, Baggage, getActiveBaggage } from 'internal:opentelemetry/common';
runWithBaggage(new Baggage({ tenant: 'acme' }), () => {
getActiveBaggage().get('tenant'); // 'acme'
});
function scopeSegment(scope: ScopeInfo): string
Renders a scope as a topic segment, appending @version when a version is present.
Both name and version are percent-encoded via encodeSegment. A versionless
scope yields just the encoded name. This is the versioned form used inside
otelTopic; topicNames emits both the bare and versioned forms.
import { scopeSegment } from 'internal:opentelemetry/common';
scopeSegment({ name: 'db', version: '2.1.0' }); // 'db@2.1.0'
scopeSegment({ name: 'db' }); // 'db'
function snapshotCarrier<TCarrier extends CarrierLike>(
carrier: TCarrier,
carrierApi?: CarrierApi<TCarrier>
): Record<string, unknown>
Copies every key/value from a carrier into a plain record.
Iterates the carrier's keys through its CarrierApi and materializes them as
an ordinary object — useful for capturing a Headers instance as a plain
snapshot (for example the injectedHeaders on a SpanRecord).
import { snapshotCarrier } from 'internal:opentelemetry/common';
const headers = new Headers({ traceparent: '00-...-01' });
const plain = snapshotCarrier(headers); // { traceparent: '00-...-01' }
function topic<T = unknown>(name: string): Topic<T>
Re-exported from topic.topic.
function topicNames(signal: string, scope: ScopeInfo, ...suffixes: string[]): string[]
Computes the set of topic names a scoped signal should be published to.
Always includes the bare otel:<signal>:<name> form; when the scope has a
version it also includes the otel:<signal>:<name>@<version> form, so both
version-agnostic and version-pinned subscribers receive the event. Any
suffixes are appended as a single :-joined, encoded segment. publishScoped
fans a payload out across exactly this list.
import { topicNames } from 'internal:opentelemetry/common';
topicNames('trace', { name: 'db', version: '2.1.0' }, 'start');
// ['otel:trace:db:start', 'otel:trace:db@2.1.0:start']
function truncateAttributeValue(value: unknown, limit: number): unknown
Truncates a string attribute value (or the strings inside an array value) to a length limit.
A non-positive or non-finite limit returns the value unchanged. Strings are
clipped to limit characters; arrays have their string elements clipped
element-wise while non-string elements pass through; all other value types are
returned as-is.
import { truncateAttributeValue } from 'internal:opentelemetry/common';
truncateAttributeValue('a very long value', 6); // 'a very'
truncateAttributeValue(['abcdef', 42], 3); // ['abc', 42]
Types
type Attributes = Record<string, unknown>
Open-ended key/value map of attributes attached to spans, logs, metrics, and resources.
Values are stored as unknown because the OpenTelemetry data model permits
strings, numbers, booleans, and homogeneous arrays of those; validation and
truncation happen later in limitAttributeEntries and truncateAttributeValue
rather than in the type. An empty object is a valid, attribute-free value.
import type { Attributes } from 'internal:opentelemetry/common';
const attrs: Attributes = {
'http.request.method': 'GET',
'http.response.status_code': 200,
'url.path': '/orders',
};
type CarrierLike = {
[key: string]: unknown;
get?(key: string): unknown;
set?(key: string, value: unknown): unknown;
keys?(): Iterable<string>;
}
Duck-typed shape a propagation carrier may take — a plain record and/or a Headers-like accessor object.
Propagators read and write context keys through either the indexer or, when
present, the optional get/set/keys methods (as a Headers or Map
provides). defaultCarrierApiFor inspects a value of this shape and picks the
right access strategy, so most callers pass a plain object or a Headers
instance directly.
import type { CarrierLike } from 'internal:opentelemetry/common';
const plain: CarrierLike = { traceparent: '00-...-01' };
const headers: CarrierLike = new Headers();
type ScopeInfo = {
name: string;
version?: string;
schemaUrl?: string | null;
attributes?: Attributes;
droppedAttributesCount?: number;
}
Identity of an instrumentation scope — the named library or subsystem that produced a signal.
The name is required and is what topic routing keys off of (see
topicNames and otelTopic); version further qualifies the scope in
versioned topic names. schemaUrl, attributes, and droppedAttributesCount
carry through to exported records unchanged. Construct these with
normalizeScope rather than by hand to guarantee a non-empty name.
import type { ScopeInfo } from 'internal:opentelemetry/common';
const scope: ScopeInfo = { name: 'my-app/db', version: '2.1.0' };
type SignalName = 'trace' | 'log' | 'metric'
The three OpenTelemetry signal families this runtime emits.
Used to build topic names and to select per-signal suffix vocabularies in
OTEL_TOPIC_SUFFIXES. Runtime instrumentation events use a separate
'runtime' family and are not part of this union.
import type { SignalName } from 'internal:opentelemetry/common';
const signal: SignalName = 'trace';
Interfaces
interface CarrierApi<TCarrier = CarrierLike> {
Strategy object that reads, writes, and enumerates keys on a specific carrier type.
Propagators never touch a carrier directly; they receive a CarrierApi from
carrierApiFor/defaultCarrierApiFor so the same inject/extract logic works
against plain objects, Headers, Map, or any bespoke transport. Supply a
custom implementation when your carrier does not match CarrierLike.
import type { CarrierApi } from 'internal:opentelemetry/common';
const mapApi: CarrierApi<Map<string, string>> = {
get: (m, k) => m.get(k),
set: (m, k, v) => void m.set(k, String(v)),
keys: (m) => [...m.keys()],
};
Methods
get(target: TCarrier, key: string): unknown
get method on CarrierApi.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
const member: CarrierApi['get'] = undefined as never;
set(target: TCarrier, key: string, value: unknown): void
set method on CarrierApi.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
const member: CarrierApi['set'] = undefined as never;
keys(target: TCarrier): string[]
keys method on CarrierApi.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
const member: CarrierApi['keys'] = undefined as never;
interface Disposable {
A teardown handle returned by an instrumentation's enable to undo its patches.
Calling dispose should reverse whatever the instrumentation installed
(topic subscriptions, monkey-patches) and must be idempotent. An
instrumentation may return one, several, or none of these.
import type { Disposable } from 'internal:opentelemetry/common';
const handle: Disposable = { dispose() { console.log('unhooked'); } };
handle.dispose();
Methods
dispose(): void
dispose method on Disposable.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
const member: Disposable['dispose'] = undefined as never;
interface ExportResult {
The outcome an exporter resolves with after attempting to send a batch.
code is 'success' when the batch was delivered (including partial-success
responses that the exporter chose to accept) and 'failure' when it was not.
Processors use this to decide whether to retry or drop the batch.
import type { ExportResult } from 'internal:opentelemetry/common';
const result: ExportResult = { code: 'success' };
Properties
code: 'success' | 'failure'
code property on ExportResult.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: ExportResult['code'];
interface Instrumentation {
A pluggable instrumentation that wires runtime events into the SDK when enabled.
enable is called once with the SDK and should install its hooks, optionally
returning Disposable(s) so the SDK can later tear them down. Returning
nothing means the instrumentation manages its own lifetime.
import type { Instrumentation } from 'internal:opentelemetry/common';
const noop: Instrumentation = {
enable(sdk) {
return { dispose() {} };
},
};
Methods
enable(sdk: OtelSdkLike): void | Disposable | Disposable[]
enable method on Instrumentation.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
const member: Instrumentation['enable'] = undefined as never;
interface OtelExporter {
The contract every telemetry exporter implements to receive batched records.
A processor calls the export* method for its signal with an array of records
and awaits an ExportResult. Implementations should resolve (never reject) so
the processor can act on the result code, and the optional shutdown should
flush and release transport resources.
import type { OtelExporter, ExportResult } from 'internal:opentelemetry/common';
const exporter: OtelExporter = {
async exportSpans(spans): Promise<ExportResult> {
console.log(spans.length, 'spans');
return { code: 'success' };
},
async exportLogs() { return { code: 'success' }; },
async exportMetrics() { return { code: 'success' }; },
};
Methods
exportSpans(spans: SpanRecord[]): Promise<ExportResult>
exportSpans method on OtelExporter.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
const member: OtelExporter['exportSpans'] = undefined as never;
exportLogs(logs: LogRecord[]): Promise<ExportResult>
exportLogs method on OtelExporter.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
const member: OtelExporter['exportLogs'] = undefined as never;
exportMetrics(metrics: MetricRecord[]): Promise<ExportResult>
exportMetrics method on OtelExporter.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
const member: OtelExporter['exportMetrics'] = undefined as never;
shutdown?(): Promise<void>
shutdown method on OtelExporter.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
const member: OtelExporter['shutdown'] = undefined as never;
interface OtelSdkLike {
The minimal SDK surface an Instrumentation needs to record signals and propagate context.
Exposes the active propagator plus record sinks for each signal.
recordSpanStart publishes a span's start before it ends, while recordSpan
publishes the completed span; recordLog and recordMetric handle the other
two signals. Instrumentations depend on this narrow interface rather than the
concrete SDK so they stay decoupled from the SDK implementation.
import type { OtelSdkLike, SpanRecord } from 'internal:opentelemetry/common';
function finish(sdk: OtelSdkLike, span: SpanRecord): void {
span.endTimeUnixNano = Date.now() * 1e6;
sdk.recordSpan(span);
}
Readonly Properties
readonly propagator: TextMapPropagator
propagator property on OtelSdkLike.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: OtelSdkLike['propagator'];
Methods
recordSpanStart(span: SpanRecord): void
recordSpanStart method on OtelSdkLike.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
const member: OtelSdkLike['recordSpanStart'] = undefined as never;
recordSpan(span: SpanRecord): void
recordSpan method on OtelSdkLike.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
const member: OtelSdkLike['recordSpan'] = undefined as never;
recordLog(log: LogRecord): void
recordLog method on OtelSdkLike.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
const member: OtelSdkLike['recordLog'] = undefined as never;
recordMetric(metric: MetricRecord): void
recordMetric method on OtelSdkLike.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
const member: OtelSdkLike['recordMetric'] = undefined as never;
interface PartialSuccessResult {
The partialSuccess payload an OTLP endpoint returns when it accepts some but not all items.
Each rejected* counter reports how many spans, logs, or data points the
backend dropped, and errorMessage explains why. A zero count with an empty
message indicates full success. Exporters surface this without treating it as
a transport failure.
import type { PartialSuccessResult } from 'internal:opentelemetry/common';
const partial: PartialSuccessResult = {
rejectedSpans: 2,
rejectedLogs: 0,
rejectedDataPoints: 0,
errorMessage: 'span attribute limit exceeded',
};
Properties
rejectedSpans: number
rejectedSpans property on PartialSuccessResult.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: PartialSuccessResult['rejectedSpans'];
rejectedLogs: number
rejectedLogs property on PartialSuccessResult.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: PartialSuccessResult['rejectedLogs'];
rejectedDataPoints: number
rejectedDataPoints property on PartialSuccessResult.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: PartialSuccessResult['rejectedDataPoints'];
errorMessage: string
errorMessage property on PartialSuccessResult.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: PartialSuccessResult['errorMessage'];
interface ProviderOptions {
Options shared by every signal provider (tracer, meter, logger).
resource describes the entity producing telemetry and may be a Resource, a
plain attribute map (normalized via normalizeResource), or null to accept
the default resource. Passed to BaseProvider.
import type { ProviderOptions } from 'internal:opentelemetry/common';
const options: ProviderOptions = {
resource: { 'service.name': 'checkout', 'service.version': '4.2.0' },
};
Properties
resource?: Resource | Attributes | null
resource property on ProviderOptions.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: ProviderOptions['resource'];
interface ResourceOptions {
Secondary options for constructing a Resource beyond its attribute map.
droppedAttributesCount records attributes elided before construction,
entityRefs declares OTel entity references (each with a type and identifying
key set), and schemaUrl pins the semantic-convention schema. All optional.
import { Resource } from 'internal:opentelemetry/common';
import type { ResourceOptions } from 'internal:opentelemetry/common';
const options: ResourceOptions = {
schemaUrl: 'https://opentelemetry.io/schemas/1.24.0',
};
const resource = new Resource({ 'service.name': 'api' }, options);
Properties
droppedAttributesCount?: number
droppedAttributesCount property on ResourceOptions.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: ResourceOptions['droppedAttributesCount'];
entityRefs?: Array<{
schemaUrl?: string;
type?: string;
idKeys?: string[];
}>
entityRefs property on ResourceOptions.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: ResourceOptions['entityRefs'];
schemaUrl?: string | null
schemaUrl property on ResourceOptions.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: ResourceOptions['schemaUrl'];
interface RetryOptions {
Exporter retry policy for transient export failures.
maxAttempts bounds the total number of tries and initialBackoffMillis is
the first backoff delay, typically grown exponentially on each retry. Omitting
a field falls back to the exporter's built-in default.
import type { RetryOptions } from 'internal:opentelemetry/common';
const retry: RetryOptions = { maxAttempts: 5, initialBackoffMillis: 250 };
Properties
maxAttempts?: number
maxAttempts property on RetryOptions.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RetryOptions['maxAttempts'];
initialBackoffMillis?: number
initialBackoffMillis property on RetryOptions.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RetryOptions['initialBackoffMillis'];
interface RuntimeDnsEvent {
Payload published on the otel:runtime:dns topics for a DNS lookup lifecycle.
lookupId correlates the phases of one lookup and requestId ties it back to
the originating HTTP request when known. hop orders multiple lookups within
a request. The resolved address/family and any error describe the
outcome. Consumed by the DNS instrumentation to build client spans.
import type { RuntimeDnsEvent } from 'internal:opentelemetry/common';
const event: RuntimeDnsEvent = {
lookupId: 'dns-1',
hostname: 'example.com',
address: '93.184.216.34',
family: 4,
};
Properties
lookupId: string
lookupId property on RuntimeDnsEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeDnsEvent['lookupId'];
requestId?: string
requestId property on RuntimeDnsEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeDnsEvent['requestId'];
hop?: number
hop property on RuntimeDnsEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeDnsEvent['hop'];
hostname?: string
hostname property on RuntimeDnsEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeDnsEvent['hostname'];
address?: string
address property on RuntimeDnsEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeDnsEvent['address'];
family?: string | number
family property on RuntimeDnsEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeDnsEvent['family'];
error?: unknown
error property on RuntimeDnsEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeDnsEvent['error'];
timeUnixNano?: number
timeUnixNano property on RuntimeDnsEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeDnsEvent['timeUnixNano'];
resource?: Resource
resource property on RuntimeDnsEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeDnsEvent['resource'];
interface RuntimeHttpRequestEvent {
Payload published on the otel:runtime:http.server/fetch topics for an HTTP request lifecycle.
requestId correlates the start, end, and error phases of one request.
method, route, url, and headers describe the request; statusCode and
error describe the outcome. The HTTP-server and fetch instrumentations
subscribe to these and translate them into spans.
import type { RuntimeHttpRequestEvent } from 'internal:opentelemetry/common';
const event: RuntimeHttpRequestEvent = {
requestId: 'req-1',
method: 'GET',
route: '/orders/:id',
statusCode: 200,
};
Properties
requestId: string
requestId property on RuntimeHttpRequestEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeHttpRequestEvent['requestId'];
method?: string
method property on RuntimeHttpRequestEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeHttpRequestEvent['method'];
route?: string
route property on RuntimeHttpRequestEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeHttpRequestEvent['route'];
url?: string
url property on RuntimeHttpRequestEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeHttpRequestEvent['url'];
headers?: CarrierLike
headers property on RuntimeHttpRequestEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeHttpRequestEvent['headers'];
statusCode?: number
statusCode property on RuntimeHttpRequestEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeHttpRequestEvent['statusCode'];
error?: unknown
error property on RuntimeHttpRequestEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeHttpRequestEvent['error'];
timeUnixNano?: number
timeUnixNano property on RuntimeHttpRequestEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeHttpRequestEvent['timeUnixNano'];
resource?: Resource
resource property on RuntimeHttpRequestEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeHttpRequestEvent['resource'];
interface RuntimeSocketEvent {
Payload published on the otel:runtime:socket topics for a TCP/socket connect lifecycle.
connectId correlates the phases of one connection attempt and requestId
ties it to the originating request. host, port, and transport describe
the peer; hop orders retries; error describes a failed connect. Consumed
by the socket instrumentation.
import type { RuntimeSocketEvent } from 'internal:opentelemetry/common';
const event: RuntimeSocketEvent = {
connectId: 'sock-1',
host: '10.0.0.5',
port: 443,
transport: 'tcp',
};
Properties
connectId: string
connectId property on RuntimeSocketEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeSocketEvent['connectId'];
requestId?: string
requestId property on RuntimeSocketEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeSocketEvent['requestId'];
hop?: number
hop property on RuntimeSocketEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeSocketEvent['hop'];
host?: string
host property on RuntimeSocketEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeSocketEvent['host'];
port?: number
port property on RuntimeSocketEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeSocketEvent['port'];
transport?: string
transport property on RuntimeSocketEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeSocketEvent['transport'];
error?: unknown
error property on RuntimeSocketEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeSocketEvent['error'];
timeUnixNano?: number
timeUnixNano property on RuntimeSocketEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeSocketEvent['timeUnixNano'];
resource?: Resource
resource property on RuntimeSocketEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeSocketEvent['resource'];
interface RuntimeTlsEvent {
Payload published on the otel:runtime:tls topics for a TLS handshake lifecycle.
handshakeId correlates the phases of one handshake and requestId ties it
to the originating request. hostname/port identify the peer, protocol
reports the negotiated TLS version, and error describes a failed handshake.
Consumed by the TLS instrumentation.
import type { RuntimeTlsEvent } from 'internal:opentelemetry/common';
const event: RuntimeTlsEvent = {
handshakeId: 'tls-1',
hostname: 'example.com',
port: 443,
protocol: 'TLSv1.3',
};
Properties
handshakeId: string
handshakeId property on RuntimeTlsEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeTlsEvent['handshakeId'];
requestId?: string
requestId property on RuntimeTlsEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeTlsEvent['requestId'];
hop?: number
hop property on RuntimeTlsEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeTlsEvent['hop'];
hostname?: string
hostname property on RuntimeTlsEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeTlsEvent['hostname'];
port?: number
port property on RuntimeTlsEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeTlsEvent['port'];
protocol?: string
protocol property on RuntimeTlsEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeTlsEvent['protocol'];
error?: unknown
error property on RuntimeTlsEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeTlsEvent['error'];
timeUnixNano?: number
timeUnixNano property on RuntimeTlsEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeTlsEvent['timeUnixNano'];
resource?: Resource
resource property on RuntimeTlsEvent.
Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.
let value: RuntimeTlsEvent['resource'];