Skip to content

feat: add apply dedup and flush delivery telemetry - #575

Open
vahidlazio wants to merge 14 commits into
mainfrom
vahidt/apply-dedup-telemetry
Open

feat: add apply dedup and flush delivery telemetry#575
vahidlazio wants to merge 14 commits into
mainfrom
vahidt/apply-dedup-telemetry

Conversation

@vahidlazio

Copy link
Copy Markdown
Collaborator

Summary

  • Add ApplyDedupTelemetry (proto field 10) tracking dedup counters: applies_total, applies_deduped, applies_not_cached, sweeps, map_size, map_capacity
  • Add flush_succeeded/flush_failed (proto fields 11-12) tracking WriteFlagLogs batch delivery outcomes across all providers
  • Host SDKs (JS, Java, Go, Python) track delivery locally and merge into TelemetryData before next send — zero WASM overhead, no resolve contention
  • Cloudflare resolver tracks delivery in queue consumer

Apply Dedup Metrics

Metric Type Description
applies_total delta counter Total flag applies entering dedup filter
applies_deduped delta counter Duplicates filtered out
applies_not_cached delta counter Passed through but not cached (map full)
sweeps delta counter Sweep operations executed
map_size gauge Current dedup map entries
map_capacity gauge Max allowed entries

Flush Delivery Metrics

Metric Type Description
flush_succeeded delta counter Successful WriteFlagLogs batch deliveries
flush_failed delta counter Failed WriteFlagLogs batch deliveries

Compatibility

Proto fields are additive — old consumers ignore them. Follow-up PRs needed:

  • epx-flags-admin: convertApplyDedup + convertFlush in VictoriaMetricsClient
  • epx-flags-resolver: same (has its own VictoriaMetricsClient)
  • epx-insights: GraphType entries + PromQL queries for dashboards

Test plan

  • 447 Rust unit tests pass (7 new tests for dedup counters, proto delta, Prometheus rendering, accumulate_delta, flush counters)
  • Clippy clean on confidence_resolver + confidence-cloudflare-resolver
  • JS provider build
  • Java provider build
  • Go provider build
  • Python provider proto regeneration
  • Integration test with dedup enabled

🤖 Generated with Claude Code

vahidlazio and others added 10 commits September 1, 2026 16:14
Add telemetry for the apply deduplication feature and WriteFlagLogs
batch delivery outcomes across all providers.

Apply dedup telemetry (ApplyDedupTelemetry, field 10 on TelemetryData):
- applies_total, applies_deduped, applies_not_cached, sweeps (delta counters)
- map_size, map_capacity (gauges)
- Tracked via inline u64 counters on ApplyDedup — zero overhead
- Wired into WASM guest (bounded_flush_logs + prometheus_snapshot)
- Wired into Cloudflare resolver (per-request delta)

Flush delivery telemetry (fields 11-12 on TelemetryData):
- flush_succeeded, flush_failed (delta counters)
- Host SDKs track delivery outcomes locally and merge into TelemetryData
  before the next send — zero WASM calls, no resolve-path contention
- JS: addFlushDeliveryTelemetry() decode/set/encode
- Java: drainFlushCounters() on WasmFlagLogger, merged in ProviderTelemetryResolver
- Go: atomic counters, swap-and-inject in Write()
- Python: counters merged in _write_logs()
- Cloudflare: tracked in queue consumer via update_prometheus_kv()

Proto fields are additive — old consumers ignore them. Follow-up PRs
needed in epx-flags-admin and epx-flags-resolver (VictoriaMetricsClient
converters) and epx-insights (dashboard GraphType entries) to display
the metrics.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add events_published, event_batches_succeeded, event_batches_failed
(proto fields 13-15 on TelemetryData) to track event pipeline delivery
outcomes. Piggybacked on the flag logs TelemetryData channel since the
events pipeline has no telemetry path of its own.

Host SDKs track event delivery locally and merge counters into
TelemetryData during the next flag logs flush — same zero-overhead
pattern as flush_succeeded/flush_failed.

- JS: counters in addFlushDeliveryTelemetry alongside flush counters
- Java: drainEventCounters() on provider, merged in ProviderTelemetryResolver
- Go: RecordEventBatch() on FlagLogger interface, drained in Write()
- Python: _event_telemetry_* counters, drained in _write_logs()
- Cloudflare: update_events_kv() in queue consumer after delivery

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…on failure

- Remove duplicate map_size Prometheus block in write_apply_dedup
  (would cause Prometheus/OpenMetrics parser rejection)
- Cloudflare: only increment events_published on successful delivery
- Java: use separate telemetryFlushSucceeded/telemetryFlushFailed counters
  instead of reusing failures (which races with the periodic log window)
- Add OpenMetrics parser test with all new telemetry types
- Add accumulate_delta test for event counters

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bugs fixed:
- Remove duplicate map_size Prometheus block (would break scrapers)
- Cloudflare: only count events_published on successful delivery
- Java: separate telemetryFlushSucceeded/Failed counters to avoid
  racing with the existing periodic log window
- Go: add RecordEventBatch to test mocks (CapturingFlagLogger,
  trackingFlagLogger, MockFlagLogger) — adding the method to the
  FlagLogger interface broke all existing tests

Tests added:
- OpenMetrics parser test with all new telemetry types
- Event counter accumulate_delta test

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add the ApplyDedupTelemetry message to the shared provider proto so
host SDKs can read dedup counters (applies_total, applies_deduped,
applies_not_cached, sweeps, map_size, map_capacity) from TelemetryData.

Verified under concurrent load test (2000 resolves, 2000 events):
- applies_total correctly counts only matching resolves entering dedup
- applies_deduped shows 97.4% dedup ratio for repeated same-user resolves
- map_size/map_capacity gauges report correct values
- Zero applies_not_cached (map well within capacity)
- No panics or data races under concurrent load

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Go provider's embedded WASM must be built in Docker for
deterministic output. The locally-built binary doesn't match
the CI Docker build, failing the WASM sync check.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previously committed Python proto was missing apply_dedup (field 10),
events_published (field 13), event_batches_succeeded (field 14), and
event_batches_failed (field 15). The provider code references these
fields and would crash at runtime with AttributeError.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Docker-built WASM reflecting apply_dedup telemetry changes in
confidence-resolver.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vahidlazio
vahidlazio marked this pull request as ready for review September 2, 2026 13:25
vahidlazio and others added 4 commits September 2, 2026 15:29
…itTelemetry

TypeScript strict mode requires all non-optional fields. The existing
TelemetryData literal in addProviderInitTelemetry was missing the new
flush and event counter fields.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ts-proto drops unknown fields during decode→encode. The provider proto
was missing resolveLatency, resolveRate, stateAge, memoryBytes — fields
set by the WASM guest that must survive when hosts re-encode
TelemetryData (in addFlushDeliveryTelemetry, addProviderInitTelemetry).

Without these fields, JS resolve-logging tests fail because resolve
rate and latency telemetry are stripped during re-encoding.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Align with epx-flags-resolver PR #1734: restructure flush and events
telemetry from flat fields (11-15) to nested messages (11-12).

TelemetryData.flush = FlushTelemetry { succeeded, failed }
TelemetryData.events = EventsTelemetry { published, batches_succeeded, batches_failed }

Updated across all providers: JS, Java, Go, Python, Cloudflare, and
core Rust telemetry. WASM rebuilt in Docker for Go sync check.

Also adds WASM-produced fields (resolve_latency, resolve_rate,
state_age, memory_bytes) to provider proto so decode→encode
round-trips in ts-proto preserve them.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (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