Skip to content

Tracing

Export OTLP spans to OpenGrade and annotate them.

Use the methods of your Opengrade instance: og.trace, og.span, og.set_user, … They take the same arguments as the module-level functions documented below, and always go to that instance. The module-level functions go to the instance activated with og.activate().

trace

trace(name: Any = None, **options: Any) -> Any

Trace a function in this instance's project: @og.trace or @og.trace(...).

Same options as opengrade.trace (name, kind, metrics, redact, ...). Unlike it, the call is routed to this instance without activate(), and tracing starts by itself (init_tracing() defaults) if it was not initialized.

span

span(name: str, kind: str = 'CHAIN', *, input: object = None, attributes: dict[str, object] | None = None, live: bool | None = None) -> span

Trace a block as a span of this instance (with or async with).

init_tracing

init_tracing(*, project_id: str | None = None, project_slug: str | None = None, endpoint: str | None = None, service_name: str | None = None, instrument: Literal['auto', False] | Sequence[str] = 'auto', force: bool = False, live: bool | None = None, live_sample_rate: float | None = None, trace_sample_rate: float | None = None, max_capture_bytes: int | None = None, metrics_workers: int | None = None, version: str | None = None, environment: str | None = None, **kwargs: Any) -> None

Configure OTLP export for this instance via the shared TracerProvider.

flush

flush(timeout_millis: int = 5000, *, runtime: _Runtime | None = None) -> bool

Flush spans, then production metrics, then queued trace scores.

timeout_millis is the total budget: each stage gets what the previous left. Metrics are drained before scores are flushed because they produce scores.

trace

trace(name: Callable[P, R]) -> Callable[P, R]
trace(name: str | None = None, *, kind: str = 'CHAIN', capture_input: bool = True, capture_output: bool = True, live: bool | None = None, metrics: Sequence[LocalMetric | Callable[..., Any]] | None = None, metrics_sample_rate: float = 1.0, redact: Callable[[str, Any], Any] | None = None, redact_output: Callable[[Any], Any] | None = None, join_chunks: Callable[[Any, Any], Any] | None = None) -> Callable[[Callable[P, R]], Callable[P, R]]
trace(name: str | Callable[P, R] | None = None, *, kind: str = 'CHAIN', capture_input: bool = True, capture_output: bool = True, live: bool | None = None, metrics: Sequence[LocalMetric | Callable[..., Any]] | None = None, metrics_sample_rate: float = 1.0, redact: Callable[[str, Any], Any] | None = None, redact_output: Callable[[Any], Any] | None = None, join_chunks: Callable[[Any, Any], Any] | None = None) -> Any

Trace a function as an OpenInference span.

Dispatches on function kind: sync, async def, generator, or async generator. For generator and async-generator functions the span is current only during each advance (next() / __anext__); between yields it is not the active context. Streamed chunks are accumulated into output.value: plain strings and common LLM delta shapes are joined as text by default. Pass join_chunks(chunk, acc) to replace that reducer (acc starts as None); join errors are stored as "<join error>". Plain sync/async functions ignore join_chunks.

metrics=[...] scores each sampled production call after it returns (off the request path) and stores the results as trace scores; metrics_sample_rate is the fraction of traces scored, deterministic per trace. Skipped inside experiments. Metrics are not supported on generator / async-generator functions.

span

span(name: str, kind: str = 'CHAIN', *, input: object = None, attributes: dict[str, object] | None = None, live: bool | None = None)

Trace a block of code as a child span (sync with or async with).

::

with opengrade.span("rerank", kind="RERANKER", input=query) as s:
    ranked = reranker.rank(query, docs)
    s.set_output([d.id for d in ranked])
    s.set_attribute("rerank.top_k", 5)

kind is an OpenInference span kind (CHAIN, LLM, RETRIEVER, RERANKER, EMBEDDING, TOOL, AGENT, GUARDRAIL, ...). An exception raised in the block marks the span ERROR and propagates. Like @opengrade.trace, the outermost span outside an experiment becomes a live interaction when init(live=True); pass live=False to opt out.

SpanHandle

SpanHandle(span: Span | None)

The span opened by opengrade.span; every method is a no-op when not recording.

is_recording property

is_recording: bool

trace_id property

trace_id: str | None

span_id property

span_id: str | None

set_input

set_input(value: object) -> None

Set input.value on this span (the experiment / production input is unchanged).

set_output

set_output(value: object) -> None

Set output.value on this span (the experiment output is unchanged).

set_attribute

set_attribute(key: str, value: object) -> None

set_attributes

set_attributes(attrs: dict[str, object] | None = None, **kwargs: object) -> None

set_error

set_error(description: str, *, exception: BaseException | None = None) -> None

current_trace_id

current_trace_id() -> str | None

Return the current OTLP trace id as 32-char hex, or None if inactive.

set_input

set_input(value: object) -> None

Set OpenInference input.value on the current span (and production metrics' input).

set_output

set_output(value: object) -> None

Set OpenInference output.value on the current span (and production metrics' output).

set_error

set_error(description: str, *, exception: BaseException | None = None) -> None

Mark the current span as ERROR (optionally attach an exception).

set_attribute

set_attribute(key: str, value: object) -> None

Set one attribute on the current opengrade span (no-op if none is active).

set_attributes

set_attributes(attrs: dict[str, object] | None = None, **kwargs: object) -> None

Set multiple attributes on the current opengrade span.

set_user

set_user(user_id: str | None) -> None

Set the end user (user.id) of the current trace.

Call it inside a traced call (@opengrade.trace or opengrade.span); the platform lifts it to the trace, so any span of the trace works. No-op otherwise.

set_session

set_session(session_id: str | None) -> None

Set the session / conversation (session.id) of the current trace.

set_tags

set_tags(*tags: str) -> None

Add tags (tag.tags) to the current trace; repeated calls accumulate.

set_metadata

set_metadata(metadata: Mapping[str, object] | None = None, **kwargs: object) -> None

Merge key/value metadata (metadata) into the current trace.

Values should be scalars (str, int, float, bool); anything else is stored as JSON text. Keys starting with _ are reserved and ignored. Traces can be filtered by key:value in the UI and API.

using_attributes

using_attributes(*, user_id: str | None = None, session_id: str | None = None, tags: Iterable[str] | None = None, metadata: Mapping[str, object] | None = None) -> Iterator[None]

Attach user / session / tags / metadata to every span opened in this block.

Blocks nest: inner ids win, tags and metadata accumulate. Useful in a request middleware, where the user is known before any traced call starts::

with opengrade.using_attributes(user_id=user.id, session_id=chat_id, tags=["beta"]):
    answer(question)