Skip to main content

ADR-019: SDK Telemetry for Prover and Solver

StatusProposed
Date2026-04-22

Context

The SDK runs on partner clients and we have no field visibility into prove/solve latencies, failure rates, or device mix. Our benchmarks are biased toward engineer machines. This ADR describes what the SDK reports to a telemetry backend operated by the SDK team (a Grafana stack, over OpenTelemetry), and what it deliberately does not.

Key constraint: No data identifying end-users, their activity, or any secrets may leave their device.

Proposal

What we collect

The SDK emits one event per call to solver.init, solver.solve, prover.prewarm, and prover.prove. Each event carries a duration, an ok/error outcome, and attributes drawn from a strict allowlist. No user identifier is emitted anywhere.

AttributeTypeNotes
sdk.versionstringfrom the SDK package
sdk.platformenumnode / web / react-native
partner.idstringpartnerTelemetryId from config
environmentenumproduction / staging / test
proof.kindenumprover events only: encrypted_transfer / encrypted_to_public / epk_ownership
solver.foundboolsolver.solve only
solver.value_bucketenumsolver.solve only: <100 / <1k / <10k / <100k / <1M / 1M+
device.*bucketedbrowser only: class, cores, memory_gb, connection
browser.name / browser.majorenum / intbrowser only
os.name / os.majorenum / intbrowser only
wasm.simd / wasm.threadsboolfeature detection
witness_build_ms / proof_generate_msintprover.prove only, sub-stage durations flattened onto the parent event
error.classstringerror outcomes only: the JS error constructor name, never the message

What we deliberately don't collect

We do NOT collect raw navigator.userAgent (replaced by bucketed browser and OS fields), screen dimensions, timezone offset, client IP, any input to solve or prove, raw error messages.

No client timestamps: time is marked on receive of a batch of events. SDK does not log any timing data beyond the duration of each computation.

Opt-in

Telemetry is off by default. Activation requires an explicit partnerTelemetryId in the runtime config.

Batching

Events accumulate in an in-memory queue. A timer fires every 15 seconds: if the queue is non-empty, events are serialized into one batch and POSTed; if empty, no network call is made. Additional flushes happen on runtime destroy, page unload.

Flushes are fire-and-forget — a failing response drops the batch.