This page covers the OTel-native API — the same primitives (
Span, SpanKind, SpanStatusCode) you’d use with the raw @opentelemetry/api / opentelemetry-api packages. If you just want to trace a custom operation and have it show up in the Zespan dashboard with evaluation scores, cost tracking, and status, use startSpan instead — it’s higher-level and integrates directly with Zespan’s own trace model.When to use this instead of startSpan
- You already export traces to an existing OTel backend and want Zespan’s spans to appear there too, dual-exported from the same instrumentation.
- You need direct access to the underlying OTel
Spanobject — for example, to set attributes withspan.setAttribute()or interoperate with another library that expects a native OTel span. - You’re building an integration that needs a real
TracerProviderregistered globally (some auto-instrumentation libraries look for one).
startSpan is almost always simpler — it doesn’t require a separate initOTel call and it feeds directly into Zespan’s cost, status, and evaluation-score model.
Relationship to enableOTel / otelEndpoint
The TypeScript and Python SDKs already have a simpler, declarative way to dual-export to an OTel backend: the enableOTel (enable_otel), otelEndpoint (otel_endpoint), and otelServiceName (otel_service_name) options passed to zespan.init() / zespan.init(). See Init options (TypeScript) and Init options (Python) for those.
The functions on this page — initOTel/init_otel and friends — are the manual, lower-level equivalent. Use them when you need to configure the TracerProvider yourself (custom resource attributes, a non-default sampler, multiple span processors) or when you want to create and manage OTel spans directly rather than going through zespan.init()’s declarative config. The two mechanisms are independent — calling initOTel does not require enableOTel to be set, and vice versa.
initOTel(config) / init_otel(config)
Configures a global OpenTelemetry TracerProvider with a BatchSpanProcessor and an OTLP HTTP exporter, and registers it as the active provider. Call this once at application startup, before creating any spans with getTracer/get_tracer.
initOTel returns { tracer, provider } — the registered Tracer and the underlying NodeTracerProvider. init_otel returns None; call get_tracer() afterward to retrieve the tracer.
OTelConfig
string
default:"https://localhost:3001/v1/traces"
OTLP HTTP endpoint that spans are exported to. Point this at your own collector or backend.
string
default:"zespan-sdk"
Service name attached as the
service.name resource attribute on every exported span. TypeScript field: serviceName. Python field: service_name.number
default:"1.0"
Fraction of traces to keep, decided once per trace from its trace id — the
same enforcement the native SDKs use, not a per-event roll. TypeScript
field:
sampleRate. Python field: sample_rate.Before this was enforced, an OTel-originated trace always sampled in at
100% regardless of this setting. If you’re upgrading from an older SDK
version and already had
sampleRate below 1.0 configured, your ingest
volume will drop to match it — this is the fix taking effect, not new
data loss.string
When set, sent as the
x-api-key header on every export request. TypeScript field: apiKey. Python field: api_key.string
default:"production"
Attached as the
deployment.environment resource attribute.getTracer() / get_tracer()
Returns the Tracer instance created by initOTel/init_otel. Throws (TypeScript: Error; Python: RuntimeError) if called before initialization.
createSpan / create_span
Starts and returns a native OTel span from the tracer configured by initOTel/init_otel. You are responsible for ending the span yourself — prefer withSpan/with_span below unless you need to manage the span lifecycle manually (for example, ending it from a different function than the one that created it).
string
required
Span name.
SpanKind
default:"SpanKind.INTERNAL"
OpenTelemetry span kind. See
SpanKind values below.Record<string, string | number | boolean | string[]>
Attributes set on the span at creation time. TypeScript accepts
attributes as an object property; Python accepts it as the attributes keyword argument (a dict).In Python,
kind and attributes are keyword-only arguments — create_span(name, *, kind=None, attributes=None).withSpan / with_span
Wraps a function call in a span, setting SpanStatusCode.OK on success or SpanStatusCode.ERROR (with the exception recorded) on failure, and always ending the span. This is the recommended way to create spans with this API — it guarantees the span is closed exactly once regardless of outcome.
withSpan<T>(name, fn, options?) — fn receives the span and returns a Promise<T>; withSpan returns that same Promise<T>. options accepts kind and attributes, same shape as createSpan.
Python: with_span(name, *, kind=None, attributes=None) is an async context manager (@contextlib.asynccontextmanager) — use it with async with, not as a function that takes a callback. It yields the span.
SpanKind values
SpanKind is re-exported from @opentelemetry/api as-is — it’s not a Zespan-specific type. The common values:
TypeScript exports
SpanKind directly from @zespan/sdk — import { SpanKind } from "@zespan/sdk". Python does not re-export SpanKind from the zespan package; import it from OpenTelemetry directly — from opentelemetry.trace import SpanKind.SpanStatusCode values
Used with span.setStatus({ code }) (TypeScript) / span.set_status(code) (Python) to record the outcome of the work a span covers.
TypeScript exports
SpanStatusCode directly from @zespan/sdk. Python does not — the underlying OTel API names this enum StatusCode, not SpanStatusCode. Import it yourself: from opentelemetry.trace import StatusCode.BaggageSpanProcessor
BaggageSpanProcessor is currently TypeScript-only — there is no Python equivalent exported from the zespan package.SpanProcessor that copies every entry in the current OTel baggage onto each span as a baggage.<key> attribute when the span starts. Zespan’s injectAgentContext/extractAgentContext helpers use OTel baggage to carry agent delegation metadata (agent.delegation.reason, agent.task) across an HTTP call to another service. Registering BaggageSpanProcessor on your TracerProvider is what makes that propagated metadata show up as searchable span attributes on the receiving side, rather than only being available on the wire.
BaggageSpanProcessor implements the standard OTel SpanProcessor interface (onStart, onEnd, shutdown, forceFlush) — add it alongside any other span processors (such as the BatchSpanProcessor used internally by initOTel) on a TracerProvider you construct yourself. It only acts on onStart; onEnd, shutdown, and forceFlush are no-ops.
initOTel does not register a BaggageSpanProcessor automatically. If you want baggage entries copied onto span attributes, add it explicitly when you construct your own TracerProvider.
