npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@telemetry-dev/otel

v0.1.5

Published

Bring-your-own OpenTelemetry base layer for telemetry.dev: span processor and OTLP/protobuf trace exporter.

Readme

@telemetry-dev/otel

Bring-your-own OpenTelemetry base layer for telemetry.dev. It provides the span processor and OTLP/protobuf trace exporter used by @telemetry-dev/sdk, without requiring the SDK runtime.

npm i @telemetry-dev/otel

@opentelemetry/api is a peer dependency and is installed automatically by current npm and pnpm versions.

NodeSDK

import { NodeSDK } from "@opentelemetry/sdk-node";
import { TelemetrySpanProcessor } from "@telemetry-dev/otel";

const sdk = new NodeSDK({
  spanProcessors: [new TelemetrySpanProcessor()],
});

sdk.start();

Vercel / Next.js registerOTel

import { registerOTel } from "@vercel/otel";
import { TelemetrySpanProcessor } from "@telemetry-dev/otel";

export function register() {
  registerOTel({
    serviceName: "my-app",
    spanProcessors: [new TelemetrySpanProcessor()],
  });
}

BasicTracerProvider

import { trace } from "@opentelemetry/api";
import { BasicTracerProvider } from "@opentelemetry/sdk-trace-base";
import { TelemetrySpanProcessor } from "@telemetry-dev/otel";

const provider = new BasicTracerProvider({
  spanProcessors: [new TelemetrySpanProcessor()],
});

trace.setGlobalTracerProvider(provider);

Options

| Option | Fallback | Default / behavior | | -------------- | ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | apiKey | TELEMETRY_DEV_API_KEY | When absent and no spanExporter override is provided, the processor is a no-op. | | baseUrl | TELEMETRY_DEV_BASE_URL, then https://ingest.telemetry.dev | Trailing slashes are removed before building OTLP URLs. | | exportMode | — | "batched"; use "immediate" for serverless paths that flush explicitly. | | batch | — | Merged over { maxExportBatchSize: 64, scheduledDelayMillis: 1000, maxQueueSize: 2048, exportTimeoutMillis: 30000 }. | | spanFilter | — | Exports every span by default because attaching the processor is an explicit BYO choice. | | metrics | — | true; records GenAI duration/token histograms when an API key is present. | | serviceName | OTEL_SERVICE_NAME | unknown_service; used on the metrics resource. | | environment | TELEMETRY_DEV_ENVIRONMENT | production; used as deployment.environment.name on the metrics resource. | | fetch | — | globalThis.fetch; override for tests or custom runtimes. | | onError | — | Receives export and processor errors; errors are also reported through diagnostics. | | spanExporter | — | Advanced/test seam replacing the built-in OTLP trace exporter. |

Missing API key behavior

new TelemetrySpanProcessor() never throws. Without an API key, and without a spanExporter override, it becomes a no-op processor and emits only a debug-level diagnostic. This makes it safe to construct during local development or in environments where telemetry is disabled.

Raw span exporter

Use createTelemetrySpanExporter() when you want to keep your own BatchSpanProcessor or SimpleSpanProcessor but send OTLP/HTTP protobuf payloads to telemetry.dev.

import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
import { createTelemetrySpanExporter } from "@telemetry-dev/otel";

const processor = new BatchSpanProcessor(createTelemetrySpanExporter());

The exporter accepts apiKey, baseUrl, fetch, onError, and exportTimeoutMillis. The timeout caps each export request and defaults to 30,000 ms. The API key and base URL use the same environment variable fallbacks as TelemetrySpanProcessor.

Correlation attributes

propagateAttributes({ userId, sessionId, metadata }, fn) works standalone with BYO providers. The function stores correlation attributes in the same OTel context key that TelemetrySpanProcessor reads on span start, so spans created inside fn receive user.id, gen_ai.conversation.id, and td.metadata.* attributes without installing @telemetry-dev/sdk.

TelemetrySpanProcessor on your provider adds gen_ai.conversation.id, but it cannot change trace IDs. Use withSessionParent(context.active(), sessionId, apiKey) for each root span. A nonempty API key and session ID put each session root in the same trace. A deterministic session parent (SHA-256(apiKey ‖ 0x00 ‖ sessionId)) is the parent, but the SDK does not send it. If one value is empty, the function keeps the input context.

Install sessionSampler(yourSampler) on the provider before you use withSessionParent or sessionRootTracerProvider. The OTel API does not expose a provider's sampler. A context helper alone cannot keep the root policy. Pass the existing programmatic sampler to the wrapper. Without an argument, sessionSampler() reads OTEL_TRACES_SAMPLER and OTEL_TRACES_SAMPLER_ARG. It does not inspect an existing provider.

The wrapper uses the original parent context and the deterministic session trace ID for the sampling decision. Real active and explicit parents keep their sampling decisions. The framework-root wrapper reparents recognized turns inside workflow spans, but keeps the workflow parent's sampling policy and trace state. Context values and baggage stay intact.

sessionSpanContext only calculates IDs. Its flags are not a sampling decision. Do not use it directly as a parent.

import { context } from "@opentelemetry/api";
import {
  BasicTracerProvider,
  ParentBasedSampler,
  TraceIdRatioBasedSampler,
} from "@opentelemetry/sdk-trace-base";
import { sessionSampler, TelemetrySpanProcessor, withSessionParent } from "@telemetry-dev/otel";

const sampler = new ParentBasedSampler({ root: new TraceIdRatioBasedSampler(0.1) });
const provider = new BasicTracerProvider({
  sampler: sessionSampler(sampler),
  spanProcessors: [new TelemetrySpanProcessor()],
});
const span = provider
  .getTracer("my-app")
  .startSpan(
    "turn",
    {},
    withSessionParent(context.active(), sessionId, process.env.TELEMETRY_DEV_API_KEY),
  );
span.end();

The environment modes are always_on, always_off, traceidratio, parentbased_always_on (default), parentbased_always_off, and parentbased_traceidratio. Ratio modes accept a finite argument in [0, 1]. Missing, invalid, or out-of-range arguments use 1 and cause an OTel diagnostic. Unknown modes use parentbased_always_on. The TypeScript and Python SDKs share deterministic session IDs. Their built-in ratio samplers can select different sessions because the OTel algorithms differ.