Skip to content

feat(asap-precompute-go): bootstrap module + types + window + snapshot cache + OTel adapter (Phase 2 steps 2.1-2.4) - #219

Merged
zzylol merged 1 commit into
mainfrom
phase-2-bootstrap-asap-precompute-go
May 2, 2026
Merged

zzylol merged 1 commit into
mainfrom
phase-2-bootstrap-asap-precompute-go

Conversation

@zzylol

@zzylol zzylol commented May 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Bootstraps asap-precompute-go/ — the host-neutral edge-precompute runtime described in docs/design-asap-edge-framework.md and pinned by ADR-0002 and ADR-0003. This is Phase 2 steps 2.1-2.4 only.

  • Layer 3 (host-neutral runtime): Observation / SketchEnvelope / Encoding / SketchType / KeyValue types; PrecomputeConfig + PrecomputeConfigSet; tumbling-only windowState with MaxSeries/AllowedLateness; outbound + inbound SnapshotCache; Precompute interface + impl driving Observe/ObserveEnvelope/Tick/UpdateConfig/Stats/Shutdown; Sketch + SketchObserver interfaces for Layer-1 wrappers (steps 2.5-2.9).
  • Layer 4 (OTel adapter): otel.Adapter implements precompute.Adapter over pmetric.MetricsDecode produces host-neutral Observations (Gauge/Sum → KindFloat; DDSketch/KLL/HLL/CountSketch/CountMinSketch → KindEnvelope, no scalar expansion); Encode groups envelopes by ResourceLabels and emits typed sketch metrics; MetricSuffix/MetricName/ReadAsInt/WriteSeen/DropOriginal knobs from the feasibility audit.
  • Control channel trait: controlchannel/ControlChannel interface only — implementations (OpAmpChannel/HttpPollChannel/FileWatchChannel) land in step 2.10.
  • Critical regression: TestSeriesKey_ByteEquivalence (5 fixtures) checks that SeriesKey(aggID, resAttrs, dpAttrs, aggregateBy) is byte-identical to today's per-OTel-processor seriesKey + attributesKey output, so the snapshot cache survives the runtime extraction (ADR-0002 "Behavior preservation").

Out of scope (deferred follow-ups)

  • Steps 2.5-2.9: refactor each existing OTel processor (DDSketch, KLL, HLL, CountSketch, CountMinSketch) into a thin shim over this runtime. Each lands its own Sketch wrapper.
  • Step 2.10: ControlChannel implementations (OpAMP / HTTP-poll / file-watch).
  • Sliding window. Tumbling-only is enough for Phase 2.
  • Quantile-output mode (TransmitSketch=false → emit one gauge per quantile). Encode currently requires the runtime to keep TransmitSketch=true. The encode boundary doesn't have a Sketch instance to query — Phase 2.5 follow-up.

Test plan

  • go vet ./... — clean.
  • go build ./... — clean.
  • go test ./... -race -count=1 — 46 cases, all PASS.
  • gofmt -l . — empty (using Go 1.25.3 toolchain).
  • CI on this PR.
  • Steps 2.5-2.9 (per-shim refactor) wire each existing processor to call precompute.New(...) and verify byte-level snapshot-cache continuity against pre-existing windows.
  • Step 2.10 plugs in a real ControlChannel and confirms UpdateConfig swaps the active plan without dropping in-flight observations.

🤖 Generated with Claude Code

…t cache + OTel adapter (Phase 2 steps 2.1-2.4)

Brings in the host-neutral edge-precompute runtime per ADR-0002 and
ADR-0003. Layer-3 owns Observation / SketchEnvelope / windowing /
delta-encoding; Layer-4 OTel adapter implements Decode/Encode against
pmetric.Metrics. Steps 2.5-2.11 (per-shim refactor + ControlChannel
implementations) are out of scope.

Source files:
- observation.go / envelope.go: host-neutral input + output types,
  Encoding enum, SketchType enum, KeyValue, ResourceLabels.
- config.go: PrecomputeConfig + PrecomputeConfigSet (versioned plan),
  AggregationMode / OnOverflow / WindowSpec / SketchParams /
  Encoding / Quantiles fields.
- matchers.go: SeriesKey / AttributesKey byte-equivalent to today's
  per-OTel-processor seriesKey/attributesKey output.
- precompute.go: Precompute interface + impl, Sketch interface,
  Observe / ObserveEnvelope / Tick / UpdateConfig / Stats /
  Shutdown.
- window.go: tumbling windowState, OnOverflow{Drop,EvictOldest}
  policies, AllowedLateness drop, ResourceLabels propagation,
  observeEnvelope merge / apply-delta path.
- snapshot_cache.go: outbound (delta source-of-truth) + inbound
  (apply-delta target) caches with first-time / above-threshold
  semantics.
- telemetry.go: PrecomputeStats atomics + StatsSnapshot.
- adapter.go: Adapter interface (Decode/Encode/ScheduleTick/
  EmitTelemetry).
- controlchannel/channel.go: ControlChannel trait only; impls land
  in step 2.10.
- otel/{config,seriesattrs,decode,encode,adapter}.go: OTel-typed
  Adapter implementing precompute.Adapter against pmetric.Metrics;
  TransmitSketch=true output mode (quantile-output deferred to
  Phase 2.5).

Tests (46 cases, all green under -race):
- byte-equivalence regression for SeriesKey vs today's
  ddsketchprocessor::seriesKey + ::attributesKey (5 fixtures).
- end-to-end Tumbling rotate, late-data drop, MaxSeries Drop +
  EvictOldest, ResourceLabels propagation.
- snapshot cache: first-full / subsequent-delta / above-threshold-
  refresh / inbound round-trip / Reset.
- Precompute: full Observe→Tick path, DeltaTransmission state
  machine (PROTO_FULL → PROTO_DELTA → PROTO_FULL on threshold),
  UpdateConfig atomic swap, Stats accounting.
- OTel adapter: Decode for Gauge / Sum / DDSketch (envelope
  preservation, no scalar expansion), Encode grouping by
  ResourceLabels, MetricSuffix / MetricName, default scope name,
  delta encoding round-trip.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant