Skip to content

feat: multi-destination flag log routing - #483

Open
vahidlazio wants to merge 13 commits into
mainfrom
feat/multi-destination-flag-logs
Open

feat: multi-destination flag log routing#483
vahidlazio wants to merge 13 commits into
mainfrom
feat/multi-destination-flag-logs

Conversation

@vahidlazio

Copy link
Copy Markdown
Collaborator

Summary

  • Add LogDestination enum (EDGE / CLOUDFLARE) to ResolverState proto (field tag 11, backwards compatible — unset defaults to Edge)
  • Parse log_destination in Rust ResolverState::from_proto and expose as typed enum
  • Route flag logs in Cloudflare worker queue consumer based on account's configured destination
  • Add new confidence-flag-log-ingest worker crate — receives WriteFlagLogsRequest via HTTP, writes NDJSON to R2 with account-level folder partitioning (flag-logs/{account_id}/date=.../hour=.../)

Deployment order

  1. Merge this PR (backwards compat — all accounts default to Edge)
  2. Deploy ingest worker to Spotify's Cloudflare account
  3. Set log_destination=CLOUDFLARE on test account via flags-admin (separate PR)
  4. Verify logs land in R2, then gradual rollout

Flags-admin changes (separate PR)

  • Add log_destination to admin's copy of resolver.proto
  • Populate field when building ResolverState for CDN push
  • Account-level setting API

Test plan

  • All 371 existing unit tests pass
  • All 3 crates compile (confidence_resolver, confidence-cloudflare-resolver, confidence-flag-log-ingest)
  • Deploy ingest worker, send synthetic WriteFlagLogsRequest, verify NDJSON in R2
  • Build test state proto with log_destination=CLOUDFLARE, deploy CF resolver, verify logs routed to ingest worker

🤖 Generated with Claude Code

vahidlazio and others added 6 commits August 6, 2026 11:57
Add account-level log destination configuration so the Cloudflare
resolver can route flag logs to either the existing edge endpoint
or a new Cloudflare ingest worker that stores logs as NDJSON in R2.

- Add LogDestination enum to ResolverState proto (tag 11)
- Parse log_destination in Rust ResolverState::from_proto
- Route logs in CF worker queue consumer based on state destination
- Add new confidence-flag-log-ingest worker crate (R2 storage with
  account-level folder partitioning)

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

- Proto: change to `repeated LogDestination log_destinations` so logs
  can be sent to multiple destinations simultaneously
- Rust lib: parse as Vec<LogDestination>, default to [Edge] when empty
- CF worker: iterate over all destinations and send to each
- Ingest worker: flat file naming {account}_{timestamp}_{uuid}.ndjson

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Keep proto enum name in sync with admin repo.

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

Read log_destinations from SetResolverStateRequest (ClientResolverState)
instead of from the inner ResolverState. Matches admin proto change.

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

Proves that log_destinations at tag 3 breaks WASM parsing
(InvalidProtocolBufferException) while tag 4 is safely skipped.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Update Cloudflare destination URL to epx-flags-logs worker
- Encode flag logs as protobuf IngestFlagLogsRequest for Cloudflare
  destination instead of JSON (matching ingestor's expected format)
- Add encode_message helper to confidence-resolver for cross-prost-version
  protobuf encoding
- Add confidence-flag-log-ingest to Dockerfile build stages

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vahidlazio
vahidlazio force-pushed the feat/multi-destination-flag-logs branch from 3e42378 to acef531 Compare August 6, 2026 16:16
When log_destinations includes Cloudflare, the ingestor handles
forwarding to BQ. Sending to Edge as well would create duplicate
writes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vahidlazio
vahidlazio marked this pull request as ready for review August 6, 2026 20:13
vahidlazio and others added 6 commits August 6, 2026 16:20
When both Cloudflare and Edge destinations are configured, Cloudflare
is always primary regardless of order in the state, with Edge as the
retry fallback on failure (HTTP 4xx/5xx or network error). Single
destination (Cloudflare-only or Edge-only) sends to that destination
only.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The workspace lists confidence-flag-log-ingest as a member, so every
stage that runs cargo against the workspace needs the crate present.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The crate denies clippy::expect_used; encoding into a Vec cannot fail,
so use prost's infallible encode_to_vec instead.

Co-Authored-By: Claude Fable 5 <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