Hire Team

INDUSAGI DOCUMENTATION

Tracing

Preserved documentation snapshot. APIs and capabilities differ by edition and version. Check the selected package before implementation. View pinned source.

View TypeScript Framework source on GitHub
On this page

src/tracing is the cross-cutting observability layer — a homegrown, OTel-free span tracer with a deliberately fresh vocabulary. Imported as indusagi/tracing, or as the tracing namespace from indusagi.

A trace is built from immutable Segment values (kinds run / inference / action / recall / custom) driven by a functional SegmentHandle (note / child / fail / close). A Recorder mints handles onto a SignalChannel async-iterable; sinks drain that channel and write somewhere. Sampled-out work collapses to the single frozen NOOP_HANDLE. No OpenTelemetry SDK is used — the data model re-derives the relevant W3C trace concepts.

Table of Contents

Public exports

src/tracing/index.ts re-exports seven layer barrels (export * over signal, channel, redaction, sinks, recorder, registry, adapter):

Export Kind Layer Purpose
Recorder class recorder The tracer that mints SegmentHandles onto a channel
SampleGate class recorder Admission control (SampleStrategy / RatioStrategy)
openSegment, withAttributes, closeSegment functions signal The Segment value constructors/derivations
openHandle, NOOP_HANDLE fn / const signal The sampled-in handle factory and the shared no-op
freshId, freshTraceId, freshSegmentId functions signal Id minting
SignalChannel class channel The async-iterable transport for TraceSignals
SecretScrubber processor redaction Attribute scrubbing before data leaves the process
ConsoleSink, FileSink, StreamSink classes sinks Terminal consumers that drain a channel
TelemetryHub, getDefaultHub, setDefaultHub class / fns registry The named-recorder registry + process default
traceAgentRun function adapter The optional runtime RunEvent bridge

Types include Segment, SegmentKind, SegmentStatus, TraceRecord, SegmentHandle, SignalSink; TraceSignal (OpenSignal / UpdateSignal / CloseSignal); Sink, ConsoleSinkOptions, FileSinkOptions, StreamSinkOptions; SampleStrategy, RatioStrategy, OpenOptions, RecorderOptions; and RunEventSubscribe.

Sub-directories

Directory Holds
signal/ segment.ts (the Segment data model), handle.ts (SegmentHandle, NOOP_HANDLE)
channel/ signal.ts — the SignalChannel transport and the TraceSignal union
recorder/ recorder.ts (Recorder), sampling.ts (SampleGate)
redaction/ secret-scrubber.ts — the SecretScrubber processor and its default rules
sinks/ base.ts (Sink), console.ts, file.ts, stream.ts
registry/ hub.ts — the TelemetryHub and default-hub accessors
adapter/ runtime-trace.ts — traceAgentRun, the runtime bridge

Recording a trace

A Recorder opens a root SegmentHandle; child nests, note annotates, fail marks an error, and close ends a segment, emitting a TraceSignal on the channel:

import { Recorder, ConsoleSink } from "indusagi/tracing";

const recorder = new Recorder(/* RecorderOptions */);
const sink = new ConsoleSink(/* ConsoleSinkOptions */);
// drain recorder's channel into the sink …

const run = recorder.open("run", "build");
const step = run.child("action", "edit");
step.note({ file: "x.ts" });
step.close();
run.close();

SampleGate admission control decides whether work is recorded; sampled-out work gets the frozen NOOP_HANDLE, so the call sites are uniform regardless of sampling.

Sinks, redaction, and the registry

A Sink (drain / optional flush / close) is a terminal consumer of a SignalChannel: ConsoleSink writes one pretty line per closed segment, FileSink appends NDJSON TraceRecords to a path, and StreamSink writes JSON lines to an injected Writable. The SecretScrubber processor sanitizes segment attributes before they leave the process. TelemetryHub is a registry of named recorders, with getDefaultHub / setDefaultHub for an opt-in process default.

The runtime adapter

traceAgentRun is the optional bridge that projects a runtime RunEvent stream onto a Recorder as nested run / inference / action segments. The adapter is the one place tracing knows the runtime's event vocabulary; the rest of the subsystem stays runtime-agnostic:

import { Recorder, traceAgentRun } from "indusagi/tracing";

const recorder = new Recorder();
traceAgentRun(recorder, agent.subscribe);  // agent from indusagi/runtime

Relationship to neighbors

Tracing is cross-cutting: it consumes the Runtime's RunEvent stream through the adapter but never the other way around — the runtime has no dependency on tracing. Every other layer can be observed by recording its own segments.

Back to the Architecture overview.