Skip to Content
GuidesTelemetry

Telemetry

txfence instruments the pipeline with spans compatible with OpenTelemetry. Every pipeline run produces a root span with child spans for each stage — policy evaluation, simulation, approval, and execution.

TelemetryProvider interface

interface TelemetryProvider { startSpan(name: string): Span } interface Span { setAttribute(key: string, value: string | number | boolean): void setStatus(status: 'ok' | 'error', message?: string): void end(): void }

Structurally compatible with OpenTelemetry spans — any OTel tracer satisfies this interface.

Wiring into createAgent

Pass as the 10th parameter to createAgent:

const agent = createAgent( config, adapters, rpcUrls, executor, undefined, undefined, undefined, // 5–7: capLockProvider, metadataVerifier, approvalProvider undefined, undefined, // 8–9: receiptStore, auditLog telemetryProvider, // 10: telemetryProvider )

Spans

Five spans are created per pipeline run:

SpanAttributes
txfence.pipelinechain, action.kind, status, rejection_reason, tx_hash, confirmed_at_block, staleness_ms
txfence.policy.evaluate
txfence.simulationprovider, coverage, gas_estimate, would_revert
txfence.approval
txfence.execution

txfence.pipeline ends in finally — guaranteed on every exit path including errors.

noopTelemetry

When no provider is configured, noopTelemetry is used — a singleton no-op with zero allocations. startSpan always returns the same shared noopSpan object.

import { noopTelemetry } from '@txfence/core'

OpenTelemetry integration

A @txfence/telemetry-otel package providing a real OpenTelemetry implementation is planned. In the meantime, wrap any OTel tracer:

import { trace } from '@opentelemetry/api' const tracer = trace.getTracer('txfence') const telemetryProvider: TelemetryProvider = { startSpan: (name) => tracer.startSpan(name), }

OTel spans have setAttribute, setStatus, and end — they satisfy the Span interface structurally.

Last updated on