0gkitdocsGitHub

@foundryprotocol/0gkit-observability

OpenTelemetry instrumentation for 0gkit primitives. One call wires every Storage / Compute / DA / Attestation operation as an OTel span with 0gkit.* semantic attributes. Bundle ≤ 20 KB gzipped.

What it does

instrument0g() patches the public methods of Storage, Compute, and DA at runtime so every call emits an OTel span. The span name is 0gkit.<primitive>.<method> (e.g. 0gkit.storage.upload). Attributes include 0gkit.network, 0gkit.size_bytes, 0gkit.gas_native, 0gkit.fee_native, 0gkit.confirm_seconds, 0gkit.root, and so on. Failures record the exception, set the span status to ERROR, and attach 0gkit.error_code (the SCREAMING_SNAKE code from the error taxonomy).

When to use it

  • Production apps that need to know what's slow, what's expensive, and what's failing in their 0G calls.
  • Cost-attribution dashboards: 0gkit.gas_native + 0gkit.fee_native attributes feed straight into per-team / per-feature cost rollups.
  • Anywhere you already have an OTel collector (Honeycomb, Datadog, Tempo, Vercel OTel, Grafana Cloud).

Install

pnpm add @foundryprotocol/0gkit-observability @opentelemetry/api

# Only if you don't already have an OTel SDK configured:
pnpm add @opentelemetry/sdk-node @opentelemetry/exporter-trace-otlp-http

Quickstart — auto SDK setup

import { instrument0g } from "@foundryprotocol/0gkit-observability";

// At process boot, BEFORE any Storage / Compute / DA call:
await instrument0g({
  serviceName: "my-app",
  exporter: {
    kind: "otlp",
    endpoint: "https://api.honeycomb.io/v1/traces",
    headers: { "x-honeycomb-team": process.env.HONEYCOMB_API_KEY! },
  },
});

// From here, every Storage / Compute / DA call emits a span.
// Nothing else in your app needs to change.

Bring your own SDK (mode: "attach")

If you already configure @opentelemetry/sdk-node (or any other OTel SDK) in your app, pass mode: "attach" so instrument0g skips SDK setup and only patches primitives:

import { instrument0g } from "@foundryprotocol/0gkit-observability";

await instrument0g({ mode: "attach" });

Tests — patch fakes with explicit targets

Tests can patch fake classes by passing targets explicitly. This bypasses the dynamic imports of the real primitives, so it's also synchronous in practice (the await resolves immediately):

import { instrument0g, disinstrument0g } from "@foundryprotocol/0gkit-observability";

class FakeStorage {
  network = "galileo";
  async upload() {
    return { root: "0xabc" };
  }
}

await instrument0g({
  mode: "attach",
  targets: { storage: { class: FakeStorage, methods: ["upload"] } },
});

// Run tests against an in-memory exporter.

disinstrument0g(); // restores originals

Span attribute reference

All attribute keys live in a single frozen ATTR constant. Every key uses the 0gkit.* vendor namespace so collectors and cost calculators can filter on the prefix.

ConstantKeyNotes
ATTR.NETWORK0gkit.network"galileo" / "aristotle" / "local"
ATTR.OP0gkit.op"storage.upload", "compute.inference", …
ATTR.SIZE_BYTES0gkit.size_bytesBytes uploaded / downloaded / published
ATTR.SEGMENTS0gkit.segmentsStorage segments (256 KiB chunks)
ATTR.GAS_NATIVE0gkit.gas_nativeGas units (stringified bigint)
ATTR.FEE_NATIVE0gkit.fee_nativeNative wei fee (stringified bigint)
ATTR.CONFIRM_SECONDS0gkit.confirm_secondsConfirmation latency in seconds
ATTR.ROOT0gkit.rootStorage Merkle root
ATTR.TX_HASH0gkit.tx_hashTransaction hash
ATTR.BLOCK_NUMBER0gkit.block_numberBlock number
ATTR.MODEL0gkit.modelCompute model id
ATTR.INPUT_TOKENS0gkit.input_tokensInput tokens consumed
ATTR.OUTPUT_TOKENS0gkit.output_tokensOutput tokens generated (or max for estimates)
ATTR.ERROR_CODE0gkit.error_codeSCREAMING_SNAKE code from the error taxonomy
ATTR.DRY_RUN0gkit.dry_runtrue for .estimate() and { dryRun: true } calls

Standard OTel http.* / rpc.* attributes are layered on top by user instrumentation — we don't duplicate them.

What's wrapped today

PrimitiveMethods
Storageupload, download, estimate, exists
Computeinference, estimate
DApublish, estimate
Attestation(free functions — pass an explicit target only)

Attestation is currently a set of free functions, not a class. The default target set skips it; if you wire your own attestation client class, pass targets.attestation to instrument it. See docs/DECISIONS.md D32 for the rationale.

Bundle size

The public entry bundles to ≤ 20 KB gzipped. Asserted by bundle-size.test.ts on every CI run. @opentelemetry/api is externalised (peer dep); the optional SDK + exporter peers are lazy-imported and never reach the bundle unless the caller asks for them.

Exporter recipes

See also

Exports

  • type AttrKey
  • type ExporterConfig
  • type InstrumentConfig
  • type InstrumentMode
  • type InstrumentTargets