T

TypeScript SDK

Pure TypeScript SDK for LLM traces, logs, and GenAI metrics. Works on Node and edge runtimes, built on OpenTelemetry with zero lock-in.

Built by

telemetry.dev

Language

TypeScript

Packages

@telemetry-dev/sdk · @telemetry-dev/otel

Category

SDKs

About the TypeScript SDK

@telemetry-dev/sdk adds LLM traces, logs, and GenAI metrics to any TypeScript or JavaScript app. Spans use the gen_ai.* semantic conventions and ship as OTLP protobuf. It runs on Node >= 20.19 and edge runtimes — Vercel Edge and Cloudflare Workers with nodejs_compat — and is the foundation the OpenAI, Anthropic, Gemini, and Bedrock wrappers build on.

Key features

  • Ergonomic span API: observe(fn) wraps any function (args become input, return becomes output); startSpan and startActiveSpan give manual control with typed generation fields.
  • User and session correlation: propagateAttributes({ userId, sessionId, metadata }, fn) stamps every span and log record in scope.
  • Logs and metrics included: log() emits trace-correlated log records; GenAI duration and token-usage histograms are recorded automatically.
  • Serverless-ready: exportMode: "immediate" plus flush() or the platform's waitUntil keep data flowing from frozen isolates.
  • Bring your own OTel: Already running NodeSDK or @vercel/otel? Attach TelemetrySpanProcessor from @telemetry-dev/otel to your existing provider instead.
  • Fail-open: Without an API key every call is a silent no-op — the SDK never throws into your code.

Get started

import { init, startSpan, flush } from "@telemetry-dev/sdk";

init({ apiKey: process.env.TELEMETRY_DEV_API_KEY });

const generation = startSpan("chat-completion", {
  type: "generation",
  model: "gpt-4o",
  provider: "openai",
  input: [{ role: "user", content: "What is OTLP?" }],
});
const res = await llm.chat("What is OTLP?");
generation.end({
  output: res.message,
  usage: { inputTokens: res.usage.input, outputTokens: res.usage.output },
});

await flush();

Cost is computed server-side from usage and current model pricing — set costUsd only when you want to override it.