Skip to main content
@kubit-ai/otel sends OpenTelemetry spans from a Node or TypeScript app to Kubit. It has two entry points: configure() when Kubit is your only OpenTelemetry setup, and KubitSpanProcessor when your app already creates a tracer provider or a NodeSDK. This page covers both, the span filter, and the settings to check before production.

Before you start

  • Node.js 18 or later
  • OpenTelemetry JS SDK v2. Version 1 isn’t supported.
  • A Kubit API key in KUBIT_API_KEY
Kubit authenticates spans with an ingestion API key, read from the KUBIT_API_KEY environment variable. Each key belongs to one workspace.
Keep the key out of source control. Put it in .env or your secrets manager, and check that .env is in .gitignore.

Prompt for your coding agent

Install

Install the package and its OpenTelemetry peer dependencies:

Choose configure() or KubitSpanProcessor

@kubit-ai/otel has no attach(), unlike the Python SDK. OpenTelemetry JS SDK v2 takes span processors only when the provider is created, so there’s no way to add one to a provider that’s already running.
Don’t call configure() if your app already sets up a tracer provider or NodeSDK. configure() registers a second global provider and replaces the first, so your existing traces stop reaching their current destination.

You have no OpenTelemetry setup

Create kubit-instrumentation.ts and import it first in your entrypoint, before any LLM client is created:
kubit-instrumentation.ts
index.ts
Change serviceName, serviceVersion and deployment.environment to match your app. Kubit uses them to tell agents and releases apart.

configure() options

configure() returns the tracer provider it registered.

You already have a tracer provider

Pass KubitSpanProcessor in spanProcessors next to your other processors, when you create the provider.

NodeTracerProvider

tracing.ts

NodeSDK

instrumentation.ts

KubitSpanProcessor options

KubitSpanProcessor is an OpenTelemetry BatchSpanProcessor that drops non-LLM spans before they’re queued. For full control, KubitExporter is the plain exporter without filtering or batching. Wrap it in your own processor.

Span filtering

By default, KubitSpanProcessor sends only LLM-related spans to Kubit. HTTP, database and framework spans from other auto-instrumentation stay out of your workspace. A span is sent when any of these is true: KNOWN_LLM_INSTRUMENTATION_SCOPE_PREFIXES exports the full prefix list.

Keep spans from your own framework

tracing.ts

Send every span

tracing.ts
If shouldExportSpan throws, the span is dropped.

Trace LLM and tool calls

Kubit receives whatever spans your app produces. Spans from an LLM instrumentation library pass the default filter. With the Vercel AI SDK, turn on telemetry per call:
chat.ts
For tool calls, wrap each tool in its own span so it shows up as a step in the execution path:
tools.ts
Span attributes lists the keys Kubit reads, including user and session IDs.

Before production

@kubit-ai/otel doesn’t read the standard OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_TRACES_ENDPOINT variables. They apply to the whole process and would redirect Kubit’s traces if another OpenTelemetry SDK set them. Use KUBIT_OTEL_ENDPOINT instead.

Verify

Send a test span with debug logging on:
send-test-span.ts
The output includes these lines, among other debug lines:
Output
No Dropped span due to shouldExportSpan filter line for chat.completion means the span passed the filter.

If it fails

Next steps