From 45f8bc7ce3097dd3ab084117b55e2c935b7d5163 Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Tue, 1 Sep 2026 16:14:31 +0200 Subject: [PATCH 01/25] feat: add apply dedup and flush delivery telemetry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- confidence-cloudflare-resolver/src/lib.rs | 77 +++-- .../flags/resolver/v1/internal_api.proto | 19 ++ confidence-resolver/src/apply_dedup.rs | 131 ++++++++ confidence-resolver/src/telemetry.rs | 287 ++++++++++++++++++ .../confidence/internal/flag_logger/grpc.go | 26 +- .../confidence/internal/flag_logger/multi.go | 27 +- .../proto/resolverinternal/internal_api.pb.go | 28 +- .../confidence/sdk/GrpcWasmFlagLogger.java | 15 +- .../sdk/OpenFeatureLocalResolveProvider.java | 2 + .../sdk/ProviderTelemetryResolver.java | 29 +- .../confidence/sdk/WasmFlagLogger.java | 8 + .../js/src/ConfidenceServerProviderLocal.ts | 20 ++ .../flags/resolver/v1/internal_api.proto | 7 + .../flags/resolver/v1/internal_api_pb2.py | 106 +++---- .../python/src/confidence/provider.py | 35 ++- wasm/rust-guest/src/lib.rs | 28 +- 16 files changed, 741 insertions(+), 104 deletions(-) diff --git a/confidence-cloudflare-resolver/src/lib.rs b/confidence-cloudflare-resolver/src/lib.rs index 4eddedd87..0be50d893 100644 --- a/confidence-cloudflare-resolver/src/lib.rs +++ b/confidence-cloudflare-resolver/src/lib.rs @@ -1,7 +1,7 @@ mod materialization; use confidence_resolver::{ - apply_dedup::ApplyDedup, + apply_dedup::{ApplyDedup, ApplyDedupSnapshot}, assign_logger, flag_logger, proto::{confidence, google::Struct}, resolve_logger, @@ -51,6 +51,22 @@ thread_local! { static FLAG_LOG: RefCell> = const { RefCell::new(None) }; static APPLY_DEDUP: RefCell = RefCell::new(ApplyDedup::new(120, 100_000)); static APPLY_DEDUP_ENABLED: Cell = const { Cell::new(false) }; + static LAST_DEDUP_SNAPSHOT: RefCell = + RefCell::new(ApplyDedupSnapshot::default()); +} + +fn dedup_telemetry_delta() -> Option { + if !APPLY_DEDUP_ENABLED.with(|c| c.get()) { + return None; + } + let current = APPLY_DEDUP.with(|d| d.borrow().telemetry_snapshot()); + let prev = LAST_DEDUP_SNAPSHOT.with(|s| std::mem::replace(&mut *s.borrow_mut(), current.clone())); + let delta = current.to_proto_delta(&prev); + if delta.applies_total > 0 || current.map_size > 0 { + Some(delta) + } else { + None + } } /// Queues one request's flag log and sweeps the apply-dedup map. Called via @@ -497,6 +513,7 @@ pub async fn main(req: Request, env: Env, ctx: Context) -> Result { let mut td = telemetry::build_request_telemetry(elapsed_us, &reasons); td.sdk = Some(sdk_info()); + td.apply_dedup = dedup_telemetry_delta(); log.telemetry_data = Some(td); event_ctx.wait_until(queue_flag_log(log)); @@ -540,9 +557,10 @@ pub async fn main(req: Request, env: Env, ctx: Context) -> Result { Response::error(msg, 500)?.with_cors_headers(&allowed_origin) } }; - // Unlike resolve there is no telemetry to attach, so - // skip queueing when the apply logged nothing (an - // errored apply). + if let Some(dedup_delta) = dedup_telemetry_delta() { + let td = log.telemetry_data.get_or_insert_with(Default::default); + td.apply_dedup = Some(dedup_delta); + } if log != WriteFlagLogsRequest::default() { event_ctx.wait_until(queue_flag_log(log)); } @@ -704,11 +722,6 @@ async fn consume_flag_logs( let req = flag_logger::aggregate_batch(logs); - // Accumulate telemetry deltas into KV-backed cumulative snapshot for /metrics. - if let Ok(kv) = env.kv("CONFIDENCE_METRICS_KV") { - update_prometheus_kv(&kv, &req).await; - } - let client_secret = CONFIDENCE_CLIENT_SECRET.get().unwrap().as_str(); let account_id = CDN_STATE_REQUEST.account_id.as_str(); let destinations = &*LOG_DESTINATIONS; @@ -719,13 +732,15 @@ async fn consume_flag_logs( (destinations[0], None) }; - if let Err(reason) = deliver_flag_logs(client_secret, account_id, &req, primary).await { + let delivered = if let Err(reason) = + deliver_flag_logs(client_secret, account_id, &req, primary).await + { console_log!( "flag log delivery to {:?} failed ({}), trying fallback", primary, reason ); - let fallback_delivered = match fallback { + match fallback { Some(fb) => match deliver_flag_logs(client_secret, account_id, &req, fb).await { Ok(()) => true, Err(fb_reason) => { @@ -738,16 +753,19 @@ async fn consume_flag_logs( } }, None => false, - }; - if !fallback_delivered { - // Returning Err makes Cloudflare Queues redeliver the batch, - // so a delivery outage doesn't silently drop logs. The - // telemetry KV update above may run again on redelivery — - // acceptable for metrics. - return Err(worker::Error::RustError( - "flag log delivery failed on all destinations".to_string(), - )); } + } else { + true + }; + + if let Ok(kv) = env.kv("CONFIDENCE_METRICS_KV") { + update_prometheus_kv(&kv, &req, Some(delivered)).await; + } + + if !delivered { + return Err(worker::Error::RustError( + "flag log delivery failed on all destinations".to_string(), + )); } } @@ -778,9 +796,16 @@ async fn deliver_flag_logs( /// `TelemetrySnapshot` stored in KV, then write its Prometheus text /// representation for the /metrics endpoint. /// +/// `flush_result` records the outcome of the batch delivery: `Some(true)` +/// for success, `Some(false)` for failure, `None` to skip. +/// /// Note: concurrent queue consumer invocations can race on KV read-modify-write. /// Acceptable for metrics — at worst one batch's deltas are lost, not cumulative state. -async fn update_prometheus_kv(kv: &kv::KvStore, req: &WriteFlagLogsRequest) { +async fn update_prometheus_kv( + kv: &kv::KvStore, + req: &WriteFlagLogsRequest, + flush_result: Option, +) { let mut cumulative = match kv.get("snapshot").text().await { Ok(Some(text)) => serde_json::from_str::(&text).unwrap_or_default(), _ => TelemetrySnapshot::default(), @@ -790,6 +815,16 @@ async fn update_prometheus_kv(kv: &kv::KvStore, req: &WriteFlagLogsRequest) { cumulative.accumulate_delta(td); } + match flush_result { + Some(true) => { + cumulative.flush_succeeded = cumulative.flush_succeeded.wrapping_add(1); + } + Some(false) => { + cumulative.flush_failed = cumulative.flush_failed.wrapping_add(1); + } + None => {} + } + let prom_text = cumulative.to_prometheus( "cf-resolver", &confidence_resolver::telemetry::PrometheusConfig::default(), diff --git a/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto b/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto index 9a9c781f6..dde474cbe 100644 --- a/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto +++ b/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto @@ -132,6 +132,25 @@ message TelemetryData { repeated ProviderInitRate provider_init_rate = 9; + ApplyDedupTelemetry apply_dedup = 10; + + // Delta counters: WriteFlagLogs batch delivery outcomes since last flush. + // Populated by the host SDK after each delivery attempt. + uint32 flush_succeeded = 11; + uint32 flush_failed = 12; + + message ApplyDedupTelemetry { + // Delta counters (since last flush): + uint32 applies_total = 1; + uint32 applies_deduped = 2; + uint32 applies_not_cached = 3; + uint32 sweeps = 4; + + // Gauges (point-in-time): + uint32 map_size = 5; + uint32 map_capacity = 6; + } + message ProviderInitRate { uint32 count = 1; reserved 2; // status — tbd diff --git a/confidence-resolver/src/apply_dedup.rs b/confidence-resolver/src/apply_dedup.rs index f0b2d9490..56dafb14c 100644 --- a/confidence-resolver/src/apply_dedup.rs +++ b/confidence-resolver/src/apply_dedup.rs @@ -3,6 +3,7 @@ use std::hash::{BuildHasherDefault, Hasher}; use crate::proto::confidence::flags::resolver::v1::events::FallthroughAssignment; use crate::proto::confidence::flags::resolver::v1::resolve_token_v1::AssignedFlag; +use crate::proto::confidence::flags::resolver::v1::telemetry_data::ApplyDedupTelemetry; use crate::FlagToApply; const HASH_INIT: u64 = 0xCBF2_9CE4_8422_2325; @@ -152,11 +153,51 @@ pub fn compute_dedup_hash(assigned: &AssignedFlag) -> u64 { /// iteration would repeat the O(n) scan. const SWEEP_MIN_INTERVAL_SECONDS: i64 = 10; +/// Point-in-time snapshot of apply-dedup telemetry counters. +/// +/// Counter fields are cumulative (monotonically increasing). Gauge fields +/// (`map_size`, `map_capacity`) are latest values. +#[derive(Clone, Default)] +#[cfg_attr(feature = "json", derive(serde::Serialize, serde::Deserialize))] +pub struct ApplyDedupSnapshot { + pub applies_total: u64, + pub applies_deduped: u64, + pub applies_not_cached: u64, + pub sweeps: u64, + pub map_size: u32, + pub map_capacity: u32, +} + +impl ApplyDedupSnapshot { + /// Compute a proto delta relative to a previous snapshot, using wrapping + /// subtraction for counters and latest values for gauges. + pub fn to_proto_delta(&self, previous: &ApplyDedupSnapshot) -> ApplyDedupTelemetry { + ApplyDedupTelemetry { + applies_total: self.applies_total.wrapping_sub(previous.applies_total) as u32, + applies_deduped: self.applies_deduped.wrapping_sub(previous.applies_deduped) as u32, + applies_not_cached: self + .applies_not_cached + .wrapping_sub(previous.applies_not_cached) as u32, + sweeps: self.sweeps.wrapping_sub(previous.sweeps) as u32, + map_size: self.map_size, + map_capacity: self.map_capacity, + } + } + + pub fn has_activity(&self) -> bool { + self.applies_total > 0 + } +} + pub struct ApplyDedup { seen: HashMap, ttl_seconds: i64, max_entries: usize, last_sweep_seconds: i64, + applies_total: u64, + applies_deduped: u64, + applies_not_cached: u64, + sweeps: u64, } impl ApplyDedup { @@ -170,6 +211,21 @@ impl ApplyDedup { ttl_seconds, max_entries, last_sweep_seconds: 0, + applies_total: 0, + applies_deduped: 0, + applies_not_cached: 0, + sweeps: 0, + } + } + + pub fn telemetry_snapshot(&self) -> ApplyDedupSnapshot { + ApplyDedupSnapshot { + applies_total: self.applies_total, + applies_deduped: self.applies_deduped, + applies_not_cached: self.applies_not_cached, + sweeps: self.sweeps, + map_size: self.seen.len() as u32, + map_capacity: self.max_entries as u32, } } @@ -190,14 +246,18 @@ impl ApplyDedup { let now_seconds = now_seconds.max(self.last_sweep_seconds); let mut keep = DedupResult::new(flags.len()); for (i, fta) in flags.iter().enumerate() { + self.applies_total = self.applies_total.wrapping_add(1); let hash = compute_dedup_hash(fta.assigned_flag); // Presence means duplicate — stale entries are removed by sweep, // after which the flag gets re-logged on its next resolve. if self.seen.contains_key(&hash) { + self.applies_deduped = self.applies_deduped.wrapping_add(1); continue; } if self.seen.len() < self.max_entries { self.seen.insert(hash, now_seconds); + } else { + self.applies_not_cached = self.applies_not_cached.wrapping_add(1); } keep.mark(i); } @@ -214,6 +274,7 @@ impl ApplyDedup { return; } self.last_sweep_seconds = now_seconds; + self.sweeps = self.sweeps.wrapping_add(1); let ttl = self.ttl_seconds; self.seen .retain(|_, ts| now_seconds.saturating_sub(*ts) < ttl); @@ -1171,4 +1232,74 @@ mod tests { // sanity: cache holds all entries assert_eq!(dedup.seen.len(), total); } + + #[test] + fn telemetry_counters_basic() { + let mut dedup = ApplyDedup::new(120, 1000); + let flags = vec![ + make_flag_to_apply("flags/a", "user1", "on"), + make_flag_to_apply("flags/b", "user1", "off"), + ]; + + dedup.filter_duplicates(&flags, 1000); + let snap = dedup.telemetry_snapshot(); + assert_eq!(snap.applies_total, 2); + assert_eq!(snap.applies_deduped, 0); + assert_eq!(snap.applies_not_cached, 0); + assert_eq!(snap.map_size, 2); + assert_eq!(snap.map_capacity, 1000); + + // Same flags again — all deduped + dedup.filter_duplicates(&flags, 1001); + let snap = dedup.telemetry_snapshot(); + assert_eq!(snap.applies_total, 4); + assert_eq!(snap.applies_deduped, 2); + } + + #[test] + fn telemetry_not_cached_when_full() { + let mut dedup = ApplyDedup::new(120, 2); + + dedup.filter_duplicates(&[make_flag_to_apply("flags/a", "u1", "on")], 1000); + dedup.filter_duplicates(&[make_flag_to_apply("flags/b", "u1", "on")], 1000); + // Map is full — new entry passes through but is not cached + dedup.filter_duplicates(&[make_flag_to_apply("flags/c", "u1", "on")], 1000); + + let snap = dedup.telemetry_snapshot(); + assert_eq!(snap.applies_total, 3); + assert_eq!(snap.applies_not_cached, 1); + assert_eq!(snap.map_size, 2); + } + + #[test] + fn telemetry_sweep_counter() { + let mut dedup = ApplyDedup::new(10, 1000); + dedup.filter_duplicates(&[make_flag_to_apply("flags/a", "u1", "on")], 100); + + dedup.sweep(105); // runs + dedup.sweep(112); // throttled + dedup.sweep(115); // runs + + let snap = dedup.telemetry_snapshot(); + assert_eq!(snap.sweeps, 2); + } + + #[test] + fn telemetry_proto_delta() { + let mut dedup = ApplyDedup::new(120, 1000); + let flags = vec![make_flag_to_apply("flags/a", "user1", "on")]; + + dedup.filter_duplicates(&flags, 1000); + let snap1 = dedup.telemetry_snapshot(); + + dedup.filter_duplicates(&flags, 1001); // duplicate + dedup.filter_duplicates(&[make_flag_to_apply("flags/b", "u1", "on")], 1001); + let snap2 = dedup.telemetry_snapshot(); + + let delta = snap2.to_proto_delta(&snap1); + assert_eq!(delta.applies_total, 2); // 1 dup + 1 new + assert_eq!(delta.applies_deduped, 1); + assert_eq!(delta.map_size, 2); + assert_eq!(delta.map_capacity, 1000); + } } diff --git a/confidence-resolver/src/telemetry.rs b/confidence-resolver/src/telemetry.rs index bfd18de55..97704bb8e 100644 --- a/confidence-resolver/src/telemetry.rs +++ b/confidence-resolver/src/telemetry.rs @@ -6,6 +6,8 @@ use arc_swap::ArcSwap; use crate::ResolveReason; +use crate::apply_dedup::ApplyDedupSnapshot; + mod pb { pub use crate::proto::confidence::flags::resolver::v1::telemetry_data::{ BucketSpan, ResolveLatency, ResolveRate, StateAge, @@ -111,6 +113,9 @@ pub struct TelemetrySnapshot { pub latency: HistogramSnapshot, pub resolve_rates: Vec, pub memory_bytes: u64, + pub apply_dedup: Option, + pub flush_succeeded: u64, + pub flush_failed: u64, } #[derive(Clone, Default)] @@ -188,6 +193,25 @@ impl TelemetrySnapshot { if td.memory_bytes > 0 { self.memory_bytes = td.memory_bytes; } + + if let Some(dedup) = &td.apply_dedup { + let ad = self + .apply_dedup + .get_or_insert_with(ApplyDedupSnapshot::default); + ad.applies_total = ad.applies_total.wrapping_add(dedup.applies_total as u64); + ad.applies_deduped = ad + .applies_deduped + .wrapping_add(dedup.applies_deduped as u64); + ad.applies_not_cached = ad + .applies_not_cached + .wrapping_add(dedup.applies_not_cached as u64); + ad.sweeps = ad.sweeps.wrapping_add(dedup.sweeps as u64); + ad.map_size = dedup.map_size; + ad.map_capacity = dedup.map_capacity; + } + + self.flush_succeeded = self.flush_succeeded.wrapping_add(td.flush_succeeded as u64); + self.flush_failed = self.flush_failed.wrapping_add(td.flush_failed as u64); } /// Format the snapshot as Prometheus exposition text. @@ -215,6 +239,8 @@ impl TelemetrySnapshot { self.write_histogram(w, resolver_id, config)?; self.write_resolve_rates(w, resolver_id, config)?; self.write_memory(w, resolver_id, config)?; + self.write_apply_dedup(w, resolver_id, config)?; + self.write_flush(w, resolver_id, config)?; if config.openmetrics { writeln!(w, "# EOF")?; } @@ -354,6 +380,157 @@ impl TelemetrySnapshot { self.memory_bytes ) } + + fn write_apply_dedup( + &self, + w: &mut dyn fmt::Write, + resolver_id: &str, + config: &PrometheusConfig, + ) -> fmt::Result { + let ad = match &self.apply_dedup { + Some(ad) if ad.has_activity() => ad, + _ => return Ok(()), + }; + let suffix = if config.openmetrics { ".0" } else { "" }; + + let type_name = if config.openmetrics { + "confidence_apply_dedup_applies" + } else { + "confidence_apply_dedup_applies_total" + }; + writeln!( + w, + "# HELP {type_name} Total flag apply events processed by dedup." + )?; + writeln!(w, "# TYPE {type_name} counter")?; + writeln!( + w, + "confidence_apply_dedup_applies_total{{resolver_id=\"{resolver_id}\"}} {}{suffix}", + ad.applies_total + )?; + + let type_name = if config.openmetrics { + "confidence_apply_dedup_deduped" + } else { + "confidence_apply_dedup_deduped_total" + }; + writeln!(w, "# HELP {type_name} Duplicate apply events filtered out.")?; + writeln!(w, "# TYPE {type_name} counter")?; + writeln!( + w, + "confidence_apply_dedup_deduped_total{{resolver_id=\"{resolver_id}\"}} {}{suffix}", + ad.applies_deduped + )?; + + let type_name = if config.openmetrics { + "confidence_apply_dedup_not_cached" + } else { + "confidence_apply_dedup_not_cached_total" + }; + writeln!( + w, + "# HELP {type_name} Apply events passed through but not cached (map full)." + )?; + writeln!(w, "# TYPE {type_name} counter")?; + writeln!( + w, + "confidence_apply_dedup_not_cached_total{{resolver_id=\"{resolver_id}\"}} {}{suffix}", + ad.applies_not_cached + )?; + + let type_name = if config.openmetrics { + "confidence_apply_dedup_sweeps" + } else { + "confidence_apply_dedup_sweeps_total" + }; + writeln!( + w, + "# HELP {type_name} Number of dedup map sweep operations." + )?; + writeln!(w, "# TYPE {type_name} counter")?; + writeln!( + w, + "confidence_apply_dedup_sweeps_total{{resolver_id=\"{resolver_id}\"}} {}{suffix}", + ad.sweeps + )?; + + writeln!( + w, + "# HELP confidence_apply_dedup_map_size Current entries in the dedup map." + )?; + writeln!(w, "# TYPE confidence_apply_dedup_map_size gauge")?; + writeln!( + w, + "confidence_apply_dedup_map_size{{resolver_id=\"{resolver_id}\"}} {}{suffix}", + ad.map_size + )?; + + writeln!( + w, + "# HELP confidence_apply_dedup_map_size Current entries in the dedup map." + )?; + writeln!(w, "# TYPE confidence_apply_dedup_map_size gauge")?; + writeln!( + w, + "confidence_apply_dedup_map_size{{resolver_id=\"{resolver_id}\"}} {}{suffix}", + ad.map_size + )?; + + writeln!( + w, + "# HELP confidence_apply_dedup_map_capacity Maximum entries allowed in the dedup map." + )?; + writeln!(w, "# TYPE confidence_apply_dedup_map_capacity gauge")?; + writeln!( + w, + "confidence_apply_dedup_map_capacity{{resolver_id=\"{resolver_id}\"}} {}{suffix}", + ad.map_capacity + ) + } + + fn write_flush( + &self, + w: &mut dyn fmt::Write, + resolver_id: &str, + config: &PrometheusConfig, + ) -> fmt::Result { + if self.flush_succeeded == 0 && self.flush_failed == 0 { + return Ok(()); + } + let suffix = if config.openmetrics { ".0" } else { "" }; + + let type_name = if config.openmetrics { + "confidence_flush_succeeded" + } else { + "confidence_flush_succeeded_total" + }; + writeln!( + w, + "# HELP {type_name} Successful WriteFlagLogs batch deliveries." + )?; + writeln!(w, "# TYPE {type_name} counter")?; + writeln!( + w, + "confidence_flush_succeeded_total{{resolver_id=\"{resolver_id}\"}} {}{suffix}", + self.flush_succeeded + )?; + + let type_name = if config.openmetrics { + "confidence_flush_failed" + } else { + "confidence_flush_failed_total" + }; + writeln!( + w, + "# HELP {type_name} Failed WriteFlagLogs batch deliveries." + )?; + writeln!(w, "# TYPE {type_name} counter")?; + writeln!( + w, + "confidence_flush_failed_total{{resolver_id=\"{resolver_id}\"}} {}{suffix}", + self.flush_failed + ) + } } /// Concurrent telemetry collector. @@ -420,6 +597,9 @@ impl Telemetry { .map(|c| c.load(Ordering::Relaxed)) .collect(), memory_bytes: (self.memory_provider)(), + apply_dedup: None, + flush_succeeded: 0, + flush_failed: 0, } } @@ -499,6 +679,9 @@ impl Telemetry { memory_bytes: (self.memory_provider)(), resolver_version: crate::version::VERSION.to_string(), provider_init_rate: Vec::new(), + apply_dedup: None, + flush_succeeded: 0, + flush_failed: 0, } } } @@ -1124,4 +1307,108 @@ mod tests { let total: u64 = snap.latency.buckets.iter().sum(); assert_eq!(total, 0); } + + #[test] + fn accumulate_delta_with_apply_dedup() { + use crate::proto::confidence::flags::resolver::v1::telemetry_data::ApplyDedupTelemetry; + + let mut snap = TelemetrySnapshot::default(); + let td = pb::TelemetryData { + apply_dedup: Some(ApplyDedupTelemetry { + applies_total: 10, + applies_deduped: 3, + applies_not_cached: 1, + sweeps: 2, + map_size: 50, + map_capacity: 100_000, + }), + ..Default::default() + }; + + snap.accumulate_delta(&td); + let ad = snap.apply_dedup.as_ref().unwrap(); + assert_eq!(ad.applies_total, 10); + assert_eq!(ad.applies_deduped, 3); + assert_eq!(ad.applies_not_cached, 1); + assert_eq!(ad.sweeps, 2); + assert_eq!(ad.map_size, 50); + assert_eq!(ad.map_capacity, 100_000); + + // Second accumulation adds counters, replaces gauges + snap.accumulate_delta(&td); + let ad = snap.apply_dedup.as_ref().unwrap(); + assert_eq!(ad.applies_total, 20); + assert_eq!(ad.applies_deduped, 6); + assert_eq!(ad.map_size, 50); // gauge, replaced + } + + #[test] + fn prometheus_apply_dedup_metrics() { + let mut snap = TelemetrySnapshot::default(); + snap.apply_dedup = Some(ApplyDedupSnapshot { + applies_total: 100, + applies_deduped: 40, + applies_not_cached: 5, + sweeps: 3, + map_size: 200, + map_capacity: 100_000, + }); + + let config = PrometheusConfig::default(); + let prom = snap.to_prometheus("w0", &config); + + assert!(prom.contains("# HELP confidence_apply_dedup_applies_total")); + assert!(prom.contains("# TYPE confidence_apply_dedup_applies_total counter")); + assert!(prom.contains(r#"confidence_apply_dedup_applies_total{resolver_id="w0"} 100"#)); + + assert!(prom.contains(r#"confidence_apply_dedup_deduped_total{resolver_id="w0"} 40"#)); + + assert!(prom.contains(r#"confidence_apply_dedup_not_cached_total{resolver_id="w0"} 5"#)); + + assert!(prom.contains(r#"confidence_apply_dedup_sweeps_total{resolver_id="w0"} 3"#)); + + assert!(prom.contains(r#"confidence_apply_dedup_map_size{resolver_id="w0"} 200"#)); + assert!(prom.contains("# TYPE confidence_apply_dedup_map_size gauge")); + + assert!(prom.contains(r#"confidence_apply_dedup_map_capacity{resolver_id="w0"} 100000"#)); + assert!(prom.contains("# TYPE confidence_apply_dedup_map_capacity gauge")); + } + + #[test] + fn prometheus_no_dedup_when_none() { + let snap = TelemetrySnapshot::default(); + let prom = snap.to_prometheus("w0", &PrometheusConfig::default()); + assert!(!prom.contains("apply_dedup")); + } + + #[test] + fn prometheus_flush_counters() { + let mut snap = TelemetrySnapshot::default(); + snap.flush_succeeded = 10; + snap.flush_failed = 2; + + let config = PrometheusConfig::default(); + let prom = snap.to_prometheus("w0", &config); + + assert!(prom.contains(r#"confidence_flush_succeeded_total{resolver_id="w0"} 10"#)); + assert!(prom.contains(r#"confidence_flush_failed_total{resolver_id="w0"} 2"#)); + } + + #[test] + fn accumulate_delta_flush_counters() { + let mut snap = TelemetrySnapshot::default(); + let td = pb::TelemetryData { + flush_succeeded: 5, + flush_failed: 1, + ..Default::default() + }; + + snap.accumulate_delta(&td); + assert_eq!(snap.flush_succeeded, 5); + assert_eq!(snap.flush_failed, 1); + + snap.accumulate_delta(&td); + assert_eq!(snap.flush_succeeded, 10); + assert_eq!(snap.flush_failed, 2); + } } diff --git a/openfeature-provider/go/confidence/internal/flag_logger/grpc.go b/openfeature-provider/go/confidence/internal/flag_logger/grpc.go index b2949a148..eb9ebe82b 100644 --- a/openfeature-provider/go/confidence/internal/flag_logger/grpc.go +++ b/openfeature-provider/go/confidence/internal/flag_logger/grpc.go @@ -13,12 +13,14 @@ import ( ) type GrpcFlagLogger struct { - stub resolverv1.InternalFlagLoggerServiceClient - clientSecret string - logger *slog.Logger - wg sync.WaitGroup - attempts atomic.Int64 - failures atomic.Int64 + stub resolverv1.InternalFlagLoggerServiceClient + clientSecret string + logger *slog.Logger + wg sync.WaitGroup + attempts atomic.Int64 + failures atomic.Int64 + flushSucceeded atomic.Int64 + flushFailed atomic.Int64 } func NewGrpcWasmFlagLogger(stub resolverv1.InternalFlagLoggerServiceClient, clientSecret string, logger *slog.Logger) *GrpcFlagLogger { @@ -57,6 +59,16 @@ func (g *GrpcFlagLogger) Write(request *resolverv1.WriteFlagLogsRequest) { "client_resolve_info", clientResolveCount, "flag_resolve_info", flagResolveCount) + succeeded := uint32(g.flushSucceeded.Swap(0)) + failed := uint32(g.flushFailed.Swap(0)) + if succeeded > 0 || failed > 0 { + if request.TelemetryData == nil { + request.TelemetryData = &resolverv1.TelemetryData{} + } + request.TelemetryData.FlushSucceeded = succeeded + request.TelemetryData.FlushFailed = failed + } + g.sendAsync(request) } @@ -75,7 +87,9 @@ func (g *GrpcFlagLogger) sendAsync(request *resolverv1.WriteFlagLogsRequest) { if _, err := g.stub.ClientWriteFlagLogs(rpcCtx, request); err != nil { g.failures.Add(1) + g.flushFailed.Add(1) } else { + g.flushSucceeded.Add(1) g.logger.Debug("Successfully sent flag log", "flag_assigned", len(request.FlagAssigned), "client_resolve_info", len(request.ClientResolveInfo), diff --git a/openfeature-provider/go/confidence/internal/flag_logger/multi.go b/openfeature-provider/go/confidence/internal/flag_logger/multi.go index 27afb18ca..a8cb971d5 100644 --- a/openfeature-provider/go/confidence/internal/flag_logger/multi.go +++ b/openfeature-provider/go/confidence/internal/flag_logger/multi.go @@ -20,12 +20,14 @@ type logSender func(ctx context.Context, request *resolverv1.WriteFlagLogsReques // CDN state. The first destination is primary; the second is fallback on error. // If no destinations are configured, it defaults to Spotify Edge (gRPC). type MultiDestinationFlagLogger struct { - senders map[admin.LogDestination]logSender - destinations func() []admin.LogDestination - logger *slog.Logger - wg sync.WaitGroup - attempts atomic.Int64 - failures atomic.Int64 + senders map[admin.LogDestination]logSender + destinations func() []admin.LogDestination + logger *slog.Logger + wg sync.WaitGroup + attempts atomic.Int64 + failures atomic.Int64 + flushSucceeded atomic.Int64 + flushFailed atomic.Int64 } // NewMultiDestinationFlagLogger creates a flag logger that routes to multiple @@ -83,6 +85,16 @@ func (m *MultiDestinationFlagLogger) Write(request *resolverv1.WriteFlagLogsRequ "client_resolve_info", clientResolveCount, "flag_resolve_info", flagResolveCount) + succeeded := uint32(m.flushSucceeded.Swap(0)) + failed := uint32(m.flushFailed.Swap(0)) + if succeeded > 0 || failed > 0 { + if request.TelemetryData == nil { + request.TelemetryData = &resolverv1.TelemetryData{} + } + request.TelemetryData.FlushSucceeded = succeeded + request.TelemetryData.FlushFailed = failed + } + m.wg.Add(1) go func() { defer m.wg.Done() @@ -122,6 +134,9 @@ func (m *MultiDestinationFlagLogger) Write(request *resolverv1.WriteFlagLogsRequ if lastErr != nil { m.failures.Add(1) + m.flushFailed.Add(1) + } else { + m.flushSucceeded.Add(1) } if m.attempts.Add(1)%10 == 0 { diff --git a/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go b/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go index 0050357cb..53f5d9a04 100644 --- a/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go +++ b/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go @@ -248,8 +248,12 @@ type TelemetryData struct { // This must be preserved when providers decode and re-encode telemetry. ResolverVersion string `protobuf:"bytes,8,opt,name=resolver_version,json=resolverVersion,proto3" json:"resolver_version,omitempty"` ProviderInitRate []*TelemetryData_ProviderInitRate `protobuf:"bytes,9,rep,name=provider_init_rate,json=providerInitRate,proto3" json:"provider_init_rate,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // Delta counters: WriteFlagLogs batch delivery outcomes since last flush. + // Populated by the host SDK after each delivery attempt. + FlushSucceeded uint32 `protobuf:"varint,11,opt,name=flush_succeeded,json=flushSucceeded,proto3" json:"flush_succeeded,omitempty"` + FlushFailed uint32 `protobuf:"varint,12,opt,name=flush_failed,json=flushFailed,proto3" json:"flush_failed,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *TelemetryData) Reset() { @@ -303,6 +307,20 @@ func (x *TelemetryData) GetProviderInitRate() []*TelemetryData_ProviderInitRate return nil } +func (x *TelemetryData) GetFlushSucceeded() uint32 { + if x != nil { + return x.FlushSucceeded + } + return 0 +} + +func (x *TelemetryData) GetFlushFailed() uint32 { + if x != nil { + return x.FlushFailed + } + return 0 +} + type ClientInfo struct { state protoimpl.MessageState `protogen:"open.v1"` Client string `protobuf:"bytes,1,opt,name=client,proto3" json:"client,omitempty"` @@ -1582,11 +1600,13 @@ const file_confidence_flags_resolver_v1_internal_api_proto_rawDesc = "" + "\x15IngestFlagLogsRequest\x12\x1d\n" + "\n" + "account_id\x18\x01 \x01(\tR\taccountId\x12H\n" + - "\x05batch\x18\x02 \x01(\v22.confidence.flags.resolver.v1.WriteFlagLogsRequestR\x05batch\"\xa9\x03\n" + + "\x05batch\x18\x02 \x01(\v22.confidence.flags.resolver.v1.WriteFlagLogsRequestR\x05batch\"\xf5\x03\n" + "\rTelemetryData\x123\n" + "\x03sdk\x18\x02 \x01(\v2!.confidence.flags.resolver.v1.SdkR\x03sdk\x12)\n" + "\x10resolver_version\x18\b \x01(\tR\x0fresolverVersion\x12j\n" + - "\x12provider_init_rate\x18\t \x03(\v2<.confidence.flags.resolver.v1.TelemetryData.ProviderInitRateR\x10providerInitRate\x1a\xcb\x01\n" + + "\x12provider_init_rate\x18\t \x03(\v2<.confidence.flags.resolver.v1.TelemetryData.ProviderInitRateR\x10providerInitRate\x12'\n" + + "\x0fflush_succeeded\x18\v \x01(\rR\x0eflushSucceeded\x12!\n" + + "\fflush_failed\x18\f \x01(\rR\vflushFailed\x1a\xcb\x01\n" + "\x10ProviderInitRate\x12\x14\n" + "\x05count\x18\x01 \x01(\rR\x05count\x12`\n" + "\x06labels\x18\x03 \x03(\v2H.confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntryR\x06labels\x1a9\n" + diff --git a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java index ad7f7e342..29745094c 100644 --- a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java +++ b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java @@ -38,6 +38,7 @@ public class GrpcWasmFlagLogger implements WasmFlagLogger { private final Duration shutdownTimeout; private final AtomicLong attempts = new AtomicLong(); private final AtomicLong failures = new AtomicLong(); + private final AtomicLong successes = new AtomicLong(); private final String clientSecret; private final HttpClientFactory httpClientFactory; private final AtomicReference> logDestinations = @@ -127,13 +128,19 @@ private void sendWithFailover(WriteFlagLogsRequest request) { // Default to Edge when no destinations configured if (destinations.isEmpty()) { - sendToEdge(request); + try { + sendToEdge(request); + successes.incrementAndGet(); + } catch (Exception e) { + failures.incrementAndGet(); + } return; } final LogDestination primary = destinations.get(0); try { sendToDestination(primary, request); + successes.incrementAndGet(); logger.debug( "Successfully sent flag log via {} with {} assigned, {} client_resolve_info, {} flag_resolve_info", primary, @@ -146,6 +153,7 @@ private void sendWithFailover(WriteFlagLogsRequest request) { logger.warn("Primary destination {} failed, trying fallback {}", primary, fallback); try { sendToDestination(fallback, request); + successes.incrementAndGet(); logger.debug( "Successfully sent flag log via fallback {} with {} assigned, {} client_resolve_info, {} flag_resolve_info", fallback, @@ -207,6 +215,11 @@ private void sendToCloudflare(WriteFlagLogsRequest request) { } } + @Override + public long[] drainFlushCounters() { + return new long[] {successes.getAndSet(0), failures.getAndSet(0)}; + } + /** * Shutdown the executor service and wait for pending async writes to complete. This method will * block for up to the configured shutdown timeout (default 10 seconds) waiting for pending log diff --git a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java index 4b80c0929..732b5a77d 100644 --- a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java +++ b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java @@ -208,6 +208,7 @@ public OpenFeatureLocalResolveProvider( final LocalResolver telemetryResolver = new ProviderTelemetryResolver( flagLogger::write, + wasmFlagLogger::drainFlushCounters, SDK, initLabels, providerLogSink -> @@ -282,6 +283,7 @@ public OpenFeatureLocalResolveProvider( final LocalResolver telemetryResolver = new ProviderTelemetryResolver( wasmFlagLogger::write, + wasmFlagLogger::drainFlushCounters, SDK, Map.of(), providerLogSink -> diff --git a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java index cf9dbc80d..75504a1ae 100644 --- a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java +++ b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java @@ -11,10 +11,12 @@ import java.util.concurrent.CompletionStage; import java.util.function.Consumer; import java.util.function.Function; +import java.util.function.Supplier; /** Owns provider-scoped telemetry above the resolver pool and recovery layers. */ final class ProviderTelemetryResolver implements LocalResolver { private final Consumer logSink; + private final Supplier flushCounterDrain; private final Sdk sdk; private final Map labels; private final LocalResolver delegate; @@ -25,18 +27,43 @@ final class ProviderTelemetryResolver implements LocalResolver { Sdk sdk, Map labels, Function, LocalResolver> innerFactory) { + this(logSink, () -> new long[] {0, 0}, sdk, labels, innerFactory); + } + + ProviderTelemetryResolver( + Consumer logSink, + Supplier flushCounterDrain, + Sdk sdk, + Map labels, + Function, LocalResolver> innerFactory) { this.logSink = logSink; + this.flushCounterDrain = flushCounterDrain; this.sdk = sdk; this.labels = Map.copyOf(labels); this.delegate = innerFactory.apply(this::writeLogs); } private synchronized void writeLogs(WriteFlagLogsRequest request) { - final WriteFlagLogsRequest outgoing = initSent ? request : addInitTelemetry(request); + WriteFlagLogsRequest outgoing = initSent ? request : addInitTelemetry(request); + outgoing = addFlushCounters(outgoing); logSink.accept(outgoing); initSent = true; } + private WriteFlagLogsRequest addFlushCounters(WriteFlagLogsRequest request) { + final long[] counters = flushCounterDrain.get(); + if (counters[0] == 0 && counters[1] == 0) { + return request; + } + return request.toBuilder() + .setTelemetryData( + request.getTelemetryData().toBuilder() + .setFlushSucceeded((int) counters[0]) + .setFlushFailed((int) counters[1]) + .build()) + .build(); + } + private synchronized void emitInitIfPending() { if (initSent) { return; diff --git a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/WasmFlagLogger.java b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/WasmFlagLogger.java index 14c5960cc..b1dc50eab 100644 --- a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/WasmFlagLogger.java +++ b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/WasmFlagLogger.java @@ -18,4 +18,12 @@ interface WasmFlagLogger { default void updateLogRouting(List destinations, String accountId) { // no-op by default for test implementations } + + /** + * Atomically reads and resets the flush delivery counters. Returns [succeeded, failed]. Called by + * the telemetry layer to merge delivery stats into the next TelemetryData. + */ + default long[] drainFlushCounters() { + return new long[] {0, 0}; + } } diff --git a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts index beff1f68a..fb60f74ec 100644 --- a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts +++ b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts @@ -93,6 +93,8 @@ export class ConfidenceServerProviderLocal implements Provider { private readonly materializationStore: MaterializationStore | null; private readonly initLabels: Record; private initTelemetryState: 'pending' | 'sending' | 'sent' = 'pending'; + private flushSucceeded = 0; + private flushFailed = 0; private resolverInstance: LocalResolver | null = null; private eventTracker: EventTracker | null = null; private stateEtag: string | null = null; @@ -512,12 +514,15 @@ export class ConfidenceServerProviderLocal implements Provider { this.initTelemetryState = 'sending'; writeFlagLogRequest = this.addProviderInitTelemetry(writeFlagLogRequest); } + writeFlagLogRequest = this.addFlushDeliveryTelemetry(writeFlagLogRequest); try { await this.sendFlagLogs(writeFlagLogRequest, signal); + this.flushSucceeded++; if (includeInit) { this.initTelemetryState = 'sent'; } } catch (error) { + this.flushFailed++; if (includeInit) { this.initTelemetryState = 'pending'; } @@ -559,6 +564,21 @@ export class ConfidenceServerProviderLocal implements Provider { } } + private addFlushDeliveryTelemetry(encodedWriteFlagLogRequest: Uint8Array): Uint8Array { + if (this.flushSucceeded === 0 && this.flushFailed === 0) { + return encodedWriteFlagLogRequest; + } + const request = WriteFlagLogsRequest.decode(encodedWriteFlagLogRequest); + if (!request.telemetryData) { + request.telemetryData = { resolverVersion: '', providerInitRate: [], flushSucceeded: 0, flushFailed: 0 }; + } + request.telemetryData.flushSucceeded = this.flushSucceeded; + request.telemetryData.flushFailed = this.flushFailed; + this.flushSucceeded = 0; + this.flushFailed = 0; + return WriteFlagLogsRequest.encode(request).finish(); + } + private addProviderInitTelemetry(encodedWriteFlagLogRequest: Uint8Array): Uint8Array { const request = WriteFlagLogsRequest.decode(encodedWriteFlagLogRequest); if (!request.telemetryData) { diff --git a/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto b/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto index 8ba7bc835..b2cbef758 100644 --- a/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto +++ b/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto @@ -57,6 +57,13 @@ message TelemetryData { repeated ProviderInitRate provider_init_rate = 9; + // apply_dedup = 10; — set by WASM guest, passes through as unknown fields + + // Delta counters: WriteFlagLogs batch delivery outcomes since last flush. + // Populated by the host SDK after each delivery attempt. + uint32 flush_succeeded = 11; + uint32 flush_failed = 12; + message ProviderInitRate { uint32 count = 1; reserved 2; // status — tbd diff --git a/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2.py b/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2.py index a835c476f..3b0740e89 100644 --- a/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2.py +++ b/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2.py @@ -23,10 +23,10 @@ from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 -from . import types_pb2 as confidence_dot_flags_dot_resolver_dot_v1_dot_types__pb2 +from confidence.flags.resolver.v1 import types_pb2 as confidence_dot_flags_dot_resolver_dot_v1_dot_types__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n/confidence/flags/resolver/v1/internal_api.proto\x12\x1c\x63onfidence.flags.resolver.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a(confidence/flags/resolver/v1/types.proto\"\xb6\x02\n\x14WriteFlagLogsRequest\x12\x41\n\rflag_assigned\x18\x01 \x03(\x0b\x32*.confidence.flags.resolver.v1.FlagAssigned\x12\x43\n\x0etelemetry_data\x18\x02 \x01(\x0b\x32+.confidence.flags.resolver.v1.TelemetryData\x12L\n\x13\x63lient_resolve_info\x18\x03 \x03(\x0b\x32/.confidence.flags.resolver.v1.ClientResolveInfo\x12H\n\x11\x66lag_resolve_info\x18\x04 \x03(\x0b\x32-.confidence.flags.resolver.v1.FlagResolveInfo\"\x17\n\x15WriteFlagLogsResponse\"n\n\x15IngestFlagLogsRequest\x12\x12\n\naccount_id\x18\x01 \x01(\t\x12\x41\n\x05\x62\x61tch\x18\x02 \x01(\x0b\x32\x32.confidence.flags.resolver.v1.WriteFlagLogsRequest\"\xe6\x02\n\rTelemetryData\x12.\n\x03sdk\x18\x02 \x01(\x0b\x32!.confidence.flags.resolver.v1.Sdk\x12\x18\n\x10resolver_version\x18\x08 \x01(\t\x12X\n\x12provider_init_rate\x18\t \x03(\x0b\x32<.confidence.flags.resolver.v1.TelemetryData.ProviderInitRate\x1a\xb0\x01\n\x10ProviderInitRate\x12\r\n\x05\x63ount\x18\x01 \x01(\r\x12X\n\x06labels\x18\x03 \x03(\x0b\x32H.confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01J\x04\x08\x02\x10\x03\"g\n\nClientInfo\x12\x0e\n\x06\x63lient\x18\x01 \x01(\t\x12\x19\n\x11\x63lient_credential\x18\x02 \x01(\t\x12.\n\x03sdk\x18\x03 \x01(\x0b\x32!.confidence.flags.resolver.v1.Sdk\"\xa4\x07\n\x0c\x46lagAssigned\x12\x12\n\nresolve_id\x18\n \x01(\t\x12=\n\x0b\x63lient_info\x18\x03 \x01(\x0b\x32(.confidence.flags.resolver.v1.ClientInfo\x12\x45\n\x05\x66lags\x18\x0f \x03(\x0b\x32\x36.confidence.flags.resolver.v1.FlagAssigned.AppliedFlag\x1a\xbd\x03\n\x0b\x41ppliedFlag\x12\x0c\n\x04\x66lag\x18\x01 \x01(\t\x12\x15\n\rtargeting_key\x18\x02 \x01(\t\x12\x1e\n\x16targeting_key_selector\x18\x03 \x01(\t\x12T\n\x0f\x61ssignment_info\x18\x04 \x01(\x0b\x32\x39.confidence.flags.resolver.v1.FlagAssigned.AssignmentInfoH\x00\x12Z\n\x12\x64\x65\x66\x61ult_assignment\x18\x05 \x01(\x0b\x32<.confidence.flags.resolver.v1.FlagAssigned.DefaultAssignmentH\x00\x12\x15\n\rassignment_id\x18\x06 \x01(\t\x12\x0c\n\x04rule\x18\x07 \x01(\t\x12T\n\x17\x66\x61llthrough_assignments\x18\x08 \x03(\x0b\x32\x33.confidence.flags.resolver.v1.FallthroughAssignment\x12.\n\napply_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x0c\n\nassignment\x1a\x32\n\x0e\x41ssignmentInfo\x12\x0f\n\x07segment\x18\x01 \x01(\t\x12\x0f\n\x07variant\x18\x02 \x01(\t\x1a\x85\x02\n\x11\x44\x65\x66\x61ultAssignment\x12\x64\n\x06reason\x18\x01 \x01(\x0e\x32T.confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.DefaultAssignmentReason\"\x89\x01\n\x17\x44\x65\x66\x61ultAssignmentReason\x12)\n%DEFAULT_ASSIGNMENT_REASON_UNSPECIFIED\x10\x00\x12\x14\n\x10NO_SEGMENT_MATCH\x10\x01\x12\x1a\n\x12NO_TREATMENT_MATCH\x10\x02\x1a\x02\x08\x01\x12\x11\n\rFLAG_ARCHIVED\x10\x03\"s\n\x15\x46\x61llthroughAssignment\x12\x0c\n\x04rule\x18\x01 \x01(\t\x12\x15\n\rassignment_id\x18\x02 \x01(\t\x12\x15\n\rtargeting_key\x18\x03 \x01(\t\x12\x1e\n\x16targeting_key_selector\x18\x04 \x01(\t\"\xdf\x02\n\x11\x43lientResolveInfo\x12\x0e\n\x06\x63lient\x18\x01 \x01(\t\x12\x19\n\x11\x63lient_credential\x18\x02 \x01(\t\x12_\n\x06schema\x18\x03 \x03(\x0b\x32O.confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance\x1a\xbd\x01\n\x1f\x45valuationContextSchemaInstance\x12k\n\x06schema\x18\x01 \x03(\x0b\x32[.confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry\x1a-\n\x0bSchemaEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"\xb5\x01\n\x0f\x46lagResolveInfo\x12\x0c\n\x04\x66lag\x18\x01 \x01(\t\x12^\n\x14variant_resolve_info\x18\x02 \x03(\x0b\x32@.confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo\x1a\x34\n\x12VariantResolveInfo\x12\x0f\n\x07variant\x18\x01 \x01(\t\x12\r\n\x05\x63ount\x18\x03 \x01(\x03\"]\n\x16WriteOperationsRequest\x12\x43\n\x10store_variant_op\x18\x01 \x03(\x0b\x32).confidence.flags.resolver.v1.VariantData\"\x17\n\x15WriteOperationsResult\"D\n\rVariantReadOp\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x0c\n\x04rule\x18\x03 \x01(\t\"8\n\x0fInclusionReadOp\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\"\xa2\x01\n\x06ReadOp\x12\x46\n\x0fvariant_read_op\x18\x01 \x01(\x0b\x32+.confidence.flags.resolver.v1.VariantReadOpH\x00\x12J\n\x11inclusion_read_op\x18\x02 \x01(\x0b\x32-.confidence.flags.resolver.v1.InclusionReadOpH\x00\x42\x04\n\x02op\"J\n\x15ReadOperationsRequest\x12\x31\n\x03ops\x18\x03 \x03(\x0b\x32$.confidence.flags.resolver.v1.ReadOp\"S\n\x0bVariantData\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x0c\n\x04rule\x18\x03 \x01(\t\x12\x0f\n\x07variant\x18\x04 \x01(\t\"K\n\rInclusionData\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x13\n\x0bis_included\x18\x03 \x01(\x08\"\xa4\x01\n\nReadResult\x12\x43\n\x0evariant_result\x18\x01 \x01(\x0b\x32).confidence.flags.resolver.v1.VariantDataH\x00\x12G\n\x10inclusion_result\x18\x02 \x01(\x0b\x32+.confidence.flags.resolver.v1.InclusionDataH\x00\x42\x08\n\x06result\"Q\n\x14ReadOperationsResult\x12\x39\n\x07results\x18\x01 \x03(\x0b\x32(.confidence.flags.resolver.v1.ReadResult2\xb2\x03\n\x19InternalFlagLoggerService\x12~\n\x13\x43lientWriteFlagLogs\x12\x32.confidence.flags.resolver.v1.WriteFlagLogsRequest\x1a\x33.confidence.flags.resolver.v1.WriteFlagLogsResponse\x12\x8a\x01\n\x1bWriteMaterializedOperations\x12\x34.confidence.flags.resolver.v1.WriteOperationsRequest\x1a\x33.confidence.flags.resolver.v1.WriteOperationsResult\"\x00\x12\x87\x01\n\x1aReadMaterializedOperations\x12\x33.confidence.flags.resolver.v1.ReadOperationsRequest\x1a\x32.confidence.flags.resolver.v1.ReadOperationsResult\"\x00\x42\xad\x01\n,com.spotify.confidence.sdk.flags.resolver.v1B\x10InternalApiProtoP\x01Zigithub.com/spotify/confidence-resolver/openfeature-provider/go/confidence/internal/proto/resolverinternalb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n/confidence/flags/resolver/v1/internal_api.proto\x12\x1c\x63onfidence.flags.resolver.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a(confidence/flags/resolver/v1/types.proto\"\xb6\x02\n\x14WriteFlagLogsRequest\x12\x41\n\rflag_assigned\x18\x01 \x03(\x0b\x32*.confidence.flags.resolver.v1.FlagAssigned\x12\x43\n\x0etelemetry_data\x18\x02 \x01(\x0b\x32+.confidence.flags.resolver.v1.TelemetryData\x12L\n\x13\x63lient_resolve_info\x18\x03 \x03(\x0b\x32/.confidence.flags.resolver.v1.ClientResolveInfo\x12H\n\x11\x66lag_resolve_info\x18\x04 \x03(\x0b\x32-.confidence.flags.resolver.v1.FlagResolveInfo\"\x17\n\x15WriteFlagLogsResponse\"n\n\x15IngestFlagLogsRequest\x12\x12\n\naccount_id\x18\x01 \x01(\t\x12\x41\n\x05\x62\x61tch\x18\x02 \x01(\x0b\x32\x32.confidence.flags.resolver.v1.WriteFlagLogsRequest\"\x95\x03\n\rTelemetryData\x12.\n\x03sdk\x18\x02 \x01(\x0b\x32!.confidence.flags.resolver.v1.Sdk\x12\x18\n\x10resolver_version\x18\x08 \x01(\t\x12X\n\x12provider_init_rate\x18\t \x03(\x0b\x32<.confidence.flags.resolver.v1.TelemetryData.ProviderInitRate\x12\x17\n\x0f\x66lush_succeeded\x18\x0b \x01(\r\x12\x14\n\x0c\x66lush_failed\x18\x0c \x01(\r\x1a\xb0\x01\n\x10ProviderInitRate\x12\r\n\x05\x63ount\x18\x01 \x01(\r\x12X\n\x06labels\x18\x03 \x03(\x0b\x32H.confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01J\x04\x08\x02\x10\x03\"g\n\nClientInfo\x12\x0e\n\x06\x63lient\x18\x01 \x01(\t\x12\x19\n\x11\x63lient_credential\x18\x02 \x01(\t\x12.\n\x03sdk\x18\x03 \x01(\x0b\x32!.confidence.flags.resolver.v1.Sdk\"\xa4\x07\n\x0c\x46lagAssigned\x12\x12\n\nresolve_id\x18\n \x01(\t\x12=\n\x0b\x63lient_info\x18\x03 \x01(\x0b\x32(.confidence.flags.resolver.v1.ClientInfo\x12\x45\n\x05\x66lags\x18\x0f \x03(\x0b\x32\x36.confidence.flags.resolver.v1.FlagAssigned.AppliedFlag\x1a\xbd\x03\n\x0b\x41ppliedFlag\x12\x0c\n\x04\x66lag\x18\x01 \x01(\t\x12\x15\n\rtargeting_key\x18\x02 \x01(\t\x12\x1e\n\x16targeting_key_selector\x18\x03 \x01(\t\x12T\n\x0f\x61ssignment_info\x18\x04 \x01(\x0b\x32\x39.confidence.flags.resolver.v1.FlagAssigned.AssignmentInfoH\x00\x12Z\n\x12\x64\x65\x66\x61ult_assignment\x18\x05 \x01(\x0b\x32<.confidence.flags.resolver.v1.FlagAssigned.DefaultAssignmentH\x00\x12\x15\n\rassignment_id\x18\x06 \x01(\t\x12\x0c\n\x04rule\x18\x07 \x01(\t\x12T\n\x17\x66\x61llthrough_assignments\x18\x08 \x03(\x0b\x32\x33.confidence.flags.resolver.v1.FallthroughAssignment\x12.\n\napply_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x0c\n\nassignment\x1a\x32\n\x0e\x41ssignmentInfo\x12\x0f\n\x07segment\x18\x01 \x01(\t\x12\x0f\n\x07variant\x18\x02 \x01(\t\x1a\x85\x02\n\x11\x44\x65\x66\x61ultAssignment\x12\x64\n\x06reason\x18\x01 \x01(\x0e\x32T.confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.DefaultAssignmentReason\"\x89\x01\n\x17\x44\x65\x66\x61ultAssignmentReason\x12)\n%DEFAULT_ASSIGNMENT_REASON_UNSPECIFIED\x10\x00\x12\x14\n\x10NO_SEGMENT_MATCH\x10\x01\x12\x1a\n\x12NO_TREATMENT_MATCH\x10\x02\x1a\x02\x08\x01\x12\x11\n\rFLAG_ARCHIVED\x10\x03\"s\n\x15\x46\x61llthroughAssignment\x12\x0c\n\x04rule\x18\x01 \x01(\t\x12\x15\n\rassignment_id\x18\x02 \x01(\t\x12\x15\n\rtargeting_key\x18\x03 \x01(\t\x12\x1e\n\x16targeting_key_selector\x18\x04 \x01(\t\"\xdf\x02\n\x11\x43lientResolveInfo\x12\x0e\n\x06\x63lient\x18\x01 \x01(\t\x12\x19\n\x11\x63lient_credential\x18\x02 \x01(\t\x12_\n\x06schema\x18\x03 \x03(\x0b\x32O.confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance\x1a\xbd\x01\n\x1f\x45valuationContextSchemaInstance\x12k\n\x06schema\x18\x01 \x03(\x0b\x32[.confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry\x1a-\n\x0bSchemaEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"\xb5\x01\n\x0f\x46lagResolveInfo\x12\x0c\n\x04\x66lag\x18\x01 \x01(\t\x12^\n\x14variant_resolve_info\x18\x02 \x03(\x0b\x32@.confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo\x1a\x34\n\x12VariantResolveInfo\x12\x0f\n\x07variant\x18\x01 \x01(\t\x12\r\n\x05\x63ount\x18\x03 \x01(\x03\"]\n\x16WriteOperationsRequest\x12\x43\n\x10store_variant_op\x18\x01 \x03(\x0b\x32).confidence.flags.resolver.v1.VariantData\"\x17\n\x15WriteOperationsResult\"D\n\rVariantReadOp\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x0c\n\x04rule\x18\x03 \x01(\t\"8\n\x0fInclusionReadOp\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\"\xa2\x01\n\x06ReadOp\x12\x46\n\x0fvariant_read_op\x18\x01 \x01(\x0b\x32+.confidence.flags.resolver.v1.VariantReadOpH\x00\x12J\n\x11inclusion_read_op\x18\x02 \x01(\x0b\x32-.confidence.flags.resolver.v1.InclusionReadOpH\x00\x42\x04\n\x02op\"J\n\x15ReadOperationsRequest\x12\x31\n\x03ops\x18\x03 \x03(\x0b\x32$.confidence.flags.resolver.v1.ReadOp\"S\n\x0bVariantData\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x0c\n\x04rule\x18\x03 \x01(\t\x12\x0f\n\x07variant\x18\x04 \x01(\t\"K\n\rInclusionData\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x13\n\x0bis_included\x18\x03 \x01(\x08\"\xa4\x01\n\nReadResult\x12\x43\n\x0evariant_result\x18\x01 \x01(\x0b\x32).confidence.flags.resolver.v1.VariantDataH\x00\x12G\n\x10inclusion_result\x18\x02 \x01(\x0b\x32+.confidence.flags.resolver.v1.InclusionDataH\x00\x42\x08\n\x06result\"Q\n\x14ReadOperationsResult\x12\x39\n\x07results\x18\x01 \x03(\x0b\x32(.confidence.flags.resolver.v1.ReadResult2\xb2\x03\n\x19InternalFlagLoggerService\x12~\n\x13\x43lientWriteFlagLogs\x12\x32.confidence.flags.resolver.v1.WriteFlagLogsRequest\x1a\x33.confidence.flags.resolver.v1.WriteFlagLogsResponse\x12\x8a\x01\n\x1bWriteMaterializedOperations\x12\x34.confidence.flags.resolver.v1.WriteOperationsRequest\x1a\x33.confidence.flags.resolver.v1.WriteOperationsResult\"\x00\x12\x87\x01\n\x1aReadMaterializedOperations\x12\x33.confidence.flags.resolver.v1.ReadOperationsRequest\x1a\x32.confidence.flags.resolver.v1.ReadOperationsResult\"\x00\x42\xad\x01\n,com.spotify.confidence.sdk.flags.resolver.v1B\x10InternalApiProtoP\x01Zigithub.com/spotify/confidence-resolver/openfeature-provider/go/confidence/internal/proto/resolverinternalb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -47,55 +47,55 @@ _globals['_INGESTFLAGLOGSREQUEST']._serialized_start=494 _globals['_INGESTFLAGLOGSREQUEST']._serialized_end=604 _globals['_TELEMETRYDATA']._serialized_start=607 - _globals['_TELEMETRYDATA']._serialized_end=965 - _globals['_TELEMETRYDATA_PROVIDERINITRATE']._serialized_start=789 - _globals['_TELEMETRYDATA_PROVIDERINITRATE']._serialized_end=965 - _globals['_TELEMETRYDATA_PROVIDERINITRATE_LABELSENTRY']._serialized_start=914 - _globals['_TELEMETRYDATA_PROVIDERINITRATE_LABELSENTRY']._serialized_end=959 - _globals['_CLIENTINFO']._serialized_start=967 - _globals['_CLIENTINFO']._serialized_end=1070 - _globals['_FLAGASSIGNED']._serialized_start=1073 - _globals['_FLAGASSIGNED']._serialized_end=2005 - _globals['_FLAGASSIGNED_APPLIEDFLAG']._serialized_start=1244 - _globals['_FLAGASSIGNED_APPLIEDFLAG']._serialized_end=1689 - _globals['_FLAGASSIGNED_ASSIGNMENTINFO']._serialized_start=1691 - _globals['_FLAGASSIGNED_ASSIGNMENTINFO']._serialized_end=1741 - _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT']._serialized_start=1744 - _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT']._serialized_end=2005 - _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT_DEFAULTASSIGNMENTREASON']._serialized_start=1868 - _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT_DEFAULTASSIGNMENTREASON']._serialized_end=2005 - _globals['_FALLTHROUGHASSIGNMENT']._serialized_start=2007 - _globals['_FALLTHROUGHASSIGNMENT']._serialized_end=2122 - _globals['_CLIENTRESOLVEINFO']._serialized_start=2125 - _globals['_CLIENTRESOLVEINFO']._serialized_end=2476 - _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE']._serialized_start=2287 - _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE']._serialized_end=2476 - _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE_SCHEMAENTRY']._serialized_start=2431 - _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE_SCHEMAENTRY']._serialized_end=2476 - _globals['_FLAGRESOLVEINFO']._serialized_start=2479 - _globals['_FLAGRESOLVEINFO']._serialized_end=2660 - _globals['_FLAGRESOLVEINFO_VARIANTRESOLVEINFO']._serialized_start=2608 - _globals['_FLAGRESOLVEINFO_VARIANTRESOLVEINFO']._serialized_end=2660 - _globals['_WRITEOPERATIONSREQUEST']._serialized_start=2662 - _globals['_WRITEOPERATIONSREQUEST']._serialized_end=2755 - _globals['_WRITEOPERATIONSRESULT']._serialized_start=2757 - _globals['_WRITEOPERATIONSRESULT']._serialized_end=2780 - _globals['_VARIANTREADOP']._serialized_start=2782 - _globals['_VARIANTREADOP']._serialized_end=2850 - _globals['_INCLUSIONREADOP']._serialized_start=2852 - _globals['_INCLUSIONREADOP']._serialized_end=2908 - _globals['_READOP']._serialized_start=2911 - _globals['_READOP']._serialized_end=3073 - _globals['_READOPERATIONSREQUEST']._serialized_start=3075 - _globals['_READOPERATIONSREQUEST']._serialized_end=3149 - _globals['_VARIANTDATA']._serialized_start=3151 - _globals['_VARIANTDATA']._serialized_end=3234 - _globals['_INCLUSIONDATA']._serialized_start=3236 - _globals['_INCLUSIONDATA']._serialized_end=3311 - _globals['_READRESULT']._serialized_start=3314 - _globals['_READRESULT']._serialized_end=3478 - _globals['_READOPERATIONSRESULT']._serialized_start=3480 - _globals['_READOPERATIONSRESULT']._serialized_end=3561 - _globals['_INTERNALFLAGLOGGERSERVICE']._serialized_start=3564 - _globals['_INTERNALFLAGLOGGERSERVICE']._serialized_end=3998 + _globals['_TELEMETRYDATA']._serialized_end=1012 + _globals['_TELEMETRYDATA_PROVIDERINITRATE']._serialized_start=836 + _globals['_TELEMETRYDATA_PROVIDERINITRATE']._serialized_end=1012 + _globals['_TELEMETRYDATA_PROVIDERINITRATE_LABELSENTRY']._serialized_start=961 + _globals['_TELEMETRYDATA_PROVIDERINITRATE_LABELSENTRY']._serialized_end=1006 + _globals['_CLIENTINFO']._serialized_start=1014 + _globals['_CLIENTINFO']._serialized_end=1117 + _globals['_FLAGASSIGNED']._serialized_start=1120 + _globals['_FLAGASSIGNED']._serialized_end=2052 + _globals['_FLAGASSIGNED_APPLIEDFLAG']._serialized_start=1291 + _globals['_FLAGASSIGNED_APPLIEDFLAG']._serialized_end=1736 + _globals['_FLAGASSIGNED_ASSIGNMENTINFO']._serialized_start=1738 + _globals['_FLAGASSIGNED_ASSIGNMENTINFO']._serialized_end=1788 + _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT']._serialized_start=1791 + _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT']._serialized_end=2052 + _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT_DEFAULTASSIGNMENTREASON']._serialized_start=1915 + _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT_DEFAULTASSIGNMENTREASON']._serialized_end=2052 + _globals['_FALLTHROUGHASSIGNMENT']._serialized_start=2054 + _globals['_FALLTHROUGHASSIGNMENT']._serialized_end=2169 + _globals['_CLIENTRESOLVEINFO']._serialized_start=2172 + _globals['_CLIENTRESOLVEINFO']._serialized_end=2523 + _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE']._serialized_start=2334 + _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE']._serialized_end=2523 + _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE_SCHEMAENTRY']._serialized_start=2478 + _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE_SCHEMAENTRY']._serialized_end=2523 + _globals['_FLAGRESOLVEINFO']._serialized_start=2526 + _globals['_FLAGRESOLVEINFO']._serialized_end=2707 + _globals['_FLAGRESOLVEINFO_VARIANTRESOLVEINFO']._serialized_start=2655 + _globals['_FLAGRESOLVEINFO_VARIANTRESOLVEINFO']._serialized_end=2707 + _globals['_WRITEOPERATIONSREQUEST']._serialized_start=2709 + _globals['_WRITEOPERATIONSREQUEST']._serialized_end=2802 + _globals['_WRITEOPERATIONSRESULT']._serialized_start=2804 + _globals['_WRITEOPERATIONSRESULT']._serialized_end=2827 + _globals['_VARIANTREADOP']._serialized_start=2829 + _globals['_VARIANTREADOP']._serialized_end=2897 + _globals['_INCLUSIONREADOP']._serialized_start=2899 + _globals['_INCLUSIONREADOP']._serialized_end=2955 + _globals['_READOP']._serialized_start=2958 + _globals['_READOP']._serialized_end=3120 + _globals['_READOPERATIONSREQUEST']._serialized_start=3122 + _globals['_READOPERATIONSREQUEST']._serialized_end=3196 + _globals['_VARIANTDATA']._serialized_start=3198 + _globals['_VARIANTDATA']._serialized_end=3281 + _globals['_INCLUSIONDATA']._serialized_start=3283 + _globals['_INCLUSIONDATA']._serialized_end=3358 + _globals['_READRESULT']._serialized_start=3361 + _globals['_READRESULT']._serialized_end=3525 + _globals['_READOPERATIONSRESULT']._serialized_start=3527 + _globals['_READOPERATIONSRESULT']._serialized_end=3608 + _globals['_INTERNALFLAGLOGGERSERVICE']._serialized_start=3611 + _globals['_INTERNALFLAGLOGGERSERVICE']._serialized_end=4045 # @@protoc_insertion_point(module_scope) diff --git a/openfeature-provider/python/src/confidence/provider.py b/openfeature-provider/python/src/confidence/provider.py index f9a9db6b2..b62e06ad5 100644 --- a/openfeature-provider/python/src/confidence/provider.py +++ b/openfeature-provider/python/src/confidence/provider.py @@ -284,6 +284,9 @@ def __init__( self._event_publish_attempts = 0 self._event_publish_failures = 0 + self._flush_succeeded = 0 + self._flush_failed = 0 + # State fetcher (injected or created) self._state_fetcher = state_fetcher @@ -913,28 +916,40 @@ def _write_logs(self, log_data: bytes) -> None: self._init_telemetry_state = "sending" include_init = True - if include_init: + flush_ok = self._flush_succeeded + flush_err = self._flush_failed + need_rewrite = include_init or flush_ok > 0 or flush_err > 0 + + if need_rewrite: request = internal_api_pb2.WriteFlagLogsRequest.FromString(log_data) - request.telemetry_data.sdk.CopyFrom( - types_pb2.Sdk( - id=types_pb2.SdkId.SDK_ID_PYTHON_PROVIDER, - version=__version__, + if include_init: + request.telemetry_data.sdk.CopyFrom( + types_pb2.Sdk( + id=types_pb2.SdkId.SDK_ID_PYTHON_PROVIDER, + version=__version__, + ) ) - ) - init_rate = request.telemetry_data.provider_init_rate.add() - init_rate.count = 1 - for k, v in self._init_labels.items(): - init_rate.labels[k] = v + init_rate = request.telemetry_data.provider_init_rate.add() + init_rate.count = 1 + for k, v in self._init_labels.items(): + init_rate.labels[k] = v + if flush_ok > 0 or flush_err > 0: + request.telemetry_data.flush_succeeded = flush_ok + request.telemetry_data.flush_failed = flush_err + self._flush_succeeded = 0 + self._flush_failed = 0 log_data = request.SerializeToString() try: self._flag_logger.write(log_data) except Exception: + self._flush_failed += 1 if include_init: with self._init_telemetry_lock: self._init_telemetry_state = "pending" raise else: + self._flush_succeeded += 1 if include_init: with self._init_telemetry_lock: self._init_telemetry_state = "sent" diff --git a/wasm/rust-guest/src/lib.rs b/wasm/rust-guest/src/lib.rs index 8588b5fa2..903ab1093 100644 --- a/wasm/rust-guest/src/lib.rs +++ b/wasm/rust-guest/src/lib.rs @@ -5,7 +5,7 @@ use std::sync::Mutex; use arc_swap::{ArcSwap, ArcSwapOption}; use bytes::Bytes; -use confidence_resolver::apply_dedup::ApplyDedup; +use confidence_resolver::apply_dedup::{ApplyDedup, ApplyDedupSnapshot}; use confidence_resolver::assign_logger::AssignLogger; use confidence_resolver::telemetry::{Telemetry, TelemetrySnapshot}; use prost::Message; @@ -72,6 +72,8 @@ static TELEMETRY: LazyLock = LazyLock::new(|| { }); static LAST_FLUSHED: LazyLock> = LazyLock::new(|| ArcSwap::from_pointee(TelemetrySnapshot::default())); +static LAST_DEDUP_SNAPSHOT: LazyLock> = + LazyLock::new(|| Mutex::new(ApplyDedupSnapshot::default())); struct WasmHost; @@ -153,6 +155,13 @@ fn sweep_apply_dedup() { } } +fn dedup_snapshot() -> ApplyDedupSnapshot { + match APPLY_DEDUP.lock() { + Ok(dedup) => dedup.telemetry_snapshot(), + Err(poisoned) => poisoned.into_inner().telemetry_snapshot(), + } +} + /// Safely gets an owned handle to the current resolver state. fn get_resolver_state() -> Result, String> { let guard = RESOLVER_STATE.load(); @@ -233,6 +242,17 @@ wasm_msg_guest! { if let Some(state) = RESOLVER_STATE.load().as_ref() { td.sdk = state.sdk.clone(); } + if APPLY_DEDUP_ENABLED.load(Ordering::Relaxed) { + let current = dedup_snapshot(); + let prev = match LAST_DEDUP_SNAPSHOT.lock() { + Ok(mut guard) => std::mem::replace(&mut *guard, current.clone()), + Err(poisoned) => std::mem::replace(&mut *poisoned.into_inner(), current.clone()), + }; + let delta = current.to_proto_delta(&prev); + if delta.applies_total > 0 || current.map_size > 0 { + td.apply_dedup = Some(delta); + } + } req.telemetry_data = Some(td); ASSIGN_LOGGER.checkpoint_fill_with_limit(&mut req, LOG_TARGET_BYTES, false); Ok(req) @@ -248,7 +268,11 @@ wasm_msg_guest! { buckets_per_decade: request.buckets_per_decade, openmetrics: request.openmetrics, }; - let text = TELEMETRY.snapshot().to_prometheus(&request.instance, &config); + let mut snap = TELEMETRY.snapshot(); + if APPLY_DEDUP_ENABLED.load(Ordering::Relaxed) { + snap.apply_dedup = Some(dedup_snapshot()); + } + let text = snap.to_prometheus(&request.instance, &config); Ok(proto::PrometheusSnapshotResponse { text }) } From 247e3f9fa13e93e4ec45c8bbfd52c36e39449e06 Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Wed, 2 Sep 2026 10:33:34 +0200 Subject: [PATCH 02/25] feat: add event delivery telemetry across all providers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- confidence-cloudflare-resolver/src/lib.rs | 57 +++++++++++-- .../flags/resolver/v1/internal_api.proto | 6 ++ confidence-resolver/src/telemetry.rs | 84 +++++++++++++++++++ .../go/confidence/flag_logger.go | 1 + .../confidence/internal/flag_logger/grpc.go | 28 ++++++- .../confidence/internal/flag_logger/multi.go | 24 +++++- .../proto/resolverinternal/internal_api.pb.go | 30 ++++++- .../go/confidence/provider.go | 6 ++ .../sdk/OpenFeatureLocalResolveProvider.java | 16 ++++ .../sdk/ProviderTelemetryResolver.java | 30 ++++++- .../js/src/ConfidenceServerProviderLocal.ts | 28 ++++++- .../flags/resolver/v1/internal_api.proto | 5 ++ .../python/src/confidence/provider.py | 24 +++++- 13 files changed, 318 insertions(+), 21 deletions(-) diff --git a/confidence-cloudflare-resolver/src/lib.rs b/confidence-cloudflare-resolver/src/lib.rs index 0be50d893..6b939b419 100644 --- a/confidence-cloudflare-resolver/src/lib.rs +++ b/confidence-cloudflare-resolver/src/lib.rs @@ -1005,7 +1005,7 @@ fn build_publish_events_request( async fn consume_events_queue( message_batch: MessageBatch, - _env: Env, + env: Env, ) -> Result<()> { let messages = message_batch.messages()?; let raw: Vec = messages.iter().map(|m| m.body().clone()).collect(); @@ -1015,6 +1015,8 @@ async fn consume_events_queue( return Ok(()); } + let event_count = all_events.len() as u64; + let client_secret = CONFIDENCE_CLIENT_SECRET .get() .ok_or_else(|| worker::Error::RustError("client secret not configured".into()))?; @@ -1026,17 +1028,58 @@ async fn consume_events_queue( &now.as_string().unwrap_or_default(), ); - let resp = send_events(&publish_request).await?; - if resp.status_code() >= 400 { - return Err(worker::Error::RustError(format!( - "events delivery failed: HTTP {}", - resp.status_code() - ))); + let delivered = match send_events(&publish_request).await { + Ok(resp) if resp.status_code() < 400 => true, + Ok(resp) => { + console_log!("events delivery failed: HTTP {}", resp.status_code()); + false + } + Err(e) => { + console_log!("events delivery error: {:?}", e); + false + } + }; + + if let Ok(kv) = env.kv("CONFIDENCE_METRICS_KV") { + update_events_kv(&kv, event_count, delivered).await; + } + + if !delivered { + return Err(worker::Error::RustError( + "events delivery failed".to_string(), + )); } Ok(()) } +async fn update_events_kv(kv: &kv::KvStore, event_count: u64, succeeded: bool) { + let mut cumulative = match kv.get("snapshot").text().await { + Ok(Some(text)) => serde_json::from_str::(&text).unwrap_or_default(), + _ => TelemetrySnapshot::default(), + }; + + cumulative.events_published = cumulative.events_published.wrapping_add(event_count); + if succeeded { + cumulative.event_batches_succeeded = cumulative.event_batches_succeeded.wrapping_add(1); + } else { + cumulative.event_batches_failed = cumulative.event_batches_failed.wrapping_add(1); + } + + let prom_text = cumulative.to_prometheus( + "cf-resolver", + &confidence_resolver::telemetry::PrometheusConfig::default(), + ); + + if let Ok(builder) = kv.put("snapshot", serde_json::to_string(&cumulative).unwrap_or_default()) + { + let _ = builder.execute().await; + } + if let Ok(builder) = kv.put("prometheus", prom_text) { + let _ = builder.execute().await; + } +} + async fn send_events(body: &serde_json::Value) -> Result { let mut init = RequestInit::new(); let headers = Headers::new(); diff --git a/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto b/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto index dde474cbe..47b74017d 100644 --- a/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto +++ b/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto @@ -139,6 +139,12 @@ message TelemetryData { uint32 flush_succeeded = 11; uint32 flush_failed = 12; + // Delta counters: event delivery stats since last flush. + // Piggybacked here because the events pipeline has no TelemetryData channel. + uint32 events_published = 13; + uint32 event_batches_succeeded = 14; + uint32 event_batches_failed = 15; + message ApplyDedupTelemetry { // Delta counters (since last flush): uint32 applies_total = 1; diff --git a/confidence-resolver/src/telemetry.rs b/confidence-resolver/src/telemetry.rs index 97704bb8e..12dc1d66c 100644 --- a/confidence-resolver/src/telemetry.rs +++ b/confidence-resolver/src/telemetry.rs @@ -116,6 +116,9 @@ pub struct TelemetrySnapshot { pub apply_dedup: Option, pub flush_succeeded: u64, pub flush_failed: u64, + pub events_published: u64, + pub event_batches_succeeded: u64, + pub event_batches_failed: u64, } #[derive(Clone, Default)] @@ -212,6 +215,15 @@ impl TelemetrySnapshot { self.flush_succeeded = self.flush_succeeded.wrapping_add(td.flush_succeeded as u64); self.flush_failed = self.flush_failed.wrapping_add(td.flush_failed as u64); + self.events_published = self + .events_published + .wrapping_add(td.events_published as u64); + self.event_batches_succeeded = self + .event_batches_succeeded + .wrapping_add(td.event_batches_succeeded as u64); + self.event_batches_failed = self + .event_batches_failed + .wrapping_add(td.event_batches_failed as u64); } /// Format the snapshot as Prometheus exposition text. @@ -241,6 +253,7 @@ impl TelemetrySnapshot { self.write_memory(w, resolver_id, config)?; self.write_apply_dedup(w, resolver_id, config)?; self.write_flush(w, resolver_id, config)?; + self.write_events(w, resolver_id, config)?; if config.openmetrics { writeln!(w, "# EOF")?; } @@ -531,6 +544,71 @@ impl TelemetrySnapshot { self.flush_failed ) } + + fn write_events( + &self, + w: &mut dyn fmt::Write, + resolver_id: &str, + config: &PrometheusConfig, + ) -> fmt::Result { + if self.events_published == 0 + && self.event_batches_succeeded == 0 + && self.event_batches_failed == 0 + { + return Ok(()); + } + let suffix = if config.openmetrics { ".0" } else { "" }; + + if self.events_published > 0 { + let type_name = if config.openmetrics { + "confidence_events_published" + } else { + "confidence_events_published_total" + }; + writeln!(w, "# HELP {type_name} Total events published.")?; + writeln!(w, "# TYPE {type_name} counter")?; + writeln!( + w, + "confidence_events_published_total{{resolver_id=\"{resolver_id}\"}} {}{suffix}", + self.events_published + )?; + } + + if self.event_batches_succeeded > 0 { + let type_name = if config.openmetrics { + "confidence_event_batches_succeeded" + } else { + "confidence_event_batches_succeeded_total" + }; + writeln!( + w, + "# HELP {type_name} Successful event batch deliveries." + )?; + writeln!(w, "# TYPE {type_name} counter")?; + writeln!( + w, + "confidence_event_batches_succeeded_total{{resolver_id=\"{resolver_id}\"}} {}{suffix}", + self.event_batches_succeeded + )?; + } + + if self.event_batches_failed > 0 { + let type_name = if config.openmetrics { + "confidence_event_batches_failed" + } else { + "confidence_event_batches_failed_total" + }; + writeln!(w, "# HELP {type_name} Failed event batch deliveries.")?; + writeln!(w, "# TYPE {type_name} counter")?; + writeln!( + w, + "confidence_event_batches_failed_total{{resolver_id=\"{resolver_id}\"}} {}{suffix}", + self.event_batches_failed + )?; + } + + Ok(()) + } } /// Concurrent telemetry collector. @@ -600,6 +678,9 @@ impl Telemetry { apply_dedup: None, flush_succeeded: 0, flush_failed: 0, + events_published: 0, + event_batches_succeeded: 0, + event_batches_failed: 0, } } @@ -682,6 +763,9 @@ impl Telemetry { apply_dedup: None, flush_succeeded: 0, flush_failed: 0, + events_published: 0, + event_batches_succeeded: 0, + event_batches_failed: 0, } } } diff --git a/openfeature-provider/go/confidence/flag_logger.go b/openfeature-provider/go/confidence/flag_logger.go index eacc44c2c..6cccddb33 100644 --- a/openfeature-provider/go/confidence/flag_logger.go +++ b/openfeature-provider/go/confidence/flag_logger.go @@ -7,4 +7,5 @@ import ( type FlagLogger interface { Write(request *resolverv1.WriteFlagLogsRequest) Shutdown() + RecordEventBatch(eventCount int, succeeded bool) } diff --git a/openfeature-provider/go/confidence/internal/flag_logger/grpc.go b/openfeature-provider/go/confidence/internal/flag_logger/grpc.go index eb9ebe82b..8d4f15d59 100644 --- a/openfeature-provider/go/confidence/internal/flag_logger/grpc.go +++ b/openfeature-provider/go/confidence/internal/flag_logger/grpc.go @@ -19,8 +19,11 @@ type GrpcFlagLogger struct { wg sync.WaitGroup attempts atomic.Int64 failures atomic.Int64 - flushSucceeded atomic.Int64 - flushFailed atomic.Int64 + flushSucceeded atomic.Int64 + flushFailed atomic.Int64 + eventsPublished atomic.Int64 + eventBatchesSucceeded atomic.Int64 + eventBatchesFailed atomic.Int64 } func NewGrpcWasmFlagLogger(stub resolverv1.InternalFlagLoggerServiceClient, clientSecret string, logger *slog.Logger) *GrpcFlagLogger { @@ -61,18 +64,33 @@ func (g *GrpcFlagLogger) Write(request *resolverv1.WriteFlagLogsRequest) { succeeded := uint32(g.flushSucceeded.Swap(0)) failed := uint32(g.flushFailed.Swap(0)) - if succeeded > 0 || failed > 0 { + evPub := uint32(g.eventsPublished.Swap(0)) + evOk := uint32(g.eventBatchesSucceeded.Swap(0)) + evFail := uint32(g.eventBatchesFailed.Swap(0)) + if succeeded > 0 || failed > 0 || evPub > 0 || evOk > 0 || evFail > 0 { if request.TelemetryData == nil { request.TelemetryData = &resolverv1.TelemetryData{} } request.TelemetryData.FlushSucceeded = succeeded request.TelemetryData.FlushFailed = failed + request.TelemetryData.EventsPublished = evPub + request.TelemetryData.EventBatchesSucceeded = evOk + request.TelemetryData.EventBatchesFailed = evFail } g.sendAsync(request) } +func (g *GrpcFlagLogger) RecordEventBatch(eventCount int, succeeded bool) { + if succeeded { + g.eventsPublished.Add(int64(eventCount)) + g.eventBatchesSucceeded.Add(1) + } else { + g.eventBatchesFailed.Add(1) + } +} + func (g *GrpcFlagLogger) sendAsync(request *resolverv1.WriteFlagLogsRequest) { g.wg.Add(1) go func() { @@ -123,3 +141,7 @@ func (n *NoOpWasmFlagLogger) Write(request *resolverv1.WriteFlagLogsRequest) { func (n *NoOpWasmFlagLogger) Shutdown() { // Nothing to shut down } + +func (n *NoOpWasmFlagLogger) RecordEventBatch(eventCount int, succeeded bool) { + // No-op +} diff --git a/openfeature-provider/go/confidence/internal/flag_logger/multi.go b/openfeature-provider/go/confidence/internal/flag_logger/multi.go index a8cb971d5..260bfd408 100644 --- a/openfeature-provider/go/confidence/internal/flag_logger/multi.go +++ b/openfeature-provider/go/confidence/internal/flag_logger/multi.go @@ -26,8 +26,11 @@ type MultiDestinationFlagLogger struct { wg sync.WaitGroup attempts atomic.Int64 failures atomic.Int64 - flushSucceeded atomic.Int64 - flushFailed atomic.Int64 + flushSucceeded atomic.Int64 + flushFailed atomic.Int64 + eventsPublished atomic.Int64 + eventBatchesSucceeded atomic.Int64 + eventBatchesFailed atomic.Int64 } // NewMultiDestinationFlagLogger creates a flag logger that routes to multiple @@ -87,12 +90,18 @@ func (m *MultiDestinationFlagLogger) Write(request *resolverv1.WriteFlagLogsRequ succeeded := uint32(m.flushSucceeded.Swap(0)) failed := uint32(m.flushFailed.Swap(0)) - if succeeded > 0 || failed > 0 { + evPub := uint32(m.eventsPublished.Swap(0)) + evOk := uint32(m.eventBatchesSucceeded.Swap(0)) + evFail := uint32(m.eventBatchesFailed.Swap(0)) + if succeeded > 0 || failed > 0 || evPub > 0 || evOk > 0 || evFail > 0 { if request.TelemetryData == nil { request.TelemetryData = &resolverv1.TelemetryData{} } request.TelemetryData.FlushSucceeded = succeeded request.TelemetryData.FlushFailed = failed + request.TelemetryData.EventsPublished = evPub + request.TelemetryData.EventBatchesSucceeded = evOk + request.TelemetryData.EventBatchesFailed = evFail } m.wg.Add(1) @@ -161,3 +170,12 @@ func (m *MultiDestinationFlagLogger) resolveDestinations() []admin.LogDestinatio func (m *MultiDestinationFlagLogger) Shutdown() { m.wg.Wait() } + +func (m *MultiDestinationFlagLogger) RecordEventBatch(eventCount int, succeeded bool) { + if succeeded { + m.eventsPublished.Add(int64(eventCount)) + m.eventBatchesSucceeded.Add(1) + } else { + m.eventBatchesFailed.Add(1) + } +} diff --git a/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go b/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go index 53f5d9a04..023ac688f 100644 --- a/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go +++ b/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go @@ -250,9 +250,12 @@ type TelemetryData struct { ProviderInitRate []*TelemetryData_ProviderInitRate `protobuf:"bytes,9,rep,name=provider_init_rate,json=providerInitRate,proto3" json:"provider_init_rate,omitempty"` // Delta counters: WriteFlagLogs batch delivery outcomes since last flush. // Populated by the host SDK after each delivery attempt. - FlushSucceeded uint32 `protobuf:"varint,11,opt,name=flush_succeeded,json=flushSucceeded,proto3" json:"flush_succeeded,omitempty"` - FlushFailed uint32 `protobuf:"varint,12,opt,name=flush_failed,json=flushFailed,proto3" json:"flush_failed,omitempty"` - unknownFields protoimpl.UnknownFields + FlushSucceeded uint32 `protobuf:"varint,11,opt,name=flush_succeeded,json=flushSucceeded,proto3" json:"flush_succeeded,omitempty"` + FlushFailed uint32 `protobuf:"varint,12,opt,name=flush_failed,json=flushFailed,proto3" json:"flush_failed,omitempty"` + EventsPublished uint32 `protobuf:"varint,13,opt,name=events_published,json=eventsPublished,proto3" json:"events_published,omitempty"` + EventBatchesSucceeded uint32 `protobuf:"varint,14,opt,name=event_batches_succeeded,json=eventBatchesSucceeded,proto3" json:"event_batches_succeeded,omitempty"` + EventBatchesFailed uint32 `protobuf:"varint,15,opt,name=event_batches_failed,json=eventBatchesFailed,proto3" json:"event_batches_failed,omitempty"` + unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -321,6 +324,27 @@ func (x *TelemetryData) GetFlushFailed() uint32 { return 0 } +func (x *TelemetryData) GetEventsPublished() uint32 { + if x != nil { + return x.EventsPublished + } + return 0 +} + +func (x *TelemetryData) GetEventBatchesSucceeded() uint32 { + if x != nil { + return x.EventBatchesSucceeded + } + return 0 +} + +func (x *TelemetryData) GetEventBatchesFailed() uint32 { + if x != nil { + return x.EventBatchesFailed + } + return 0 +} + type ClientInfo struct { state protoimpl.MessageState `protogen:"open.v1"` Client string `protobuf:"bytes,1,opt,name=client,proto3" json:"client,omitempty"` diff --git a/openfeature-provider/go/confidence/provider.go b/openfeature-provider/go/confidence/provider.go index 44dd855ad..1c7948ac3 100644 --- a/openfeature-provider/go/confidence/provider.go +++ b/openfeature-provider/go/confidence/provider.go @@ -632,9 +632,15 @@ func (p *LocalResolverProvider) flushAndPublishEvents(ctx context.Context) int { return 0 } + eventCount := len(batch.Events) if err := p.publishEvents(ctx, batch); err != nil { p.eventPublishFailures.Add(1) p.logger.Debug("Failed to publish events", "error", err) + if p.flagLogger != nil { + p.flagLogger.RecordEventBatch(eventCount, false) + } + } else if p.flagLogger != nil { + p.flagLogger.RecordEventBatch(eventCount, true) } if p.eventPublishAttempts.Add(1)%eventPublishLogWindow == 0 { diff --git a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java index 732b5a77d..7504996c8 100644 --- a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java +++ b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java @@ -83,6 +83,9 @@ public class OpenFeatureLocalResolveProvider implements FeatureProvider { private final AtomicLong eventPublishAttempts = new AtomicLong(); private final AtomicLong eventPublishFailures = new AtomicLong(); + private final AtomicLong telemetryEventsPublished = new AtomicLong(); + private final AtomicLong telemetryEventBatchesSucceeded = new AtomicLong(); + private final AtomicLong telemetryEventBatchesFailed = new AtomicLong(); private final ScheduledExecutorService flagsFetcherExecutor = newFlagsFetcherExecutor(); private final ScheduledExecutorService assignLogExecutor = Executors.newScheduledThreadPool(1, new ThreadFactoryBuilder().setDaemon(true).build()); @@ -209,6 +212,7 @@ public OpenFeatureLocalResolveProvider( new ProviderTelemetryResolver( flagLogger::write, wasmFlagLogger::drainFlushCounters, + this::drainEventCounters, SDK, initLabels, providerLogSink -> @@ -284,6 +288,7 @@ public OpenFeatureLocalResolveProvider( new ProviderTelemetryResolver( wasmFlagLogger::write, wasmFlagLogger::drainFlushCounters, + this::drainEventCounters, SDK, Map.of(), providerLogSink -> @@ -777,6 +782,8 @@ private void sendEvents(FlushEventsResponse batch) { .build(); try { final PublishEventsResponse response = eventsStub.publishEvents(request); + telemetryEventsPublished.addAndGet(batch.getEventsCount()); + telemetryEventBatchesSucceeded.incrementAndGet(); for (final EventError error : response.getErrorsList()) { log.error( "Failed to publish event at index {}: {} {}", @@ -786,6 +793,7 @@ private void sendEvents(FlushEventsResponse batch) { } } catch (StatusRuntimeException e) { eventPublishFailures.incrementAndGet(); + telemetryEventBatchesFailed.incrementAndGet(); log.warn("Failed to send events", e); } if (eventPublishAttempts.incrementAndGet() % EVENT_STATS_WINDOW == 0) { @@ -796,6 +804,14 @@ private void sendEvents(FlushEventsResponse batch) { } } + long[] drainEventCounters() { + return new long[] { + telemetryEventsPublished.getAndSet(0), + telemetryEventBatchesSucceeded.getAndSet(0), + telemetryEventBatchesFailed.getAndSet(0) + }; + } + private void doRegisterResolve(ResolveReason reason, long startNanos) { long latencyUs = (System.nanoTime() - startNanos) / 1000; try { diff --git a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java index 75504a1ae..ba69ab573 100644 --- a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java +++ b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java @@ -17,6 +17,7 @@ final class ProviderTelemetryResolver implements LocalResolver { private final Consumer logSink; private final Supplier flushCounterDrain; + private final Supplier eventCounterDrain; private final Sdk sdk; private final Map labels; private final LocalResolver delegate; @@ -27,7 +28,7 @@ final class ProviderTelemetryResolver implements LocalResolver { Sdk sdk, Map labels, Function, LocalResolver> innerFactory) { - this(logSink, () -> new long[] {0, 0}, sdk, labels, innerFactory); + this(logSink, () -> new long[] {0, 0}, () -> new long[] {0, 0, 0}, sdk, labels, innerFactory); } ProviderTelemetryResolver( @@ -36,8 +37,19 @@ final class ProviderTelemetryResolver implements LocalResolver { Sdk sdk, Map labels, Function, LocalResolver> innerFactory) { + this(logSink, flushCounterDrain, () -> new long[] {0, 0, 0}, sdk, labels, innerFactory); + } + + ProviderTelemetryResolver( + Consumer logSink, + Supplier flushCounterDrain, + Supplier eventCounterDrain, + Sdk sdk, + Map labels, + Function, LocalResolver> innerFactory) { this.logSink = logSink; this.flushCounterDrain = flushCounterDrain; + this.eventCounterDrain = eventCounterDrain; this.sdk = sdk; this.labels = Map.copyOf(labels); this.delegate = innerFactory.apply(this::writeLogs); @@ -46,6 +58,7 @@ final class ProviderTelemetryResolver implements LocalResolver { private synchronized void writeLogs(WriteFlagLogsRequest request) { WriteFlagLogsRequest outgoing = initSent ? request : addInitTelemetry(request); outgoing = addFlushCounters(outgoing); + outgoing = addEventCounters(outgoing); logSink.accept(outgoing); initSent = true; } @@ -64,6 +77,21 @@ private WriteFlagLogsRequest addFlushCounters(WriteFlagLogsRequest request) { .build(); } + private WriteFlagLogsRequest addEventCounters(WriteFlagLogsRequest request) { + final long[] counters = eventCounterDrain.get(); + if (counters[0] == 0 && counters[1] == 0 && counters[2] == 0) { + return request; + } + return request.toBuilder() + .setTelemetryData( + request.getTelemetryData().toBuilder() + .setEventsPublished((int) counters[0]) + .setEventBatchesSucceeded((int) counters[1]) + .setEventBatchesFailed((int) counters[2]) + .build()) + .build(); + } + private synchronized void emitInitIfPending() { if (initSent) { return; diff --git a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts index fb60f74ec..fab566ae4 100644 --- a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts +++ b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts @@ -95,6 +95,9 @@ export class ConfidenceServerProviderLocal implements Provider { private initTelemetryState: 'pending' | 'sending' | 'sent' = 'pending'; private flushSucceeded = 0; private flushFailed = 0; + private eventsPublished = 0; + private eventBatchesSucceeded = 0; + private eventBatchesFailed = 0; private resolverInstance: LocalResolver | null = null; private eventTracker: EventTracker | null = null; private stateEtag: string | null = null; @@ -317,9 +320,12 @@ export class ConfidenceServerProviderLocal implements Provider { body: body as Uint8Array, }); if (!response.ok) { + this.eventBatchesFailed++; logger.error(`Failed to send events: ${response.status} ${response.statusText}`); return; } + this.eventBatchesSucceeded++; + this.eventsPublished += batch.events?.length ?? 0; const { errors } = PublishEventsResponse.decode(new Uint8Array(await response.arrayBuffer())); for (const error of errors) { logger.error( @@ -327,6 +333,7 @@ export class ConfidenceServerProviderLocal implements Provider { ); } } catch (err) { + this.eventBatchesFailed++; logger.warn('Failed to send events:', err); } } @@ -565,17 +572,34 @@ export class ConfidenceServerProviderLocal implements Provider { } private addFlushDeliveryTelemetry(encodedWriteFlagLogRequest: Uint8Array): Uint8Array { - if (this.flushSucceeded === 0 && this.flushFailed === 0) { + const hasFlush = this.flushSucceeded > 0 || this.flushFailed > 0; + const hasEvents = + this.eventsPublished > 0 || this.eventBatchesSucceeded > 0 || this.eventBatchesFailed > 0; + if (!hasFlush && !hasEvents) { return encodedWriteFlagLogRequest; } const request = WriteFlagLogsRequest.decode(encodedWriteFlagLogRequest); if (!request.telemetryData) { - request.telemetryData = { resolverVersion: '', providerInitRate: [], flushSucceeded: 0, flushFailed: 0 }; + request.telemetryData = { + resolverVersion: '', + providerInitRate: [], + flushSucceeded: 0, + flushFailed: 0, + eventsPublished: 0, + eventBatchesSucceeded: 0, + eventBatchesFailed: 0, + }; } request.telemetryData.flushSucceeded = this.flushSucceeded; request.telemetryData.flushFailed = this.flushFailed; + request.telemetryData.eventsPublished = this.eventsPublished; + request.telemetryData.eventBatchesSucceeded = this.eventBatchesSucceeded; + request.telemetryData.eventBatchesFailed = this.eventBatchesFailed; this.flushSucceeded = 0; this.flushFailed = 0; + this.eventsPublished = 0; + this.eventBatchesSucceeded = 0; + this.eventBatchesFailed = 0; return WriteFlagLogsRequest.encode(request).finish(); } diff --git a/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto b/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto index b2cbef758..c5a43c13c 100644 --- a/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto +++ b/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto @@ -64,6 +64,11 @@ message TelemetryData { uint32 flush_succeeded = 11; uint32 flush_failed = 12; + // Delta counters: event delivery stats since last flush. + uint32 events_published = 13; + uint32 event_batches_succeeded = 14; + uint32 event_batches_failed = 15; + message ProviderInitRate { uint32 count = 1; reserved 2; // status — tbd diff --git a/openfeature-provider/python/src/confidence/provider.py b/openfeature-provider/python/src/confidence/provider.py index b62e06ad5..c1a1eca5f 100644 --- a/openfeature-provider/python/src/confidence/provider.py +++ b/openfeature-provider/python/src/confidence/provider.py @@ -286,6 +286,9 @@ def __init__( self._flush_succeeded = 0 self._flush_failed = 0 + self._event_telemetry_published = 0 + self._event_telemetry_succeeded = 0 + self._event_telemetry_failed = 0 # State fetcher (injected or created) self._state_fetcher = state_fetcher @@ -918,7 +921,16 @@ def _write_logs(self, log_data: bytes) -> None: flush_ok = self._flush_succeeded flush_err = self._flush_failed - need_rewrite = include_init or flush_ok > 0 or flush_err > 0 + with self._event_stats_lock: + ev_published = self._event_telemetry_published + ev_ok = self._event_telemetry_succeeded + ev_err = self._event_telemetry_failed + self._event_telemetry_published = 0 + self._event_telemetry_succeeded = 0 + self._event_telemetry_failed = 0 + has_flush = flush_ok > 0 or flush_err > 0 + has_events = ev_published > 0 or ev_ok > 0 or ev_err > 0 + need_rewrite = include_init or has_flush or has_events if need_rewrite: request = internal_api_pb2.WriteFlagLogsRequest.FromString(log_data) @@ -933,11 +945,15 @@ def _write_logs(self, log_data: bytes) -> None: init_rate.count = 1 for k, v in self._init_labels.items(): init_rate.labels[k] = v - if flush_ok > 0 or flush_err > 0: + if has_flush: request.telemetry_data.flush_succeeded = flush_ok request.telemetry_data.flush_failed = flush_err self._flush_succeeded = 0 self._flush_failed = 0 + if has_events: + request.telemetry_data.events_published = ev_published + request.telemetry_data.event_batches_succeeded = ev_ok + request.telemetry_data.event_batches_failed = ev_err log_data = request.SerializeToString() try: @@ -1147,6 +1163,10 @@ def _send_events(self, batch: events_wasm_pb2.FlushEventsResponse) -> None: with self._event_stats_lock: if failed: self._event_publish_failures += 1 + self._event_telemetry_failed += 1 + else: + self._event_telemetry_published += len(batch.events) + self._event_telemetry_succeeded += 1 self._event_publish_attempts += 1 if self._event_publish_attempts % EVENTS_STATS_WINDOW == 0: if self._event_publish_failures > 0: From 977fbc8d36965a56f6e7f1410c05a155df848ff6 Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Wed, 2 Sep 2026 14:01:32 +0200 Subject: [PATCH 03/25] fix: gofmt Go provider files Co-Authored-By: Claude Opus 4.6 (1M context) --- .../go/confidence/internal/flag_logger/grpc.go | 12 ++++++------ .../go/confidence/internal/flag_logger/multi.go | 12 ++++++------ .../proto/resolverinternal/internal_api.pb.go | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/openfeature-provider/go/confidence/internal/flag_logger/grpc.go b/openfeature-provider/go/confidence/internal/flag_logger/grpc.go index 8d4f15d59..8bb6d9fd8 100644 --- a/openfeature-provider/go/confidence/internal/flag_logger/grpc.go +++ b/openfeature-provider/go/confidence/internal/flag_logger/grpc.go @@ -13,12 +13,12 @@ import ( ) type GrpcFlagLogger struct { - stub resolverv1.InternalFlagLoggerServiceClient - clientSecret string - logger *slog.Logger - wg sync.WaitGroup - attempts atomic.Int64 - failures atomic.Int64 + stub resolverv1.InternalFlagLoggerServiceClient + clientSecret string + logger *slog.Logger + wg sync.WaitGroup + attempts atomic.Int64 + failures atomic.Int64 flushSucceeded atomic.Int64 flushFailed atomic.Int64 eventsPublished atomic.Int64 diff --git a/openfeature-provider/go/confidence/internal/flag_logger/multi.go b/openfeature-provider/go/confidence/internal/flag_logger/multi.go index 260bfd408..907e3179a 100644 --- a/openfeature-provider/go/confidence/internal/flag_logger/multi.go +++ b/openfeature-provider/go/confidence/internal/flag_logger/multi.go @@ -20,12 +20,12 @@ type logSender func(ctx context.Context, request *resolverv1.WriteFlagLogsReques // CDN state. The first destination is primary; the second is fallback on error. // If no destinations are configured, it defaults to Spotify Edge (gRPC). type MultiDestinationFlagLogger struct { - senders map[admin.LogDestination]logSender - destinations func() []admin.LogDestination - logger *slog.Logger - wg sync.WaitGroup - attempts atomic.Int64 - failures atomic.Int64 + senders map[admin.LogDestination]logSender + destinations func() []admin.LogDestination + logger *slog.Logger + wg sync.WaitGroup + attempts atomic.Int64 + failures atomic.Int64 flushSucceeded atomic.Int64 flushFailed atomic.Int64 eventsPublished atomic.Int64 diff --git a/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go b/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go index 023ac688f..47af3fe39 100644 --- a/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go +++ b/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go @@ -256,7 +256,7 @@ type TelemetryData struct { EventBatchesSucceeded uint32 `protobuf:"varint,14,opt,name=event_batches_succeeded,json=eventBatchesSucceeded,proto3" json:"event_batches_succeeded,omitempty"` EventBatchesFailed uint32 `protobuf:"varint,15,opt,name=event_batches_failed,json=eventBatchesFailed,proto3" json:"event_batches_failed,omitempty"` unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + sizeCache protoimpl.SizeCache } func (x *TelemetryData) Reset() { From 39b2682a148a7f405446b66383c1f9689f922c5c Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Wed, 2 Sep 2026 14:11:23 +0200 Subject: [PATCH 04/25] =?UTF-8?q?fix:=20review=20fixes=20=E2=80=94=20dupli?= =?UTF-8?q?cate=20metric,=20counter=20race,=20events=5Fpublished=20on=20fa?= =?UTF-8?q?ilure?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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) --- confidence-cloudflare-resolver/src/lib.rs | 2 +- confidence-resolver/src/telemetry.rs | 73 +++++++++++++++---- .../confidence/sdk/GrpcWasmFlagLogger.java | 14 ++-- 3 files changed, 68 insertions(+), 21 deletions(-) diff --git a/confidence-cloudflare-resolver/src/lib.rs b/confidence-cloudflare-resolver/src/lib.rs index 6b939b419..ab0b847e5 100644 --- a/confidence-cloudflare-resolver/src/lib.rs +++ b/confidence-cloudflare-resolver/src/lib.rs @@ -1059,8 +1059,8 @@ async fn update_events_kv(kv: &kv::KvStore, event_count: u64, succeeded: bool) { _ => TelemetrySnapshot::default(), }; - cumulative.events_published = cumulative.events_published.wrapping_add(event_count); if succeeded { + cumulative.events_published = cumulative.events_published.wrapping_add(event_count); cumulative.event_batches_succeeded = cumulative.event_batches_succeeded.wrapping_add(1); } else { cumulative.event_batches_failed = cumulative.event_batches_failed.wrapping_add(1); diff --git a/confidence-resolver/src/telemetry.rs b/confidence-resolver/src/telemetry.rs index 12dc1d66c..b3d0a61f1 100644 --- a/confidence-resolver/src/telemetry.rs +++ b/confidence-resolver/src/telemetry.rs @@ -478,17 +478,6 @@ impl TelemetrySnapshot { ad.map_size )?; - writeln!( - w, - "# HELP confidence_apply_dedup_map_size Current entries in the dedup map." - )?; - writeln!(w, "# TYPE confidence_apply_dedup_map_size gauge")?; - writeln!( - w, - "confidence_apply_dedup_map_size{{resolver_id=\"{resolver_id}\"}} {}{suffix}", - ad.map_size - )?; - writeln!( w, "# HELP confidence_apply_dedup_map_capacity Maximum entries allowed in the dedup map." @@ -580,10 +569,7 @@ impl TelemetrySnapshot { } else { "confidence_event_batches_succeeded_total" }; - writeln!( - w, - "# HELP {type_name} Successful event batch deliveries." - )?; + writeln!(w, "# HELP {type_name} Successful event batch deliveries.")?; writeln!(w, "# TYPE {type_name} counter")?; writeln!( w, @@ -1495,4 +1481,61 @@ mod tests { assert_eq!(snap.flush_succeeded, 10); assert_eq!(snap.flush_failed, 2); } + + #[test] + fn accumulate_delta_event_counters() { + let mut snap = TelemetrySnapshot::default(); + let td = pb::TelemetryData { + events_published: 42, + event_batches_succeeded: 3, + event_batches_failed: 1, + ..Default::default() + }; + + snap.accumulate_delta(&td); + assert_eq!(snap.events_published, 42); + assert_eq!(snap.event_batches_succeeded, 3); + assert_eq!(snap.event_batches_failed, 1); + + snap.accumulate_delta(&td); + assert_eq!(snap.events_published, 84); + assert_eq!(snap.event_batches_succeeded, 6); + assert_eq!(snap.event_batches_failed, 2); + } + + #[test] + fn openmetrics_with_all_telemetry() { + let tel = Telemetry::with_memory_provider(|| 1_048_576); + tel.record_latency_us(100); + tel.mark_resolve(ResolveReason::Match); + + let mut snap = tel.snapshot(); + snap.apply_dedup = Some(ApplyDedupSnapshot { + applies_total: 10, + applies_deduped: 3, + applies_not_cached: 0, + sweeps: 1, + map_size: 5, + map_capacity: 100_000, + }); + snap.flush_succeeded = 2; + snap.flush_failed = 1; + snap.events_published = 50; + snap.event_batches_succeeded = 4; + snap.event_batches_failed = 1; + + let config = PrometheusConfig { + openmetrics: true, + ..PrometheusConfig::default() + }; + let output = snap.to_prometheus("w0", &config); + + assert!(output.trim_end().ends_with("# EOF")); + let result = openmetrics_parser::openmetrics::parse_openmetrics(&output); + assert!( + result.is_ok(), + "OpenMetrics parser rejected output with all telemetry: {:?}\n\nRaw:\n{output}", + result.err() + ); + } } diff --git a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java index 29745094c..456559826 100644 --- a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java +++ b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java @@ -38,7 +38,8 @@ public class GrpcWasmFlagLogger implements WasmFlagLogger { private final Duration shutdownTimeout; private final AtomicLong attempts = new AtomicLong(); private final AtomicLong failures = new AtomicLong(); - private final AtomicLong successes = new AtomicLong(); + private final AtomicLong telemetryFlushSucceeded = new AtomicLong(); + private final AtomicLong telemetryFlushFailed = new AtomicLong(); private final String clientSecret; private final HttpClientFactory httpClientFactory; private final AtomicReference> logDestinations = @@ -130,9 +131,10 @@ private void sendWithFailover(WriteFlagLogsRequest request) { if (destinations.isEmpty()) { try { sendToEdge(request); - successes.incrementAndGet(); + telemetryFlushSucceeded.incrementAndGet(); } catch (Exception e) { failures.incrementAndGet(); + telemetryFlushFailed.incrementAndGet(); } return; } @@ -140,7 +142,7 @@ private void sendWithFailover(WriteFlagLogsRequest request) { final LogDestination primary = destinations.get(0); try { sendToDestination(primary, request); - successes.incrementAndGet(); + telemetryFlushSucceeded.incrementAndGet(); logger.debug( "Successfully sent flag log via {} with {} assigned, {} client_resolve_info, {} flag_resolve_info", primary, @@ -153,7 +155,7 @@ private void sendWithFailover(WriteFlagLogsRequest request) { logger.warn("Primary destination {} failed, trying fallback {}", primary, fallback); try { sendToDestination(fallback, request); - successes.incrementAndGet(); + telemetryFlushSucceeded.incrementAndGet(); logger.debug( "Successfully sent flag log via fallback {} with {} assigned, {} client_resolve_info, {} flag_resolve_info", fallback, @@ -162,10 +164,12 @@ private void sendWithFailover(WriteFlagLogsRequest request) { request.getFlagResolveInfoCount()); } catch (Exception fallbackEx) { failures.incrementAndGet(); + telemetryFlushFailed.incrementAndGet(); logger.warn("Fallback destination {} also failed", fallback, fallbackEx); } } else { failures.incrementAndGet(); + telemetryFlushFailed.incrementAndGet(); } } } @@ -217,7 +221,7 @@ private void sendToCloudflare(WriteFlagLogsRequest request) { @Override public long[] drainFlushCounters() { - return new long[] {successes.getAndSet(0), failures.getAndSet(0)}; + return new long[] {telemetryFlushSucceeded.getAndSet(0), telemetryFlushFailed.getAndSet(0)}; } /** From 90f00d8cbf5a9ab2206029651cb86bb32cd320c9 Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Wed, 2 Sep 2026 14:21:39 +0200 Subject: [PATCH 05/25] fix: review bugs + broken Go interface + test improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- openfeature-provider/go/confidence/integration_test.go | 2 ++ .../go/confidence/internal/flag_logger/capturing.go | 3 +++ .../go/confidence/internal/testutil/helpers.go | 2 ++ 3 files changed, 7 insertions(+) diff --git a/openfeature-provider/go/confidence/integration_test.go b/openfeature-provider/go/confidence/integration_test.go index 93c46ef5b..8777a5695 100644 --- a/openfeature-provider/go/confidence/integration_test.go +++ b/openfeature-provider/go/confidence/integration_test.go @@ -56,6 +56,8 @@ func (t *trackingFlagLogger) Shutdown() { t.actualLogger.Shutdown() } +func (t *trackingFlagLogger) RecordEventBatch(eventCount int, succeeded bool) {} + func (t *trackingFlagLogger) GetLogsSentCount() int32 { return atomic.LoadInt32(&t.logsSentCount) } diff --git a/openfeature-provider/go/confidence/internal/flag_logger/capturing.go b/openfeature-provider/go/confidence/internal/flag_logger/capturing.go index 101739dde..8a8535d0e 100644 --- a/openfeature-provider/go/confidence/internal/flag_logger/capturing.go +++ b/openfeature-provider/go/confidence/internal/flag_logger/capturing.go @@ -53,6 +53,9 @@ func (c *CapturingFlagLogger) Shutdown() { c.shutdownCalled = true } +// RecordEventBatch is a no-op for the capturing logger. +func (c *CapturingFlagLogger) RecordEventBatch(eventCount int, succeeded bool) {} + // GetCapturedRequests returns a copy of all captured requests func (c *CapturingFlagLogger) GetCapturedRequests() []*resolverv1.WriteFlagLogsRequest { c.mu.Lock() diff --git a/openfeature-provider/go/confidence/internal/testutil/helpers.go b/openfeature-provider/go/confidence/internal/testutil/helpers.go index 53de8c80f..30de97038 100644 --- a/openfeature-provider/go/confidence/internal/testutil/helpers.go +++ b/openfeature-provider/go/confidence/internal/testutil/helpers.go @@ -52,6 +52,8 @@ func (m *MockFlagLogger) Write(request *resolverv1.WriteFlagLogsRequest) { m.writeFunc(request) } +func (m *MockFlagLogger) RecordEventBatch(eventCount int, succeeded bool) {} + type StateProviderMock struct { AccountID string State []byte From a41393e6f7ff30cde6a10b730ade13d935eaa69c Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Wed, 2 Sep 2026 14:32:06 +0200 Subject: [PATCH 06/25] feat: add ApplyDedupTelemetry to provider proto + rebuild WASM 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) --- .../assets/confidence_resolver.wasm | Bin 500838 -> 510659 bytes .../proto/resolverinternal/internal_api.pb.go | 238 +++++++++++++----- .../flags/resolver/v1/internal_api.proto | 11 +- 3 files changed, 183 insertions(+), 66 deletions(-) diff --git a/openfeature-provider/go/confidence/internal/local_resolver/assets/confidence_resolver.wasm b/openfeature-provider/go/confidence/internal/local_resolver/assets/confidence_resolver.wasm index 4b70bf1928ee1e9119b593593c0c5e851c256070..19a75352aae0d50876a95d0393f6a8a0c24cea18 100755 GIT binary patch delta 118831 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 delta 109105 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
SCTO_!~__ z-JAYK^)LU6y6x~7n{ptJW>AnLsq%}pXJq;vG!%pO$Q^V$&6HJlP*+eu{+)CeJtL>z zNp(reHFsh}qzv3eHzMayEQgGMGJRf79|38&O0FM4^|K?AO4!q7C!0ku+}LyT#xr-* zkcg*#GxtLI+U5OsQ?n8k5y@^i;&o_Pwbc$sJi9O@zy${xRJ%5vfECKb_Nn?eleP1l z7k9(U0jna7utyO+jIJumOG>&IbisAW()&b8n~2wvef%n&%QK2lL8b+Z9_{>OSgi7U zP(D3U-i7oi7@N!DyWDl;)_bTYCfErh=_V?d_l!iBzm`)*(zW!8yg9>@N}tKIBdKnj z6=s8}GAhvy$|m$*SlxbX%@o-s;hJATk!3g4+@Ir&~1m~w=Hwze8Tu5s7V!^85o zd!cU*%bEAlN;+K8^?vXGeJ5Xkfc{43WY#E}O=o4rC~7ax9GAb0q7Z#A)Bldy&JXhC zztf^fOgf*IF;3q6Ajtd!x&1+^q$lL#|DZ46{k-!bWPhsSw}&vN0oA5IO!WfC85j_n z%Wv$NCVM_iUFd|I{xBv>C*>~>Q?HD02DNn=Qx7M$w!l>IYp3MkM`$DcDC<0m$aa5&21Wf0XX3YlV+MX@fm8`A4_biY-=2gRk*^?X>*(QR+)S%lv=Q<@AfZ z>0k7yb!j2v9|Pl_mIEH6rt+~8*fjDnSczxk_Q$BBocI_e$g~o;0e+VqORy^Pvn(m0 zR^s$%`K24{f4fWQU*P(lr4+>U;GRtk^pidZo#cX*|1h+0jTD z7Uqnasqok_K9MS~98b*!uKyfQ4ZKIWtoE&3G9KpcDH%I~`T+$uPoSs0=hUkm@}~*Z zi1X_cDMvheNE#C9O!iqMYW0DECJuU`Qr6+?`es$q_Y0 zRuT+9F8IIJPNn*EKvrS5Oxn*D!82;n6YY2V(Iux%qm=q=+OgD%{JY7>1UGiT6Y=cGR?rDrCc0O|cQlg`9^$EHt6(~ihrpP>mzeN0kr<~qg|FPlPN z!Gk)Se|7%J)7Hz4l3q-)%Ec@SCEOQ^9nKMuaQ7UM56z+{QHg6d7FK_d|C~)@ASchw zrdR0``N|v^(G~MxRgS5sng??-q^2XFKKS?kU@{Fdg+l!0fiTfN`R|bZydp_>{Zom~`wZBrvE~2!O(%r}mtJ&4ksmd8}z_)a& zI(5Rd#%ed-@9-C)38U;OMDyjtvwj8(Cs^X_go}=JtnBb>`0_3h%~Z*;O+NoAL7u2l zA+B0>TtIQ*jTy540`SF$QsPpAMP81z06(P#-F!(3Iz^FD>SxJowSsgL?9E$ z!kn>aAr#8OwQ}e}tVaD-=DZQs&vo;i4{19Y*IffH_ETUrW|#bYzBB)(ZfDtF1DFE~S~DiLl# z5F7TZqDNK(a?T6RW`XSt6vouqg7bg!g0odH(gatsmEYr_rI1&r9sz{+Ayh{;Ti|Rj z4o#BxEpT3YmvY8Kc>Qnw`2WRs9|pK!p);#Q0b~KJ5UTTu8KOvMy~kb~%W>-P-wd
0W0GNNA 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 JsiM~OI5gTGhaiqAywC&G70CxZa6 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 GWB&(zL7xZ! delta 118831 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 From a4aaf1d6f5ca7f3754307d63b4b2f533a72836a7 Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Wed, 2 Sep 2026 14:48:50 +0200 Subject: [PATCH 08/25] fix(python): regenerate proto with all telemetry fields 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) --- .../flags/resolver/v1/internal_api_pb2.py | 110 +++++++++--------- 1 file changed, 56 insertions(+), 54 deletions(-) diff --git a/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2.py b/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2.py index 3b0740e89..ffaaf31ea 100644 --- a/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2.py +++ b/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: confidence/flags/resolver/v1/internal_api.proto -# Protobuf Python Version: 5.29.0 +# Protobuf Python Version: 5.29.3 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -13,7 +13,7 @@ _runtime_version.Domain.PUBLIC, 5, 29, - 0, + 3, '', 'confidence/flags/resolver/v1/internal_api.proto' ) @@ -26,7 +26,7 @@ from confidence.flags.resolver.v1 import types_pb2 as confidence_dot_flags_dot_resolver_dot_v1_dot_types__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n/confidence/flags/resolver/v1/internal_api.proto\x12\x1c\x63onfidence.flags.resolver.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a(confidence/flags/resolver/v1/types.proto\"\xb6\x02\n\x14WriteFlagLogsRequest\x12\x41\n\rflag_assigned\x18\x01 \x03(\x0b\x32*.confidence.flags.resolver.v1.FlagAssigned\x12\x43\n\x0etelemetry_data\x18\x02 \x01(\x0b\x32+.confidence.flags.resolver.v1.TelemetryData\x12L\n\x13\x63lient_resolve_info\x18\x03 \x03(\x0b\x32/.confidence.flags.resolver.v1.ClientResolveInfo\x12H\n\x11\x66lag_resolve_info\x18\x04 \x03(\x0b\x32-.confidence.flags.resolver.v1.FlagResolveInfo\"\x17\n\x15WriteFlagLogsResponse\"n\n\x15IngestFlagLogsRequest\x12\x12\n\naccount_id\x18\x01 \x01(\t\x12\x41\n\x05\x62\x61tch\x18\x02 \x01(\x0b\x32\x32.confidence.flags.resolver.v1.WriteFlagLogsRequest\"\x95\x03\n\rTelemetryData\x12.\n\x03sdk\x18\x02 \x01(\x0b\x32!.confidence.flags.resolver.v1.Sdk\x12\x18\n\x10resolver_version\x18\x08 \x01(\t\x12X\n\x12provider_init_rate\x18\t \x03(\x0b\x32<.confidence.flags.resolver.v1.TelemetryData.ProviderInitRate\x12\x17\n\x0f\x66lush_succeeded\x18\x0b \x01(\r\x12\x14\n\x0c\x66lush_failed\x18\x0c \x01(\r\x1a\xb0\x01\n\x10ProviderInitRate\x12\r\n\x05\x63ount\x18\x01 \x01(\r\x12X\n\x06labels\x18\x03 \x03(\x0b\x32H.confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01J\x04\x08\x02\x10\x03\"g\n\nClientInfo\x12\x0e\n\x06\x63lient\x18\x01 \x01(\t\x12\x19\n\x11\x63lient_credential\x18\x02 \x01(\t\x12.\n\x03sdk\x18\x03 \x01(\x0b\x32!.confidence.flags.resolver.v1.Sdk\"\xa4\x07\n\x0c\x46lagAssigned\x12\x12\n\nresolve_id\x18\n \x01(\t\x12=\n\x0b\x63lient_info\x18\x03 \x01(\x0b\x32(.confidence.flags.resolver.v1.ClientInfo\x12\x45\n\x05\x66lags\x18\x0f \x03(\x0b\x32\x36.confidence.flags.resolver.v1.FlagAssigned.AppliedFlag\x1a\xbd\x03\n\x0b\x41ppliedFlag\x12\x0c\n\x04\x66lag\x18\x01 \x01(\t\x12\x15\n\rtargeting_key\x18\x02 \x01(\t\x12\x1e\n\x16targeting_key_selector\x18\x03 \x01(\t\x12T\n\x0f\x61ssignment_info\x18\x04 \x01(\x0b\x32\x39.confidence.flags.resolver.v1.FlagAssigned.AssignmentInfoH\x00\x12Z\n\x12\x64\x65\x66\x61ult_assignment\x18\x05 \x01(\x0b\x32<.confidence.flags.resolver.v1.FlagAssigned.DefaultAssignmentH\x00\x12\x15\n\rassignment_id\x18\x06 \x01(\t\x12\x0c\n\x04rule\x18\x07 \x01(\t\x12T\n\x17\x66\x61llthrough_assignments\x18\x08 \x03(\x0b\x32\x33.confidence.flags.resolver.v1.FallthroughAssignment\x12.\n\napply_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x0c\n\nassignment\x1a\x32\n\x0e\x41ssignmentInfo\x12\x0f\n\x07segment\x18\x01 \x01(\t\x12\x0f\n\x07variant\x18\x02 \x01(\t\x1a\x85\x02\n\x11\x44\x65\x66\x61ultAssignment\x12\x64\n\x06reason\x18\x01 \x01(\x0e\x32T.confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.DefaultAssignmentReason\"\x89\x01\n\x17\x44\x65\x66\x61ultAssignmentReason\x12)\n%DEFAULT_ASSIGNMENT_REASON_UNSPECIFIED\x10\x00\x12\x14\n\x10NO_SEGMENT_MATCH\x10\x01\x12\x1a\n\x12NO_TREATMENT_MATCH\x10\x02\x1a\x02\x08\x01\x12\x11\n\rFLAG_ARCHIVED\x10\x03\"s\n\x15\x46\x61llthroughAssignment\x12\x0c\n\x04rule\x18\x01 \x01(\t\x12\x15\n\rassignment_id\x18\x02 \x01(\t\x12\x15\n\rtargeting_key\x18\x03 \x01(\t\x12\x1e\n\x16targeting_key_selector\x18\x04 \x01(\t\"\xdf\x02\n\x11\x43lientResolveInfo\x12\x0e\n\x06\x63lient\x18\x01 \x01(\t\x12\x19\n\x11\x63lient_credential\x18\x02 \x01(\t\x12_\n\x06schema\x18\x03 \x03(\x0b\x32O.confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance\x1a\xbd\x01\n\x1f\x45valuationContextSchemaInstance\x12k\n\x06schema\x18\x01 \x03(\x0b\x32[.confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry\x1a-\n\x0bSchemaEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"\xb5\x01\n\x0f\x46lagResolveInfo\x12\x0c\n\x04\x66lag\x18\x01 \x01(\t\x12^\n\x14variant_resolve_info\x18\x02 \x03(\x0b\x32@.confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo\x1a\x34\n\x12VariantResolveInfo\x12\x0f\n\x07variant\x18\x01 \x01(\t\x12\r\n\x05\x63ount\x18\x03 \x01(\x03\"]\n\x16WriteOperationsRequest\x12\x43\n\x10store_variant_op\x18\x01 \x03(\x0b\x32).confidence.flags.resolver.v1.VariantData\"\x17\n\x15WriteOperationsResult\"D\n\rVariantReadOp\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x0c\n\x04rule\x18\x03 \x01(\t\"8\n\x0fInclusionReadOp\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\"\xa2\x01\n\x06ReadOp\x12\x46\n\x0fvariant_read_op\x18\x01 \x01(\x0b\x32+.confidence.flags.resolver.v1.VariantReadOpH\x00\x12J\n\x11inclusion_read_op\x18\x02 \x01(\x0b\x32-.confidence.flags.resolver.v1.InclusionReadOpH\x00\x42\x04\n\x02op\"J\n\x15ReadOperationsRequest\x12\x31\n\x03ops\x18\x03 \x03(\x0b\x32$.confidence.flags.resolver.v1.ReadOp\"S\n\x0bVariantData\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x0c\n\x04rule\x18\x03 \x01(\t\x12\x0f\n\x07variant\x18\x04 \x01(\t\"K\n\rInclusionData\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x13\n\x0bis_included\x18\x03 \x01(\x08\"\xa4\x01\n\nReadResult\x12\x43\n\x0evariant_result\x18\x01 \x01(\x0b\x32).confidence.flags.resolver.v1.VariantDataH\x00\x12G\n\x10inclusion_result\x18\x02 \x01(\x0b\x32+.confidence.flags.resolver.v1.InclusionDataH\x00\x42\x08\n\x06result\"Q\n\x14ReadOperationsResult\x12\x39\n\x07results\x18\x01 \x03(\x0b\x32(.confidence.flags.resolver.v1.ReadResult2\xb2\x03\n\x19InternalFlagLoggerService\x12~\n\x13\x43lientWriteFlagLogs\x12\x32.confidence.flags.resolver.v1.WriteFlagLogsRequest\x1a\x33.confidence.flags.resolver.v1.WriteFlagLogsResponse\x12\x8a\x01\n\x1bWriteMaterializedOperations\x12\x34.confidence.flags.resolver.v1.WriteOperationsRequest\x1a\x33.confidence.flags.resolver.v1.WriteOperationsResult\"\x00\x12\x87\x01\n\x1aReadMaterializedOperations\x12\x33.confidence.flags.resolver.v1.ReadOperationsRequest\x1a\x32.confidence.flags.resolver.v1.ReadOperationsResult\"\x00\x42\xad\x01\n,com.spotify.confidence.sdk.flags.resolver.v1B\x10InternalApiProtoP\x01Zigithub.com/spotify/confidence-resolver/openfeature-provider/go/confidence/internal/proto/resolverinternalb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n/confidence/flags/resolver/v1/internal_api.proto\x12\x1c\x63onfidence.flags.resolver.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a(confidence/flags/resolver/v1/types.proto\"\xb6\x02\n\x14WriteFlagLogsRequest\x12\x41\n\rflag_assigned\x18\x01 \x03(\x0b\x32*.confidence.flags.resolver.v1.FlagAssigned\x12\x43\n\x0etelemetry_data\x18\x02 \x01(\x0b\x32+.confidence.flags.resolver.v1.TelemetryData\x12L\n\x13\x63lient_resolve_info\x18\x03 \x03(\x0b\x32/.confidence.flags.resolver.v1.ClientResolveInfo\x12H\n\x11\x66lag_resolve_info\x18\x04 \x03(\x0b\x32-.confidence.flags.resolver.v1.FlagResolveInfo\"\x17\n\x15WriteFlagLogsResponse\"n\n\x15IngestFlagLogsRequest\x12\x12\n\naccount_id\x18\x01 \x01(\t\x12\x41\n\x05\x62\x61tch\x18\x02 \x01(\x0b\x32\x32.confidence.flags.resolver.v1.WriteFlagLogsRequest\"\xe0\x05\n\rTelemetryData\x12.\n\x03sdk\x18\x02 \x01(\x0b\x32!.confidence.flags.resolver.v1.Sdk\x12\x18\n\x10resolver_version\x18\x08 \x01(\t\x12X\n\x12provider_init_rate\x18\t \x03(\x0b\x32<.confidence.flags.resolver.v1.TelemetryData.ProviderInitRate\x12T\n\x0b\x61pply_dedup\x18\n \x01(\x0b\x32?.confidence.flags.resolver.v1.TelemetryData.ApplyDedupTelemetry\x12\x17\n\x0f\x66lush_succeeded\x18\x0b \x01(\r\x12\x14\n\x0c\x66lush_failed\x18\x0c \x01(\r\x12\x18\n\x10\x65vents_published\x18\r \x01(\r\x12\x1f\n\x17\x65vent_batches_succeeded\x18\x0e \x01(\r\x12\x1c\n\x14\x65vent_batches_failed\x18\x0f \x01(\r\x1a\x99\x01\n\x13\x41pplyDedupTelemetry\x12\x15\n\rapplies_total\x18\x01 \x01(\r\x12\x17\n\x0f\x61pplies_deduped\x18\x02 \x01(\r\x12\x1a\n\x12\x61pplies_not_cached\x18\x03 \x01(\r\x12\x0e\n\x06sweeps\x18\x04 \x01(\r\x12\x10\n\x08map_size\x18\x05 \x01(\r\x12\x14\n\x0cmap_capacity\x18\x06 \x01(\r\x1a\xb0\x01\n\x10ProviderInitRate\x12\r\n\x05\x63ount\x18\x01 \x01(\r\x12X\n\x06labels\x18\x03 \x03(\x0b\x32H.confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01J\x04\x08\x02\x10\x03\"g\n\nClientInfo\x12\x0e\n\x06\x63lient\x18\x01 \x01(\t\x12\x19\n\x11\x63lient_credential\x18\x02 \x01(\t\x12.\n\x03sdk\x18\x03 \x01(\x0b\x32!.confidence.flags.resolver.v1.Sdk\"\xa4\x07\n\x0c\x46lagAssigned\x12\x12\n\nresolve_id\x18\n \x01(\t\x12=\n\x0b\x63lient_info\x18\x03 \x01(\x0b\x32(.confidence.flags.resolver.v1.ClientInfo\x12\x45\n\x05\x66lags\x18\x0f \x03(\x0b\x32\x36.confidence.flags.resolver.v1.FlagAssigned.AppliedFlag\x1a\xbd\x03\n\x0b\x41ppliedFlag\x12\x0c\n\x04\x66lag\x18\x01 \x01(\t\x12\x15\n\rtargeting_key\x18\x02 \x01(\t\x12\x1e\n\x16targeting_key_selector\x18\x03 \x01(\t\x12T\n\x0f\x61ssignment_info\x18\x04 \x01(\x0b\x32\x39.confidence.flags.resolver.v1.FlagAssigned.AssignmentInfoH\x00\x12Z\n\x12\x64\x65\x66\x61ult_assignment\x18\x05 \x01(\x0b\x32<.confidence.flags.resolver.v1.FlagAssigned.DefaultAssignmentH\x00\x12\x15\n\rassignment_id\x18\x06 \x01(\t\x12\x0c\n\x04rule\x18\x07 \x01(\t\x12T\n\x17\x66\x61llthrough_assignments\x18\x08 \x03(\x0b\x32\x33.confidence.flags.resolver.v1.FallthroughAssignment\x12.\n\napply_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x0c\n\nassignment\x1a\x32\n\x0e\x41ssignmentInfo\x12\x0f\n\x07segment\x18\x01 \x01(\t\x12\x0f\n\x07variant\x18\x02 \x01(\t\x1a\x85\x02\n\x11\x44\x65\x66\x61ultAssignment\x12\x64\n\x06reason\x18\x01 \x01(\x0e\x32T.confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.DefaultAssignmentReason\"\x89\x01\n\x17\x44\x65\x66\x61ultAssignmentReason\x12)\n%DEFAULT_ASSIGNMENT_REASON_UNSPECIFIED\x10\x00\x12\x14\n\x10NO_SEGMENT_MATCH\x10\x01\x12\x1a\n\x12NO_TREATMENT_MATCH\x10\x02\x1a\x02\x08\x01\x12\x11\n\rFLAG_ARCHIVED\x10\x03\"s\n\x15\x46\x61llthroughAssignment\x12\x0c\n\x04rule\x18\x01 \x01(\t\x12\x15\n\rassignment_id\x18\x02 \x01(\t\x12\x15\n\rtargeting_key\x18\x03 \x01(\t\x12\x1e\n\x16targeting_key_selector\x18\x04 \x01(\t\"\xdf\x02\n\x11\x43lientResolveInfo\x12\x0e\n\x06\x63lient\x18\x01 \x01(\t\x12\x19\n\x11\x63lient_credential\x18\x02 \x01(\t\x12_\n\x06schema\x18\x03 \x03(\x0b\x32O.confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance\x1a\xbd\x01\n\x1f\x45valuationContextSchemaInstance\x12k\n\x06schema\x18\x01 \x03(\x0b\x32[.confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry\x1a-\n\x0bSchemaEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"\xb5\x01\n\x0f\x46lagResolveInfo\x12\x0c\n\x04\x66lag\x18\x01 \x01(\t\x12^\n\x14variant_resolve_info\x18\x02 \x03(\x0b\x32@.confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo\x1a\x34\n\x12VariantResolveInfo\x12\x0f\n\x07variant\x18\x01 \x01(\t\x12\r\n\x05\x63ount\x18\x03 \x01(\x03\"]\n\x16WriteOperationsRequest\x12\x43\n\x10store_variant_op\x18\x01 \x03(\x0b\x32).confidence.flags.resolver.v1.VariantData\"\x17\n\x15WriteOperationsResult\"D\n\rVariantReadOp\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x0c\n\x04rule\x18\x03 \x01(\t\"8\n\x0fInclusionReadOp\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\"\xa2\x01\n\x06ReadOp\x12\x46\n\x0fvariant_read_op\x18\x01 \x01(\x0b\x32+.confidence.flags.resolver.v1.VariantReadOpH\x00\x12J\n\x11inclusion_read_op\x18\x02 \x01(\x0b\x32-.confidence.flags.resolver.v1.InclusionReadOpH\x00\x42\x04\n\x02op\"J\n\x15ReadOperationsRequest\x12\x31\n\x03ops\x18\x03 \x03(\x0b\x32$.confidence.flags.resolver.v1.ReadOp\"S\n\x0bVariantData\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x0c\n\x04rule\x18\x03 \x01(\t\x12\x0f\n\x07variant\x18\x04 \x01(\t\"K\n\rInclusionData\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x13\n\x0bis_included\x18\x03 \x01(\x08\"\xa4\x01\n\nReadResult\x12\x43\n\x0evariant_result\x18\x01 \x01(\x0b\x32).confidence.flags.resolver.v1.VariantDataH\x00\x12G\n\x10inclusion_result\x18\x02 \x01(\x0b\x32+.confidence.flags.resolver.v1.InclusionDataH\x00\x42\x08\n\x06result\"Q\n\x14ReadOperationsResult\x12\x39\n\x07results\x18\x01 \x03(\x0b\x32(.confidence.flags.resolver.v1.ReadResult2\xb2\x03\n\x19InternalFlagLoggerService\x12~\n\x13\x43lientWriteFlagLogs\x12\x32.confidence.flags.resolver.v1.WriteFlagLogsRequest\x1a\x33.confidence.flags.resolver.v1.WriteFlagLogsResponse\x12\x8a\x01\n\x1bWriteMaterializedOperations\x12\x34.confidence.flags.resolver.v1.WriteOperationsRequest\x1a\x33.confidence.flags.resolver.v1.WriteOperationsResult\"\x00\x12\x87\x01\n\x1aReadMaterializedOperations\x12\x33.confidence.flags.resolver.v1.ReadOperationsRequest\x1a\x32.confidence.flags.resolver.v1.ReadOperationsResult\"\x00\x42\xad\x01\n,com.spotify.confidence.sdk.flags.resolver.v1B\x10InternalApiProtoP\x01Zigithub.com/spotify/confidence-resolver/openfeature-provider/go/confidence/internal/proto/resolverinternalb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -47,55 +47,57 @@ _globals['_INGESTFLAGLOGSREQUEST']._serialized_start=494 _globals['_INGESTFLAGLOGSREQUEST']._serialized_end=604 _globals['_TELEMETRYDATA']._serialized_start=607 - _globals['_TELEMETRYDATA']._serialized_end=1012 - _globals['_TELEMETRYDATA_PROVIDERINITRATE']._serialized_start=836 - _globals['_TELEMETRYDATA_PROVIDERINITRATE']._serialized_end=1012 - _globals['_TELEMETRYDATA_PROVIDERINITRATE_LABELSENTRY']._serialized_start=961 - _globals['_TELEMETRYDATA_PROVIDERINITRATE_LABELSENTRY']._serialized_end=1006 - _globals['_CLIENTINFO']._serialized_start=1014 - _globals['_CLIENTINFO']._serialized_end=1117 - _globals['_FLAGASSIGNED']._serialized_start=1120 - _globals['_FLAGASSIGNED']._serialized_end=2052 - _globals['_FLAGASSIGNED_APPLIEDFLAG']._serialized_start=1291 - _globals['_FLAGASSIGNED_APPLIEDFLAG']._serialized_end=1736 - _globals['_FLAGASSIGNED_ASSIGNMENTINFO']._serialized_start=1738 - _globals['_FLAGASSIGNED_ASSIGNMENTINFO']._serialized_end=1788 - _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT']._serialized_start=1791 - _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT']._serialized_end=2052 - _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT_DEFAULTASSIGNMENTREASON']._serialized_start=1915 - _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT_DEFAULTASSIGNMENTREASON']._serialized_end=2052 - _globals['_FALLTHROUGHASSIGNMENT']._serialized_start=2054 - _globals['_FALLTHROUGHASSIGNMENT']._serialized_end=2169 - _globals['_CLIENTRESOLVEINFO']._serialized_start=2172 - _globals['_CLIENTRESOLVEINFO']._serialized_end=2523 - _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE']._serialized_start=2334 - _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE']._serialized_end=2523 - _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE_SCHEMAENTRY']._serialized_start=2478 - _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE_SCHEMAENTRY']._serialized_end=2523 - _globals['_FLAGRESOLVEINFO']._serialized_start=2526 - _globals['_FLAGRESOLVEINFO']._serialized_end=2707 - _globals['_FLAGRESOLVEINFO_VARIANTRESOLVEINFO']._serialized_start=2655 - _globals['_FLAGRESOLVEINFO_VARIANTRESOLVEINFO']._serialized_end=2707 - _globals['_WRITEOPERATIONSREQUEST']._serialized_start=2709 - _globals['_WRITEOPERATIONSREQUEST']._serialized_end=2802 - _globals['_WRITEOPERATIONSRESULT']._serialized_start=2804 - _globals['_WRITEOPERATIONSRESULT']._serialized_end=2827 - _globals['_VARIANTREADOP']._serialized_start=2829 - _globals['_VARIANTREADOP']._serialized_end=2897 - _globals['_INCLUSIONREADOP']._serialized_start=2899 - _globals['_INCLUSIONREADOP']._serialized_end=2955 - _globals['_READOP']._serialized_start=2958 - _globals['_READOP']._serialized_end=3120 - _globals['_READOPERATIONSREQUEST']._serialized_start=3122 - _globals['_READOPERATIONSREQUEST']._serialized_end=3196 - _globals['_VARIANTDATA']._serialized_start=3198 - _globals['_VARIANTDATA']._serialized_end=3281 - _globals['_INCLUSIONDATA']._serialized_start=3283 - _globals['_INCLUSIONDATA']._serialized_end=3358 - _globals['_READRESULT']._serialized_start=3361 - _globals['_READRESULT']._serialized_end=3525 - _globals['_READOPERATIONSRESULT']._serialized_start=3527 - _globals['_READOPERATIONSRESULT']._serialized_end=3608 - _globals['_INTERNALFLAGLOGGERSERVICE']._serialized_start=3611 - _globals['_INTERNALFLAGLOGGERSERVICE']._serialized_end=4045 + _globals['_TELEMETRYDATA']._serialized_end=1343 + _globals['_TELEMETRYDATA_APPLYDEDUPTELEMETRY']._serialized_start=1011 + _globals['_TELEMETRYDATA_APPLYDEDUPTELEMETRY']._serialized_end=1164 + _globals['_TELEMETRYDATA_PROVIDERINITRATE']._serialized_start=1167 + _globals['_TELEMETRYDATA_PROVIDERINITRATE']._serialized_end=1343 + _globals['_TELEMETRYDATA_PROVIDERINITRATE_LABELSENTRY']._serialized_start=1292 + _globals['_TELEMETRYDATA_PROVIDERINITRATE_LABELSENTRY']._serialized_end=1337 + _globals['_CLIENTINFO']._serialized_start=1345 + _globals['_CLIENTINFO']._serialized_end=1448 + _globals['_FLAGASSIGNED']._serialized_start=1451 + _globals['_FLAGASSIGNED']._serialized_end=2383 + _globals['_FLAGASSIGNED_APPLIEDFLAG']._serialized_start=1622 + _globals['_FLAGASSIGNED_APPLIEDFLAG']._serialized_end=2067 + _globals['_FLAGASSIGNED_ASSIGNMENTINFO']._serialized_start=2069 + _globals['_FLAGASSIGNED_ASSIGNMENTINFO']._serialized_end=2119 + _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT']._serialized_start=2122 + _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT']._serialized_end=2383 + _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT_DEFAULTASSIGNMENTREASON']._serialized_start=2246 + _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT_DEFAULTASSIGNMENTREASON']._serialized_end=2383 + _globals['_FALLTHROUGHASSIGNMENT']._serialized_start=2385 + _globals['_FALLTHROUGHASSIGNMENT']._serialized_end=2500 + _globals['_CLIENTRESOLVEINFO']._serialized_start=2503 + _globals['_CLIENTRESOLVEINFO']._serialized_end=2854 + _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE']._serialized_start=2665 + _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE']._serialized_end=2854 + _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE_SCHEMAENTRY']._serialized_start=2809 + _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE_SCHEMAENTRY']._serialized_end=2854 + _globals['_FLAGRESOLVEINFO']._serialized_start=2857 + _globals['_FLAGRESOLVEINFO']._serialized_end=3038 + _globals['_FLAGRESOLVEINFO_VARIANTRESOLVEINFO']._serialized_start=2986 + _globals['_FLAGRESOLVEINFO_VARIANTRESOLVEINFO']._serialized_end=3038 + _globals['_WRITEOPERATIONSREQUEST']._serialized_start=3040 + _globals['_WRITEOPERATIONSREQUEST']._serialized_end=3133 + _globals['_WRITEOPERATIONSRESULT']._serialized_start=3135 + _globals['_WRITEOPERATIONSRESULT']._serialized_end=3158 + _globals['_VARIANTREADOP']._serialized_start=3160 + _globals['_VARIANTREADOP']._serialized_end=3228 + _globals['_INCLUSIONREADOP']._serialized_start=3230 + _globals['_INCLUSIONREADOP']._serialized_end=3286 + _globals['_READOP']._serialized_start=3289 + _globals['_READOP']._serialized_end=3451 + _globals['_READOPERATIONSREQUEST']._serialized_start=3453 + _globals['_READOPERATIONSREQUEST']._serialized_end=3527 + _globals['_VARIANTDATA']._serialized_start=3529 + _globals['_VARIANTDATA']._serialized_end=3612 + _globals['_INCLUSIONDATA']._serialized_start=3614 + _globals['_INCLUSIONDATA']._serialized_end=3689 + _globals['_READRESULT']._serialized_start=3692 + _globals['_READRESULT']._serialized_end=3856 + _globals['_READOPERATIONSRESULT']._serialized_start=3858 + _globals['_READOPERATIONSRESULT']._serialized_end=3939 + _globals['_INTERNALFLAGLOGGERSERVICE']._serialized_start=3942 + _globals['_INTERNALFLAGLOGGERSERVICE']._serialized_end=4376 # @@protoc_insertion_point(module_scope) From 8fe91b9c7cfd0e31a78ba350076fa8337ac47e04 Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Wed, 2 Sep 2026 15:03:41 +0200 Subject: [PATCH 09/25] chore: sync WASM module for Go provider Docker-built WASM reflecting apply_dedup telemetry changes in confidence-resolver. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../assets/confidence_resolver.wasm | Bin 500838 -> 509841 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/openfeature-provider/go/confidence/internal/local_resolver/assets/confidence_resolver.wasm b/openfeature-provider/go/confidence/internal/local_resolver/assets/confidence_resolver.wasm index 4b70bf1928ee1e9119b593593c0c5e851c256070..34e909bd5ca71c8eab5615cba73b902ef55c8631 100755 GIT binary patch delta 93797 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 delta 85469 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�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 Cgj^~B From 04a1b32f03438c42d1684b0928313509851ec193 Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Wed, 2 Sep 2026 15:23:15 +0200 Subject: [PATCH 10/25] fix: prettier format ConfidenceServerProviderLocal.ts Co-Authored-By: Claude Opus 4.6 (1M context) --- openfeature-provider/js/src/ConfidenceServerProviderLocal.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts index fab566ae4..730cd1efe 100644 --- a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts +++ b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts @@ -573,8 +573,7 @@ export class ConfidenceServerProviderLocal implements Provider { private addFlushDeliveryTelemetry(encodedWriteFlagLogRequest: Uint8Array): Uint8Array { const hasFlush = this.flushSucceeded > 0 || this.flushFailed > 0; - const hasEvents = - this.eventsPublished > 0 || this.eventBatchesSucceeded > 0 || this.eventBatchesFailed > 0; + const hasEvents = this.eventsPublished > 0 || this.eventBatchesSucceeded > 0 || this.eventBatchesFailed > 0; if (!hasFlush && !hasEvents) { return encodedWriteFlagLogRequest; } From 7cd14694fb3cf2f96bb3705e010cc15918dffa20 Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Wed, 2 Sep 2026 15:29:03 +0200 Subject: [PATCH 11/25] fix(js): add missing fields to TelemetryData literal in addProviderInitTelemetry 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) --- .../js/src/ConfidenceServerProviderLocal.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts index 730cd1efe..889877ec7 100644 --- a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts +++ b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts @@ -605,7 +605,15 @@ export class ConfidenceServerProviderLocal implements Provider { private addProviderInitTelemetry(encodedWriteFlagLogRequest: Uint8Array): Uint8Array { const request = WriteFlagLogsRequest.decode(encodedWriteFlagLogRequest); if (!request.telemetryData) { - request.telemetryData = { resolverVersion: '', providerInitRate: [] }; + request.telemetryData = { + resolverVersion: '', + providerInitRate: [], + flushSucceeded: 0, + flushFailed: 0, + eventsPublished: 0, + eventBatchesSucceeded: 0, + eventBatchesFailed: 0, + }; } request.telemetryData.sdk = { id: SdkId.SDK_ID_JS_LOCAL_SERVER_PROVIDER, From 8cfdff42b07c3587c52e3750a9fefaf73b52c4f5 Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Wed, 2 Sep 2026 15:39:17 +0200 Subject: [PATCH 12/25] fix: add WASM-produced fields to provider proto to survive round-trips MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- .../proto/resolverinternal/internal_api.pb.go | 408 +++++++++++++++--- .../js/src/ConfidenceServerProviderLocal.ts | 15 +- .../flags/resolver/v1/internal_api.proto | 28 ++ .../flags/resolver/v1/internal_api_pb2.py | 116 ++--- 4 files changed, 442 insertions(+), 125 deletions(-) diff --git a/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go b/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go index a70cfba65..2064a5479 100644 --- a/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go +++ b/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go @@ -244,6 +244,12 @@ type TelemetryData struct { state protoimpl.MessageState `protogen:"open.v1"` // Information about the SDK/provider Sdk *resolver.Sdk `protobuf:"bytes,2,opt,name=sdk,proto3" json:"sdk,omitempty"` + // WASM-produced fields. Must be present so decode→encode round-trips + // in host SDKs preserve them (ts-proto/protobuf-js drop unknown fields). + ResolveLatency *TelemetryData_ResolveLatency `protobuf:"bytes,4,opt,name=resolve_latency,json=resolveLatency,proto3" json:"resolve_latency,omitempty"` + ResolveRate []*TelemetryData_ResolveRate `protobuf:"bytes,5,rep,name=resolve_rate,json=resolveRate,proto3" json:"resolve_rate,omitempty"` + StateAge *TelemetryData_StateAge `protobuf:"bytes,6,opt,name=state_age,json=stateAge,proto3" json:"state_age,omitempty"` + MemoryBytes uint64 `protobuf:"varint,7,opt,name=memory_bytes,json=memoryBytes,proto3" json:"memory_bytes,omitempty"` // Version of the embedded resolver (e.g. "0.14.0"). // This must be preserved when providers decode and re-encode telemetry. ResolverVersion string `protobuf:"bytes,8,opt,name=resolver_version,json=resolverVersion,proto3" json:"resolver_version,omitempty"` @@ -298,6 +304,34 @@ func (x *TelemetryData) GetSdk() *resolver.Sdk { return nil } +func (x *TelemetryData) GetResolveLatency() *TelemetryData_ResolveLatency { + if x != nil { + return x.ResolveLatency + } + return nil +} + +func (x *TelemetryData) GetResolveRate() []*TelemetryData_ResolveRate { + if x != nil { + return x.ResolveRate + } + return nil +} + +func (x *TelemetryData) GetStateAge() *TelemetryData_StateAge { + if x != nil { + return x.StateAge + } + return nil +} + +func (x *TelemetryData) GetMemoryBytes() uint64 { + if x != nil { + return x.MemoryBytes + } + return 0 +} + func (x *TelemetryData) GetResolverVersion() string { if x != nil { return x.ResolverVersion @@ -1232,6 +1266,222 @@ func (x *ReadOperationsResult) GetResults() []*ReadResult { return nil } +type TelemetryData_ResolveLatency struct { + state protoimpl.MessageState `protogen:"open.v1"` + Sum uint32 `protobuf:"varint,1,opt,name=sum,proto3" json:"sum,omitempty"` + Count uint32 `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"` + Buckets []*TelemetryData_BucketSpan `protobuf:"bytes,3,rep,name=buckets,proto3" json:"buckets,omitempty"` + LnRatio float64 `protobuf:"fixed64,4,opt,name=ln_ratio,json=lnRatio,proto3" json:"ln_ratio,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TelemetryData_ResolveLatency) Reset() { + *x = TelemetryData_ResolveLatency{} + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TelemetryData_ResolveLatency) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TelemetryData_ResolveLatency) ProtoMessage() {} + +func (x *TelemetryData_ResolveLatency) ProtoReflect() protoreflect.Message { + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TelemetryData_ResolveLatency.ProtoReflect.Descriptor instead. +func (*TelemetryData_ResolveLatency) Descriptor() ([]byte, []int) { + return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 0} +} + +func (x *TelemetryData_ResolveLatency) GetSum() uint32 { + if x != nil { + return x.Sum + } + return 0 +} + +func (x *TelemetryData_ResolveLatency) GetCount() uint32 { + if x != nil { + return x.Count + } + return 0 +} + +func (x *TelemetryData_ResolveLatency) GetBuckets() []*TelemetryData_BucketSpan { + if x != nil { + return x.Buckets + } + return nil +} + +func (x *TelemetryData_ResolveLatency) GetLnRatio() float64 { + if x != nil { + return x.LnRatio + } + return 0 +} + +type TelemetryData_ResolveRate struct { + state protoimpl.MessageState `protogen:"open.v1"` + Count uint32 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` + Reason uint32 `protobuf:"varint,2,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TelemetryData_ResolveRate) Reset() { + *x = TelemetryData_ResolveRate{} + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TelemetryData_ResolveRate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TelemetryData_ResolveRate) ProtoMessage() {} + +func (x *TelemetryData_ResolveRate) ProtoReflect() protoreflect.Message { + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[20] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TelemetryData_ResolveRate.ProtoReflect.Descriptor instead. +func (*TelemetryData_ResolveRate) Descriptor() ([]byte, []int) { + return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 1} +} + +func (x *TelemetryData_ResolveRate) GetCount() uint32 { + if x != nil { + return x.Count + } + return 0 +} + +func (x *TelemetryData_ResolveRate) GetReason() uint32 { + if x != nil { + return x.Reason + } + return 0 +} + +type TelemetryData_StateAge struct { + state protoimpl.MessageState `protogen:"open.v1"` + LastStateUpdate uint64 `protobuf:"varint,1,opt,name=last_state_update,json=lastStateUpdate,proto3" json:"last_state_update,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TelemetryData_StateAge) Reset() { + *x = TelemetryData_StateAge{} + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TelemetryData_StateAge) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TelemetryData_StateAge) ProtoMessage() {} + +func (x *TelemetryData_StateAge) ProtoReflect() protoreflect.Message { + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[21] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TelemetryData_StateAge.ProtoReflect.Descriptor instead. +func (*TelemetryData_StateAge) Descriptor() ([]byte, []int) { + return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 2} +} + +func (x *TelemetryData_StateAge) GetLastStateUpdate() uint64 { + if x != nil { + return x.LastStateUpdate + } + return 0 +} + +type TelemetryData_BucketSpan struct { + state protoimpl.MessageState `protogen:"open.v1"` + Offset int32 `protobuf:"varint,1,opt,name=offset,proto3" json:"offset,omitempty"` + Counts []uint32 `protobuf:"varint,2,rep,packed,name=counts,proto3" json:"counts,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TelemetryData_BucketSpan) Reset() { + *x = TelemetryData_BucketSpan{} + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TelemetryData_BucketSpan) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TelemetryData_BucketSpan) ProtoMessage() {} + +func (x *TelemetryData_BucketSpan) ProtoReflect() protoreflect.Message { + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[22] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TelemetryData_BucketSpan.ProtoReflect.Descriptor instead. +func (*TelemetryData_BucketSpan) Descriptor() ([]byte, []int) { + return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 3} +} + +func (x *TelemetryData_BucketSpan) GetOffset() int32 { + if x != nil { + return x.Offset + } + return 0 +} + +func (x *TelemetryData_BucketSpan) GetCounts() []uint32 { + if x != nil { + return x.Counts + } + return nil +} + type TelemetryData_ApplyDedupTelemetry struct { state protoimpl.MessageState `protogen:"open.v1"` AppliesTotal uint32 `protobuf:"varint,1,opt,name=applies_total,json=appliesTotal,proto3" json:"applies_total,omitempty"` @@ -1246,7 +1496,7 @@ type TelemetryData_ApplyDedupTelemetry struct { func (x *TelemetryData_ApplyDedupTelemetry) Reset() { *x = TelemetryData_ApplyDedupTelemetry{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[19] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1258,7 +1508,7 @@ func (x *TelemetryData_ApplyDedupTelemetry) String() string { func (*TelemetryData_ApplyDedupTelemetry) ProtoMessage() {} func (x *TelemetryData_ApplyDedupTelemetry) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[19] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1271,7 +1521,7 @@ func (x *TelemetryData_ApplyDedupTelemetry) ProtoReflect() protoreflect.Message // Deprecated: Use TelemetryData_ApplyDedupTelemetry.ProtoReflect.Descriptor instead. func (*TelemetryData_ApplyDedupTelemetry) Descriptor() ([]byte, []int) { - return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 0} + return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 4} } func (x *TelemetryData_ApplyDedupTelemetry) GetAppliesTotal() uint32 { @@ -1326,7 +1576,7 @@ type TelemetryData_ProviderInitRate struct { func (x *TelemetryData_ProviderInitRate) Reset() { *x = TelemetryData_ProviderInitRate{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[20] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1338,7 +1588,7 @@ func (x *TelemetryData_ProviderInitRate) String() string { func (*TelemetryData_ProviderInitRate) ProtoMessage() {} func (x *TelemetryData_ProviderInitRate) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[20] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1351,7 +1601,7 @@ func (x *TelemetryData_ProviderInitRate) ProtoReflect() protoreflect.Message { // Deprecated: Use TelemetryData_ProviderInitRate.ProtoReflect.Descriptor instead. func (*TelemetryData_ProviderInitRate) Descriptor() ([]byte, []int) { - return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 1} + return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 5} } func (x *TelemetryData_ProviderInitRate) GetCount() uint32 { @@ -1388,7 +1638,7 @@ type FlagAssigned_AppliedFlag struct { func (x *FlagAssigned_AppliedFlag) Reset() { *x = FlagAssigned_AppliedFlag{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[22] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1400,7 +1650,7 @@ func (x *FlagAssigned_AppliedFlag) String() string { func (*FlagAssigned_AppliedFlag) ProtoMessage() {} func (x *FlagAssigned_AppliedFlag) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[22] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1516,7 +1766,7 @@ type FlagAssigned_AssignmentInfo struct { func (x *FlagAssigned_AssignmentInfo) Reset() { *x = FlagAssigned_AssignmentInfo{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[23] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1528,7 +1778,7 @@ func (x *FlagAssigned_AssignmentInfo) String() string { func (*FlagAssigned_AssignmentInfo) ProtoMessage() {} func (x *FlagAssigned_AssignmentInfo) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[23] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1567,7 +1817,7 @@ type FlagAssigned_DefaultAssignment struct { func (x *FlagAssigned_DefaultAssignment) Reset() { *x = FlagAssigned_DefaultAssignment{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[24] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1579,7 +1829,7 @@ func (x *FlagAssigned_DefaultAssignment) String() string { func (*FlagAssigned_DefaultAssignment) ProtoMessage() {} func (x *FlagAssigned_DefaultAssignment) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[24] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1613,7 +1863,7 @@ type ClientResolveInfo_EvaluationContextSchemaInstance struct { func (x *ClientResolveInfo_EvaluationContextSchemaInstance) Reset() { *x = ClientResolveInfo_EvaluationContextSchemaInstance{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[25] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1625,7 +1875,7 @@ func (x *ClientResolveInfo_EvaluationContextSchemaInstance) String() string { func (*ClientResolveInfo_EvaluationContextSchemaInstance) ProtoMessage() {} func (x *ClientResolveInfo_EvaluationContextSchemaInstance) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[25] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1661,7 +1911,7 @@ type FlagResolveInfo_VariantResolveInfo struct { func (x *FlagResolveInfo_VariantResolveInfo) Reset() { *x = FlagResolveInfo_VariantResolveInfo{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[27] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1673,7 +1923,7 @@ func (x *FlagResolveInfo_VariantResolveInfo) String() string { func (*FlagResolveInfo_VariantResolveInfo) ProtoMessage() {} func (x *FlagResolveInfo_VariantResolveInfo) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[27] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1717,9 +1967,13 @@ const file_confidence_flags_resolver_v1_internal_api_proto_rawDesc = "" + "\x15IngestFlagLogsRequest\x12\x1d\n" + "\n" + "account_id\x18\x01 \x01(\tR\taccountId\x12H\n" + - "\x05batch\x18\x02 \x01(\v22.confidence.flags.resolver.v1.WriteFlagLogsRequestR\x05batch\"\xd6\a\n" + + "\x05batch\x18\x02 \x01(\v22.confidence.flags.resolver.v1.WriteFlagLogsRequestR\x05batch\"\xe8\f\n" + "\rTelemetryData\x123\n" + - "\x03sdk\x18\x02 \x01(\v2!.confidence.flags.resolver.v1.SdkR\x03sdk\x12)\n" + + "\x03sdk\x18\x02 \x01(\v2!.confidence.flags.resolver.v1.SdkR\x03sdk\x12c\n" + + "\x0fresolve_latency\x18\x04 \x01(\v2:.confidence.flags.resolver.v1.TelemetryData.ResolveLatencyR\x0eresolveLatency\x12Z\n" + + "\fresolve_rate\x18\x05 \x03(\v27.confidence.flags.resolver.v1.TelemetryData.ResolveRateR\vresolveRate\x12Q\n" + + "\tstate_age\x18\x06 \x01(\v24.confidence.flags.resolver.v1.TelemetryData.StateAgeR\bstateAge\x12!\n" + + "\fmemory_bytes\x18\a \x01(\x04R\vmemoryBytes\x12)\n" + "\x10resolver_version\x18\b \x01(\tR\x0fresolverVersion\x12j\n" + "\x12provider_init_rate\x18\t \x03(\v2<.confidence.flags.resolver.v1.TelemetryData.ProviderInitRateR\x10providerInitRate\x12`\n" + "\vapply_dedup\x18\n" + @@ -1729,7 +1983,21 @@ const file_confidence_flags_resolver_v1_internal_api_proto_rawDesc = "" + "\fflush_failed\x18\f \x01(\rR\vflushFailed\x12)\n" + "\x10events_published\x18\r \x01(\rR\x0feventsPublished\x126\n" + "\x17event_batches_succeeded\x18\x0e \x01(\rR\x15eventBatchesSucceeded\x120\n" + - "\x14event_batches_failed\x18\x0f \x01(\rR\x12eventBatchesFailed\x1a\xe7\x01\n" + + "\x14event_batches_failed\x18\x0f \x01(\rR\x12eventBatchesFailed\x1a\xa5\x01\n" + + "\x0eResolveLatency\x12\x10\n" + + "\x03sum\x18\x01 \x01(\rR\x03sum\x12\x14\n" + + "\x05count\x18\x02 \x01(\rR\x05count\x12P\n" + + "\abuckets\x18\x03 \x03(\v26.confidence.flags.resolver.v1.TelemetryData.BucketSpanR\abuckets\x12\x19\n" + + "\bln_ratio\x18\x04 \x01(\x01R\alnRatio\x1a;\n" + + "\vResolveRate\x12\x14\n" + + "\x05count\x18\x01 \x01(\rR\x05count\x12\x16\n" + + "\x06reason\x18\x02 \x01(\rR\x06reason\x1a6\n" + + "\bStateAge\x12*\n" + + "\x11last_state_update\x18\x01 \x01(\x04R\x0flastStateUpdate\x1a<\n" + + "\n" + + "BucketSpan\x12\x16\n" + + "\x06offset\x18\x01 \x01(\x05R\x06offset\x12\x16\n" + + "\x06counts\x18\x02 \x03(\rR\x06counts\x1a\xe7\x01\n" + "\x13ApplyDedupTelemetry\x12#\n" + "\rapplies_total\x18\x01 \x01(\rR\fappliesTotal\x12'\n" + "\x0fapplies_deduped\x18\x02 \x01(\rR\x0eappliesDeduped\x12,\n" + @@ -1850,7 +2118,7 @@ func file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP() []byte { } var file_confidence_flags_resolver_v1_internal_api_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_confidence_flags_resolver_v1_internal_api_proto_msgTypes = make([]protoimpl.MessageInfo, 28) +var file_confidence_flags_resolver_v1_internal_api_proto_msgTypes = make([]protoimpl.MessageInfo, 32) var file_confidence_flags_resolver_v1_internal_api_proto_goTypes = []any{ (FlagAssigned_DefaultAssignment_DefaultAssignmentReason)(0), // 0: confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.DefaultAssignmentReason (*WriteFlagLogsRequest)(nil), // 1: confidence.flags.resolver.v1.WriteFlagLogsRequest @@ -1872,17 +2140,21 @@ var file_confidence_flags_resolver_v1_internal_api_proto_goTypes = []any{ (*InclusionData)(nil), // 17: confidence.flags.resolver.v1.InclusionData (*ReadResult)(nil), // 18: confidence.flags.resolver.v1.ReadResult (*ReadOperationsResult)(nil), // 19: confidence.flags.resolver.v1.ReadOperationsResult - (*TelemetryData_ApplyDedupTelemetry)(nil), // 20: confidence.flags.resolver.v1.TelemetryData.ApplyDedupTelemetry - (*TelemetryData_ProviderInitRate)(nil), // 21: confidence.flags.resolver.v1.TelemetryData.ProviderInitRate - nil, // 22: confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry - (*FlagAssigned_AppliedFlag)(nil), // 23: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag - (*FlagAssigned_AssignmentInfo)(nil), // 24: confidence.flags.resolver.v1.FlagAssigned.AssignmentInfo - (*FlagAssigned_DefaultAssignment)(nil), // 25: confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment - (*ClientResolveInfo_EvaluationContextSchemaInstance)(nil), // 26: confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance - nil, // 27: confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry - (*FlagResolveInfo_VariantResolveInfo)(nil), // 28: confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo - (*resolver.Sdk)(nil), // 29: confidence.flags.resolver.v1.Sdk - (*timestamppb.Timestamp)(nil), // 30: google.protobuf.Timestamp + (*TelemetryData_ResolveLatency)(nil), // 20: confidence.flags.resolver.v1.TelemetryData.ResolveLatency + (*TelemetryData_ResolveRate)(nil), // 21: confidence.flags.resolver.v1.TelemetryData.ResolveRate + (*TelemetryData_StateAge)(nil), // 22: confidence.flags.resolver.v1.TelemetryData.StateAge + (*TelemetryData_BucketSpan)(nil), // 23: confidence.flags.resolver.v1.TelemetryData.BucketSpan + (*TelemetryData_ApplyDedupTelemetry)(nil), // 24: confidence.flags.resolver.v1.TelemetryData.ApplyDedupTelemetry + (*TelemetryData_ProviderInitRate)(nil), // 25: confidence.flags.resolver.v1.TelemetryData.ProviderInitRate + nil, // 26: confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry + (*FlagAssigned_AppliedFlag)(nil), // 27: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag + (*FlagAssigned_AssignmentInfo)(nil), // 28: confidence.flags.resolver.v1.FlagAssigned.AssignmentInfo + (*FlagAssigned_DefaultAssignment)(nil), // 29: confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment + (*ClientResolveInfo_EvaluationContextSchemaInstance)(nil), // 30: confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance + nil, // 31: confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry + (*FlagResolveInfo_VariantResolveInfo)(nil), // 32: confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo + (*resolver.Sdk)(nil), // 33: confidence.flags.resolver.v1.Sdk + (*timestamppb.Timestamp)(nil), // 34: google.protobuf.Timestamp } var file_confidence_flags_resolver_v1_internal_api_proto_depIdxs = []int32{ 6, // 0: confidence.flags.resolver.v1.WriteFlagLogsRequest.flag_assigned:type_name -> confidence.flags.resolver.v1.FlagAssigned @@ -1890,39 +2162,43 @@ var file_confidence_flags_resolver_v1_internal_api_proto_depIdxs = []int32{ 8, // 2: confidence.flags.resolver.v1.WriteFlagLogsRequest.client_resolve_info:type_name -> confidence.flags.resolver.v1.ClientResolveInfo 9, // 3: confidence.flags.resolver.v1.WriteFlagLogsRequest.flag_resolve_info:type_name -> confidence.flags.resolver.v1.FlagResolveInfo 1, // 4: confidence.flags.resolver.v1.IngestFlagLogsRequest.batch:type_name -> confidence.flags.resolver.v1.WriteFlagLogsRequest - 29, // 5: confidence.flags.resolver.v1.TelemetryData.sdk:type_name -> confidence.flags.resolver.v1.Sdk - 21, // 6: confidence.flags.resolver.v1.TelemetryData.provider_init_rate:type_name -> confidence.flags.resolver.v1.TelemetryData.ProviderInitRate - 20, // 7: confidence.flags.resolver.v1.TelemetryData.apply_dedup:type_name -> confidence.flags.resolver.v1.TelemetryData.ApplyDedupTelemetry - 29, // 8: confidence.flags.resolver.v1.ClientInfo.sdk:type_name -> confidence.flags.resolver.v1.Sdk - 5, // 9: confidence.flags.resolver.v1.FlagAssigned.client_info:type_name -> confidence.flags.resolver.v1.ClientInfo - 23, // 10: confidence.flags.resolver.v1.FlagAssigned.flags:type_name -> confidence.flags.resolver.v1.FlagAssigned.AppliedFlag - 26, // 11: confidence.flags.resolver.v1.ClientResolveInfo.schema:type_name -> confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance - 28, // 12: confidence.flags.resolver.v1.FlagResolveInfo.variant_resolve_info:type_name -> confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo - 16, // 13: confidence.flags.resolver.v1.WriteOperationsRequest.store_variant_op:type_name -> confidence.flags.resolver.v1.VariantData - 12, // 14: confidence.flags.resolver.v1.ReadOp.variant_read_op:type_name -> confidence.flags.resolver.v1.VariantReadOp - 13, // 15: confidence.flags.resolver.v1.ReadOp.inclusion_read_op:type_name -> confidence.flags.resolver.v1.InclusionReadOp - 14, // 16: confidence.flags.resolver.v1.ReadOperationsRequest.ops:type_name -> confidence.flags.resolver.v1.ReadOp - 16, // 17: confidence.flags.resolver.v1.ReadResult.variant_result:type_name -> confidence.flags.resolver.v1.VariantData - 17, // 18: confidence.flags.resolver.v1.ReadResult.inclusion_result:type_name -> confidence.flags.resolver.v1.InclusionData - 18, // 19: confidence.flags.resolver.v1.ReadOperationsResult.results:type_name -> confidence.flags.resolver.v1.ReadResult - 22, // 20: confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.labels:type_name -> confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry - 24, // 21: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.assignment_info:type_name -> confidence.flags.resolver.v1.FlagAssigned.AssignmentInfo - 25, // 22: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.default_assignment:type_name -> confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment - 7, // 23: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.fallthrough_assignments:type_name -> confidence.flags.resolver.v1.FallthroughAssignment - 30, // 24: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.apply_time:type_name -> google.protobuf.Timestamp - 0, // 25: confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.reason:type_name -> confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.DefaultAssignmentReason - 27, // 26: confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.schema:type_name -> confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry - 1, // 27: confidence.flags.resolver.v1.InternalFlagLoggerService.ClientWriteFlagLogs:input_type -> confidence.flags.resolver.v1.WriteFlagLogsRequest - 10, // 28: confidence.flags.resolver.v1.InternalFlagLoggerService.WriteMaterializedOperations:input_type -> confidence.flags.resolver.v1.WriteOperationsRequest - 15, // 29: confidence.flags.resolver.v1.InternalFlagLoggerService.ReadMaterializedOperations:input_type -> confidence.flags.resolver.v1.ReadOperationsRequest - 2, // 30: confidence.flags.resolver.v1.InternalFlagLoggerService.ClientWriteFlagLogs:output_type -> confidence.flags.resolver.v1.WriteFlagLogsResponse - 11, // 31: confidence.flags.resolver.v1.InternalFlagLoggerService.WriteMaterializedOperations:output_type -> confidence.flags.resolver.v1.WriteOperationsResult - 19, // 32: confidence.flags.resolver.v1.InternalFlagLoggerService.ReadMaterializedOperations:output_type -> confidence.flags.resolver.v1.ReadOperationsResult - 30, // [30:33] is the sub-list for method output_type - 27, // [27:30] is the sub-list for method input_type - 27, // [27:27] is the sub-list for extension type_name - 27, // [27:27] is the sub-list for extension extendee - 0, // [0:27] is the sub-list for field type_name + 33, // 5: confidence.flags.resolver.v1.TelemetryData.sdk:type_name -> confidence.flags.resolver.v1.Sdk + 20, // 6: confidence.flags.resolver.v1.TelemetryData.resolve_latency:type_name -> confidence.flags.resolver.v1.TelemetryData.ResolveLatency + 21, // 7: confidence.flags.resolver.v1.TelemetryData.resolve_rate:type_name -> confidence.flags.resolver.v1.TelemetryData.ResolveRate + 22, // 8: confidence.flags.resolver.v1.TelemetryData.state_age:type_name -> confidence.flags.resolver.v1.TelemetryData.StateAge + 25, // 9: confidence.flags.resolver.v1.TelemetryData.provider_init_rate:type_name -> confidence.flags.resolver.v1.TelemetryData.ProviderInitRate + 24, // 10: confidence.flags.resolver.v1.TelemetryData.apply_dedup:type_name -> confidence.flags.resolver.v1.TelemetryData.ApplyDedupTelemetry + 33, // 11: confidence.flags.resolver.v1.ClientInfo.sdk:type_name -> confidence.flags.resolver.v1.Sdk + 5, // 12: confidence.flags.resolver.v1.FlagAssigned.client_info:type_name -> confidence.flags.resolver.v1.ClientInfo + 27, // 13: confidence.flags.resolver.v1.FlagAssigned.flags:type_name -> confidence.flags.resolver.v1.FlagAssigned.AppliedFlag + 30, // 14: confidence.flags.resolver.v1.ClientResolveInfo.schema:type_name -> confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance + 32, // 15: confidence.flags.resolver.v1.FlagResolveInfo.variant_resolve_info:type_name -> confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo + 16, // 16: confidence.flags.resolver.v1.WriteOperationsRequest.store_variant_op:type_name -> confidence.flags.resolver.v1.VariantData + 12, // 17: confidence.flags.resolver.v1.ReadOp.variant_read_op:type_name -> confidence.flags.resolver.v1.VariantReadOp + 13, // 18: confidence.flags.resolver.v1.ReadOp.inclusion_read_op:type_name -> confidence.flags.resolver.v1.InclusionReadOp + 14, // 19: confidence.flags.resolver.v1.ReadOperationsRequest.ops:type_name -> confidence.flags.resolver.v1.ReadOp + 16, // 20: confidence.flags.resolver.v1.ReadResult.variant_result:type_name -> confidence.flags.resolver.v1.VariantData + 17, // 21: confidence.flags.resolver.v1.ReadResult.inclusion_result:type_name -> confidence.flags.resolver.v1.InclusionData + 18, // 22: confidence.flags.resolver.v1.ReadOperationsResult.results:type_name -> confidence.flags.resolver.v1.ReadResult + 23, // 23: confidence.flags.resolver.v1.TelemetryData.ResolveLatency.buckets:type_name -> confidence.flags.resolver.v1.TelemetryData.BucketSpan + 26, // 24: confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.labels:type_name -> confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry + 28, // 25: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.assignment_info:type_name -> confidence.flags.resolver.v1.FlagAssigned.AssignmentInfo + 29, // 26: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.default_assignment:type_name -> confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment + 7, // 27: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.fallthrough_assignments:type_name -> confidence.flags.resolver.v1.FallthroughAssignment + 34, // 28: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.apply_time:type_name -> google.protobuf.Timestamp + 0, // 29: confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.reason:type_name -> confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.DefaultAssignmentReason + 31, // 30: confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.schema:type_name -> confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry + 1, // 31: confidence.flags.resolver.v1.InternalFlagLoggerService.ClientWriteFlagLogs:input_type -> confidence.flags.resolver.v1.WriteFlagLogsRequest + 10, // 32: confidence.flags.resolver.v1.InternalFlagLoggerService.WriteMaterializedOperations:input_type -> confidence.flags.resolver.v1.WriteOperationsRequest + 15, // 33: confidence.flags.resolver.v1.InternalFlagLoggerService.ReadMaterializedOperations:input_type -> confidence.flags.resolver.v1.ReadOperationsRequest + 2, // 34: confidence.flags.resolver.v1.InternalFlagLoggerService.ClientWriteFlagLogs:output_type -> confidence.flags.resolver.v1.WriteFlagLogsResponse + 11, // 35: confidence.flags.resolver.v1.InternalFlagLoggerService.WriteMaterializedOperations:output_type -> confidence.flags.resolver.v1.WriteOperationsResult + 19, // 36: confidence.flags.resolver.v1.InternalFlagLoggerService.ReadMaterializedOperations:output_type -> confidence.flags.resolver.v1.ReadOperationsResult + 34, // [34:37] is the sub-list for method output_type + 31, // [31:34] is the sub-list for method input_type + 31, // [31:31] is the sub-list for extension type_name + 31, // [31:31] is the sub-list for extension extendee + 0, // [0:31] is the sub-list for field type_name } func init() { file_confidence_flags_resolver_v1_internal_api_proto_init() } @@ -1938,7 +2214,7 @@ func file_confidence_flags_resolver_v1_internal_api_proto_init() { (*ReadResult_VariantResult)(nil), (*ReadResult_InclusionResult)(nil), } - file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[22].OneofWrappers = []any{ + file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[26].OneofWrappers = []any{ (*FlagAssigned_AppliedFlag_AssignmentInfo)(nil), (*FlagAssigned_AppliedFlag_DefaultAssignment)(nil), } @@ -1948,7 +2224,7 @@ func file_confidence_flags_resolver_v1_internal_api_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_confidence_flags_resolver_v1_internal_api_proto_rawDesc), len(file_confidence_flags_resolver_v1_internal_api_proto_rawDesc)), NumEnums: 1, - NumMessages: 28, + NumMessages: 32, NumExtensions: 0, NumServices: 1, }, diff --git a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts index 889877ec7..1e9b3c593 100644 --- a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts +++ b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts @@ -582,6 +582,8 @@ export class ConfidenceServerProviderLocal implements Provider { request.telemetryData = { resolverVersion: '', providerInitRate: [], + resolveRate: [], + memoryBytes: 0, flushSucceeded: 0, flushFailed: 0, eventsPublished: 0, @@ -589,11 +591,12 @@ export class ConfidenceServerProviderLocal implements Provider { eventBatchesFailed: 0, }; } - request.telemetryData.flushSucceeded = this.flushSucceeded; - request.telemetryData.flushFailed = this.flushFailed; - request.telemetryData.eventsPublished = this.eventsPublished; - request.telemetryData.eventBatchesSucceeded = this.eventBatchesSucceeded; - request.telemetryData.eventBatchesFailed = this.eventBatchesFailed; + const td = request.telemetryData!; + td.flushSucceeded = this.flushSucceeded; + td.flushFailed = this.flushFailed; + td.eventsPublished = this.eventsPublished; + td.eventBatchesSucceeded = this.eventBatchesSucceeded; + td.eventBatchesFailed = this.eventBatchesFailed; this.flushSucceeded = 0; this.flushFailed = 0; this.eventsPublished = 0; @@ -608,6 +611,8 @@ export class ConfidenceServerProviderLocal implements Provider { request.telemetryData = { resolverVersion: '', providerInitRate: [], + resolveRate: [], + memoryBytes: 0, flushSucceeded: 0, flushFailed: 0, eventsPublished: 0, diff --git a/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto b/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto index c51d1f3e2..5ea5b0e21 100644 --- a/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto +++ b/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto @@ -51,6 +51,13 @@ message TelemetryData { // Information about the SDK/provider Sdk sdk = 2; + // WASM-produced fields. Must be present so decode→encode round-trips + // in host SDKs preserve them (ts-proto/protobuf-js drop unknown fields). + ResolveLatency resolve_latency = 4; + repeated ResolveRate resolve_rate = 5; + StateAge state_age = 6; + uint64 memory_bytes = 7; + // Version of the embedded resolver (e.g. "0.14.0"). // This must be preserved when providers decode and re-encode telemetry. string resolver_version = 8; @@ -69,6 +76,27 @@ message TelemetryData { uint32 event_batches_succeeded = 14; uint32 event_batches_failed = 15; + message ResolveLatency { + uint32 sum = 1; + uint32 count = 2; + repeated BucketSpan buckets = 3; + double ln_ratio = 4; + } + + message ResolveRate { + uint32 count = 1; + uint32 reason = 2; + } + + message StateAge { + uint64 last_state_update = 1; + } + + message BucketSpan { + int32 offset = 1; + repeated uint32 counts = 2; + } + message ApplyDedupTelemetry { uint32 applies_total = 1; uint32 applies_deduped = 2; diff --git a/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2.py b/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2.py index ffaaf31ea..25154a728 100644 --- a/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2.py +++ b/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2.py @@ -26,7 +26,7 @@ from confidence.flags.resolver.v1 import types_pb2 as confidence_dot_flags_dot_resolver_dot_v1_dot_types__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n/confidence/flags/resolver/v1/internal_api.proto\x12\x1c\x63onfidence.flags.resolver.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a(confidence/flags/resolver/v1/types.proto\"\xb6\x02\n\x14WriteFlagLogsRequest\x12\x41\n\rflag_assigned\x18\x01 \x03(\x0b\x32*.confidence.flags.resolver.v1.FlagAssigned\x12\x43\n\x0etelemetry_data\x18\x02 \x01(\x0b\x32+.confidence.flags.resolver.v1.TelemetryData\x12L\n\x13\x63lient_resolve_info\x18\x03 \x03(\x0b\x32/.confidence.flags.resolver.v1.ClientResolveInfo\x12H\n\x11\x66lag_resolve_info\x18\x04 \x03(\x0b\x32-.confidence.flags.resolver.v1.FlagResolveInfo\"\x17\n\x15WriteFlagLogsResponse\"n\n\x15IngestFlagLogsRequest\x12\x12\n\naccount_id\x18\x01 \x01(\t\x12\x41\n\x05\x62\x61tch\x18\x02 \x01(\x0b\x32\x32.confidence.flags.resolver.v1.WriteFlagLogsRequest\"\xe0\x05\n\rTelemetryData\x12.\n\x03sdk\x18\x02 \x01(\x0b\x32!.confidence.flags.resolver.v1.Sdk\x12\x18\n\x10resolver_version\x18\x08 \x01(\t\x12X\n\x12provider_init_rate\x18\t \x03(\x0b\x32<.confidence.flags.resolver.v1.TelemetryData.ProviderInitRate\x12T\n\x0b\x61pply_dedup\x18\n \x01(\x0b\x32?.confidence.flags.resolver.v1.TelemetryData.ApplyDedupTelemetry\x12\x17\n\x0f\x66lush_succeeded\x18\x0b \x01(\r\x12\x14\n\x0c\x66lush_failed\x18\x0c \x01(\r\x12\x18\n\x10\x65vents_published\x18\r \x01(\r\x12\x1f\n\x17\x65vent_batches_succeeded\x18\x0e \x01(\r\x12\x1c\n\x14\x65vent_batches_failed\x18\x0f \x01(\r\x1a\x99\x01\n\x13\x41pplyDedupTelemetry\x12\x15\n\rapplies_total\x18\x01 \x01(\r\x12\x17\n\x0f\x61pplies_deduped\x18\x02 \x01(\r\x12\x1a\n\x12\x61pplies_not_cached\x18\x03 \x01(\r\x12\x0e\n\x06sweeps\x18\x04 \x01(\r\x12\x10\n\x08map_size\x18\x05 \x01(\r\x12\x14\n\x0cmap_capacity\x18\x06 \x01(\r\x1a\xb0\x01\n\x10ProviderInitRate\x12\r\n\x05\x63ount\x18\x01 \x01(\r\x12X\n\x06labels\x18\x03 \x03(\x0b\x32H.confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01J\x04\x08\x02\x10\x03\"g\n\nClientInfo\x12\x0e\n\x06\x63lient\x18\x01 \x01(\t\x12\x19\n\x11\x63lient_credential\x18\x02 \x01(\t\x12.\n\x03sdk\x18\x03 \x01(\x0b\x32!.confidence.flags.resolver.v1.Sdk\"\xa4\x07\n\x0c\x46lagAssigned\x12\x12\n\nresolve_id\x18\n \x01(\t\x12=\n\x0b\x63lient_info\x18\x03 \x01(\x0b\x32(.confidence.flags.resolver.v1.ClientInfo\x12\x45\n\x05\x66lags\x18\x0f \x03(\x0b\x32\x36.confidence.flags.resolver.v1.FlagAssigned.AppliedFlag\x1a\xbd\x03\n\x0b\x41ppliedFlag\x12\x0c\n\x04\x66lag\x18\x01 \x01(\t\x12\x15\n\rtargeting_key\x18\x02 \x01(\t\x12\x1e\n\x16targeting_key_selector\x18\x03 \x01(\t\x12T\n\x0f\x61ssignment_info\x18\x04 \x01(\x0b\x32\x39.confidence.flags.resolver.v1.FlagAssigned.AssignmentInfoH\x00\x12Z\n\x12\x64\x65\x66\x61ult_assignment\x18\x05 \x01(\x0b\x32<.confidence.flags.resolver.v1.FlagAssigned.DefaultAssignmentH\x00\x12\x15\n\rassignment_id\x18\x06 \x01(\t\x12\x0c\n\x04rule\x18\x07 \x01(\t\x12T\n\x17\x66\x61llthrough_assignments\x18\x08 \x03(\x0b\x32\x33.confidence.flags.resolver.v1.FallthroughAssignment\x12.\n\napply_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x0c\n\nassignment\x1a\x32\n\x0e\x41ssignmentInfo\x12\x0f\n\x07segment\x18\x01 \x01(\t\x12\x0f\n\x07variant\x18\x02 \x01(\t\x1a\x85\x02\n\x11\x44\x65\x66\x61ultAssignment\x12\x64\n\x06reason\x18\x01 \x01(\x0e\x32T.confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.DefaultAssignmentReason\"\x89\x01\n\x17\x44\x65\x66\x61ultAssignmentReason\x12)\n%DEFAULT_ASSIGNMENT_REASON_UNSPECIFIED\x10\x00\x12\x14\n\x10NO_SEGMENT_MATCH\x10\x01\x12\x1a\n\x12NO_TREATMENT_MATCH\x10\x02\x1a\x02\x08\x01\x12\x11\n\rFLAG_ARCHIVED\x10\x03\"s\n\x15\x46\x61llthroughAssignment\x12\x0c\n\x04rule\x18\x01 \x01(\t\x12\x15\n\rassignment_id\x18\x02 \x01(\t\x12\x15\n\rtargeting_key\x18\x03 \x01(\t\x12\x1e\n\x16targeting_key_selector\x18\x04 \x01(\t\"\xdf\x02\n\x11\x43lientResolveInfo\x12\x0e\n\x06\x63lient\x18\x01 \x01(\t\x12\x19\n\x11\x63lient_credential\x18\x02 \x01(\t\x12_\n\x06schema\x18\x03 \x03(\x0b\x32O.confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance\x1a\xbd\x01\n\x1f\x45valuationContextSchemaInstance\x12k\n\x06schema\x18\x01 \x03(\x0b\x32[.confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry\x1a-\n\x0bSchemaEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"\xb5\x01\n\x0f\x46lagResolveInfo\x12\x0c\n\x04\x66lag\x18\x01 \x01(\t\x12^\n\x14variant_resolve_info\x18\x02 \x03(\x0b\x32@.confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo\x1a\x34\n\x12VariantResolveInfo\x12\x0f\n\x07variant\x18\x01 \x01(\t\x12\r\n\x05\x63ount\x18\x03 \x01(\x03\"]\n\x16WriteOperationsRequest\x12\x43\n\x10store_variant_op\x18\x01 \x03(\x0b\x32).confidence.flags.resolver.v1.VariantData\"\x17\n\x15WriteOperationsResult\"D\n\rVariantReadOp\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x0c\n\x04rule\x18\x03 \x01(\t\"8\n\x0fInclusionReadOp\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\"\xa2\x01\n\x06ReadOp\x12\x46\n\x0fvariant_read_op\x18\x01 \x01(\x0b\x32+.confidence.flags.resolver.v1.VariantReadOpH\x00\x12J\n\x11inclusion_read_op\x18\x02 \x01(\x0b\x32-.confidence.flags.resolver.v1.InclusionReadOpH\x00\x42\x04\n\x02op\"J\n\x15ReadOperationsRequest\x12\x31\n\x03ops\x18\x03 \x03(\x0b\x32$.confidence.flags.resolver.v1.ReadOp\"S\n\x0bVariantData\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x0c\n\x04rule\x18\x03 \x01(\t\x12\x0f\n\x07variant\x18\x04 \x01(\t\"K\n\rInclusionData\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x13\n\x0bis_included\x18\x03 \x01(\x08\"\xa4\x01\n\nReadResult\x12\x43\n\x0evariant_result\x18\x01 \x01(\x0b\x32).confidence.flags.resolver.v1.VariantDataH\x00\x12G\n\x10inclusion_result\x18\x02 \x01(\x0b\x32+.confidence.flags.resolver.v1.InclusionDataH\x00\x42\x08\n\x06result\"Q\n\x14ReadOperationsResult\x12\x39\n\x07results\x18\x01 \x03(\x0b\x32(.confidence.flags.resolver.v1.ReadResult2\xb2\x03\n\x19InternalFlagLoggerService\x12~\n\x13\x43lientWriteFlagLogs\x12\x32.confidence.flags.resolver.v1.WriteFlagLogsRequest\x1a\x33.confidence.flags.resolver.v1.WriteFlagLogsResponse\x12\x8a\x01\n\x1bWriteMaterializedOperations\x12\x34.confidence.flags.resolver.v1.WriteOperationsRequest\x1a\x33.confidence.flags.resolver.v1.WriteOperationsResult\"\x00\x12\x87\x01\n\x1aReadMaterializedOperations\x12\x33.confidence.flags.resolver.v1.ReadOperationsRequest\x1a\x32.confidence.flags.resolver.v1.ReadOperationsResult\"\x00\x42\xad\x01\n,com.spotify.confidence.sdk.flags.resolver.v1B\x10InternalApiProtoP\x01Zigithub.com/spotify/confidence-resolver/openfeature-provider/go/confidence/internal/proto/resolverinternalb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n/confidence/flags/resolver/v1/internal_api.proto\x12\x1c\x63onfidence.flags.resolver.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a(confidence/flags/resolver/v1/types.proto\"\xb6\x02\n\x14WriteFlagLogsRequest\x12\x41\n\rflag_assigned\x18\x01 \x03(\x0b\x32*.confidence.flags.resolver.v1.FlagAssigned\x12\x43\n\x0etelemetry_data\x18\x02 \x01(\x0b\x32+.confidence.flags.resolver.v1.TelemetryData\x12L\n\x13\x63lient_resolve_info\x18\x03 \x03(\x0b\x32/.confidence.flags.resolver.v1.ClientResolveInfo\x12H\n\x11\x66lag_resolve_info\x18\x04 \x03(\x0b\x32-.confidence.flags.resolver.v1.FlagResolveInfo\"\x17\n\x15WriteFlagLogsResponse\"n\n\x15IngestFlagLogsRequest\x12\x12\n\naccount_id\x18\x01 \x01(\t\x12\x41\n\x05\x62\x61tch\x18\x02 \x01(\x0b\x32\x32.confidence.flags.resolver.v1.WriteFlagLogsRequest\"\xf0\t\n\rTelemetryData\x12.\n\x03sdk\x18\x02 \x01(\x0b\x32!.confidence.flags.resolver.v1.Sdk\x12S\n\x0fresolve_latency\x18\x04 \x01(\x0b\x32:.confidence.flags.resolver.v1.TelemetryData.ResolveLatency\x12M\n\x0cresolve_rate\x18\x05 \x03(\x0b\x32\x37.confidence.flags.resolver.v1.TelemetryData.ResolveRate\x12G\n\tstate_age\x18\x06 \x01(\x0b\x32\x34.confidence.flags.resolver.v1.TelemetryData.StateAge\x12\x14\n\x0cmemory_bytes\x18\x07 \x01(\x04\x12\x18\n\x10resolver_version\x18\x08 \x01(\t\x12X\n\x12provider_init_rate\x18\t \x03(\x0b\x32<.confidence.flags.resolver.v1.TelemetryData.ProviderInitRate\x12T\n\x0b\x61pply_dedup\x18\n \x01(\x0b\x32?.confidence.flags.resolver.v1.TelemetryData.ApplyDedupTelemetry\x12\x17\n\x0f\x66lush_succeeded\x18\x0b \x01(\r\x12\x14\n\x0c\x66lush_failed\x18\x0c \x01(\r\x12\x18\n\x10\x65vents_published\x18\r \x01(\r\x12\x1f\n\x17\x65vent_batches_succeeded\x18\x0e \x01(\r\x12\x1c\n\x14\x65vent_batches_failed\x18\x0f \x01(\r\x1a\x87\x01\n\x0eResolveLatency\x12\x0b\n\x03sum\x18\x01 \x01(\r\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12G\n\x07\x62uckets\x18\x03 \x03(\x0b\x32\x36.confidence.flags.resolver.v1.TelemetryData.BucketSpan\x12\x10\n\x08ln_ratio\x18\x04 \x01(\x01\x1a,\n\x0bResolveRate\x12\r\n\x05\x63ount\x18\x01 \x01(\r\x12\x0e\n\x06reason\x18\x02 \x01(\r\x1a%\n\x08StateAge\x12\x19\n\x11last_state_update\x18\x01 \x01(\x04\x1a,\n\nBucketSpan\x12\x0e\n\x06offset\x18\x01 \x01(\x05\x12\x0e\n\x06\x63ounts\x18\x02 \x03(\r\x1a\x99\x01\n\x13\x41pplyDedupTelemetry\x12\x15\n\rapplies_total\x18\x01 \x01(\r\x12\x17\n\x0f\x61pplies_deduped\x18\x02 \x01(\r\x12\x1a\n\x12\x61pplies_not_cached\x18\x03 \x01(\r\x12\x0e\n\x06sweeps\x18\x04 \x01(\r\x12\x10\n\x08map_size\x18\x05 \x01(\r\x12\x14\n\x0cmap_capacity\x18\x06 \x01(\r\x1a\xb0\x01\n\x10ProviderInitRate\x12\r\n\x05\x63ount\x18\x01 \x01(\r\x12X\n\x06labels\x18\x03 \x03(\x0b\x32H.confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01J\x04\x08\x02\x10\x03\"g\n\nClientInfo\x12\x0e\n\x06\x63lient\x18\x01 \x01(\t\x12\x19\n\x11\x63lient_credential\x18\x02 \x01(\t\x12.\n\x03sdk\x18\x03 \x01(\x0b\x32!.confidence.flags.resolver.v1.Sdk\"\xa4\x07\n\x0c\x46lagAssigned\x12\x12\n\nresolve_id\x18\n \x01(\t\x12=\n\x0b\x63lient_info\x18\x03 \x01(\x0b\x32(.confidence.flags.resolver.v1.ClientInfo\x12\x45\n\x05\x66lags\x18\x0f \x03(\x0b\x32\x36.confidence.flags.resolver.v1.FlagAssigned.AppliedFlag\x1a\xbd\x03\n\x0b\x41ppliedFlag\x12\x0c\n\x04\x66lag\x18\x01 \x01(\t\x12\x15\n\rtargeting_key\x18\x02 \x01(\t\x12\x1e\n\x16targeting_key_selector\x18\x03 \x01(\t\x12T\n\x0f\x61ssignment_info\x18\x04 \x01(\x0b\x32\x39.confidence.flags.resolver.v1.FlagAssigned.AssignmentInfoH\x00\x12Z\n\x12\x64\x65\x66\x61ult_assignment\x18\x05 \x01(\x0b\x32<.confidence.flags.resolver.v1.FlagAssigned.DefaultAssignmentH\x00\x12\x15\n\rassignment_id\x18\x06 \x01(\t\x12\x0c\n\x04rule\x18\x07 \x01(\t\x12T\n\x17\x66\x61llthrough_assignments\x18\x08 \x03(\x0b\x32\x33.confidence.flags.resolver.v1.FallthroughAssignment\x12.\n\napply_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x0c\n\nassignment\x1a\x32\n\x0e\x41ssignmentInfo\x12\x0f\n\x07segment\x18\x01 \x01(\t\x12\x0f\n\x07variant\x18\x02 \x01(\t\x1a\x85\x02\n\x11\x44\x65\x66\x61ultAssignment\x12\x64\n\x06reason\x18\x01 \x01(\x0e\x32T.confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.DefaultAssignmentReason\"\x89\x01\n\x17\x44\x65\x66\x61ultAssignmentReason\x12)\n%DEFAULT_ASSIGNMENT_REASON_UNSPECIFIED\x10\x00\x12\x14\n\x10NO_SEGMENT_MATCH\x10\x01\x12\x1a\n\x12NO_TREATMENT_MATCH\x10\x02\x1a\x02\x08\x01\x12\x11\n\rFLAG_ARCHIVED\x10\x03\"s\n\x15\x46\x61llthroughAssignment\x12\x0c\n\x04rule\x18\x01 \x01(\t\x12\x15\n\rassignment_id\x18\x02 \x01(\t\x12\x15\n\rtargeting_key\x18\x03 \x01(\t\x12\x1e\n\x16targeting_key_selector\x18\x04 \x01(\t\"\xdf\x02\n\x11\x43lientResolveInfo\x12\x0e\n\x06\x63lient\x18\x01 \x01(\t\x12\x19\n\x11\x63lient_credential\x18\x02 \x01(\t\x12_\n\x06schema\x18\x03 \x03(\x0b\x32O.confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance\x1a\xbd\x01\n\x1f\x45valuationContextSchemaInstance\x12k\n\x06schema\x18\x01 \x03(\x0b\x32[.confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry\x1a-\n\x0bSchemaEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"\xb5\x01\n\x0f\x46lagResolveInfo\x12\x0c\n\x04\x66lag\x18\x01 \x01(\t\x12^\n\x14variant_resolve_info\x18\x02 \x03(\x0b\x32@.confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo\x1a\x34\n\x12VariantResolveInfo\x12\x0f\n\x07variant\x18\x01 \x01(\t\x12\r\n\x05\x63ount\x18\x03 \x01(\x03\"]\n\x16WriteOperationsRequest\x12\x43\n\x10store_variant_op\x18\x01 \x03(\x0b\x32).confidence.flags.resolver.v1.VariantData\"\x17\n\x15WriteOperationsResult\"D\n\rVariantReadOp\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x0c\n\x04rule\x18\x03 \x01(\t\"8\n\x0fInclusionReadOp\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\"\xa2\x01\n\x06ReadOp\x12\x46\n\x0fvariant_read_op\x18\x01 \x01(\x0b\x32+.confidence.flags.resolver.v1.VariantReadOpH\x00\x12J\n\x11inclusion_read_op\x18\x02 \x01(\x0b\x32-.confidence.flags.resolver.v1.InclusionReadOpH\x00\x42\x04\n\x02op\"J\n\x15ReadOperationsRequest\x12\x31\n\x03ops\x18\x03 \x03(\x0b\x32$.confidence.flags.resolver.v1.ReadOp\"S\n\x0bVariantData\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x0c\n\x04rule\x18\x03 \x01(\t\x12\x0f\n\x07variant\x18\x04 \x01(\t\"K\n\rInclusionData\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x13\n\x0bis_included\x18\x03 \x01(\x08\"\xa4\x01\n\nReadResult\x12\x43\n\x0evariant_result\x18\x01 \x01(\x0b\x32).confidence.flags.resolver.v1.VariantDataH\x00\x12G\n\x10inclusion_result\x18\x02 \x01(\x0b\x32+.confidence.flags.resolver.v1.InclusionDataH\x00\x42\x08\n\x06result\"Q\n\x14ReadOperationsResult\x12\x39\n\x07results\x18\x01 \x03(\x0b\x32(.confidence.flags.resolver.v1.ReadResult2\xb2\x03\n\x19InternalFlagLoggerService\x12~\n\x13\x43lientWriteFlagLogs\x12\x32.confidence.flags.resolver.v1.WriteFlagLogsRequest\x1a\x33.confidence.flags.resolver.v1.WriteFlagLogsResponse\x12\x8a\x01\n\x1bWriteMaterializedOperations\x12\x34.confidence.flags.resolver.v1.WriteOperationsRequest\x1a\x33.confidence.flags.resolver.v1.WriteOperationsResult\"\x00\x12\x87\x01\n\x1aReadMaterializedOperations\x12\x33.confidence.flags.resolver.v1.ReadOperationsRequest\x1a\x32.confidence.flags.resolver.v1.ReadOperationsResult\"\x00\x42\xad\x01\n,com.spotify.confidence.sdk.flags.resolver.v1B\x10InternalApiProtoP\x01Zigithub.com/spotify/confidence-resolver/openfeature-provider/go/confidence/internal/proto/resolverinternalb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -47,57 +47,65 @@ _globals['_INGESTFLAGLOGSREQUEST']._serialized_start=494 _globals['_INGESTFLAGLOGSREQUEST']._serialized_end=604 _globals['_TELEMETRYDATA']._serialized_start=607 - _globals['_TELEMETRYDATA']._serialized_end=1343 - _globals['_TELEMETRYDATA_APPLYDEDUPTELEMETRY']._serialized_start=1011 - _globals['_TELEMETRYDATA_APPLYDEDUPTELEMETRY']._serialized_end=1164 - _globals['_TELEMETRYDATA_PROVIDERINITRATE']._serialized_start=1167 - _globals['_TELEMETRYDATA_PROVIDERINITRATE']._serialized_end=1343 - _globals['_TELEMETRYDATA_PROVIDERINITRATE_LABELSENTRY']._serialized_start=1292 - _globals['_TELEMETRYDATA_PROVIDERINITRATE_LABELSENTRY']._serialized_end=1337 - _globals['_CLIENTINFO']._serialized_start=1345 - _globals['_CLIENTINFO']._serialized_end=1448 - _globals['_FLAGASSIGNED']._serialized_start=1451 - _globals['_FLAGASSIGNED']._serialized_end=2383 - _globals['_FLAGASSIGNED_APPLIEDFLAG']._serialized_start=1622 - _globals['_FLAGASSIGNED_APPLIEDFLAG']._serialized_end=2067 - _globals['_FLAGASSIGNED_ASSIGNMENTINFO']._serialized_start=2069 - _globals['_FLAGASSIGNED_ASSIGNMENTINFO']._serialized_end=2119 - _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT']._serialized_start=2122 - _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT']._serialized_end=2383 - _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT_DEFAULTASSIGNMENTREASON']._serialized_start=2246 - _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT_DEFAULTASSIGNMENTREASON']._serialized_end=2383 - _globals['_FALLTHROUGHASSIGNMENT']._serialized_start=2385 - _globals['_FALLTHROUGHASSIGNMENT']._serialized_end=2500 - _globals['_CLIENTRESOLVEINFO']._serialized_start=2503 - _globals['_CLIENTRESOLVEINFO']._serialized_end=2854 - _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE']._serialized_start=2665 - _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE']._serialized_end=2854 - _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE_SCHEMAENTRY']._serialized_start=2809 - _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE_SCHEMAENTRY']._serialized_end=2854 - _globals['_FLAGRESOLVEINFO']._serialized_start=2857 - _globals['_FLAGRESOLVEINFO']._serialized_end=3038 - _globals['_FLAGRESOLVEINFO_VARIANTRESOLVEINFO']._serialized_start=2986 - _globals['_FLAGRESOLVEINFO_VARIANTRESOLVEINFO']._serialized_end=3038 - _globals['_WRITEOPERATIONSREQUEST']._serialized_start=3040 - _globals['_WRITEOPERATIONSREQUEST']._serialized_end=3133 - _globals['_WRITEOPERATIONSRESULT']._serialized_start=3135 - _globals['_WRITEOPERATIONSRESULT']._serialized_end=3158 - _globals['_VARIANTREADOP']._serialized_start=3160 - _globals['_VARIANTREADOP']._serialized_end=3228 - _globals['_INCLUSIONREADOP']._serialized_start=3230 - _globals['_INCLUSIONREADOP']._serialized_end=3286 - _globals['_READOP']._serialized_start=3289 - _globals['_READOP']._serialized_end=3451 - _globals['_READOPERATIONSREQUEST']._serialized_start=3453 - _globals['_READOPERATIONSREQUEST']._serialized_end=3527 - _globals['_VARIANTDATA']._serialized_start=3529 - _globals['_VARIANTDATA']._serialized_end=3612 - _globals['_INCLUSIONDATA']._serialized_start=3614 - _globals['_INCLUSIONDATA']._serialized_end=3689 - _globals['_READRESULT']._serialized_start=3692 - _globals['_READRESULT']._serialized_end=3856 - _globals['_READOPERATIONSRESULT']._serialized_start=3858 - _globals['_READOPERATIONSRESULT']._serialized_end=3939 - _globals['_INTERNALFLAGLOGGERSERVICE']._serialized_start=3942 - _globals['_INTERNALFLAGLOGGERSERVICE']._serialized_end=4376 + _globals['_TELEMETRYDATA']._serialized_end=1871 + _globals['_TELEMETRYDATA_RESOLVELATENCY']._serialized_start=1270 + _globals['_TELEMETRYDATA_RESOLVELATENCY']._serialized_end=1405 + _globals['_TELEMETRYDATA_RESOLVERATE']._serialized_start=1407 + _globals['_TELEMETRYDATA_RESOLVERATE']._serialized_end=1451 + _globals['_TELEMETRYDATA_STATEAGE']._serialized_start=1453 + _globals['_TELEMETRYDATA_STATEAGE']._serialized_end=1490 + _globals['_TELEMETRYDATA_BUCKETSPAN']._serialized_start=1492 + _globals['_TELEMETRYDATA_BUCKETSPAN']._serialized_end=1536 + _globals['_TELEMETRYDATA_APPLYDEDUPTELEMETRY']._serialized_start=1539 + _globals['_TELEMETRYDATA_APPLYDEDUPTELEMETRY']._serialized_end=1692 + _globals['_TELEMETRYDATA_PROVIDERINITRATE']._serialized_start=1695 + _globals['_TELEMETRYDATA_PROVIDERINITRATE']._serialized_end=1871 + _globals['_TELEMETRYDATA_PROVIDERINITRATE_LABELSENTRY']._serialized_start=1820 + _globals['_TELEMETRYDATA_PROVIDERINITRATE_LABELSENTRY']._serialized_end=1865 + _globals['_CLIENTINFO']._serialized_start=1873 + _globals['_CLIENTINFO']._serialized_end=1976 + _globals['_FLAGASSIGNED']._serialized_start=1979 + _globals['_FLAGASSIGNED']._serialized_end=2911 + _globals['_FLAGASSIGNED_APPLIEDFLAG']._serialized_start=2150 + _globals['_FLAGASSIGNED_APPLIEDFLAG']._serialized_end=2595 + _globals['_FLAGASSIGNED_ASSIGNMENTINFO']._serialized_start=2597 + _globals['_FLAGASSIGNED_ASSIGNMENTINFO']._serialized_end=2647 + _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT']._serialized_start=2650 + _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT']._serialized_end=2911 + _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT_DEFAULTASSIGNMENTREASON']._serialized_start=2774 + _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT_DEFAULTASSIGNMENTREASON']._serialized_end=2911 + _globals['_FALLTHROUGHASSIGNMENT']._serialized_start=2913 + _globals['_FALLTHROUGHASSIGNMENT']._serialized_end=3028 + _globals['_CLIENTRESOLVEINFO']._serialized_start=3031 + _globals['_CLIENTRESOLVEINFO']._serialized_end=3382 + _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE']._serialized_start=3193 + _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE']._serialized_end=3382 + _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE_SCHEMAENTRY']._serialized_start=3337 + _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE_SCHEMAENTRY']._serialized_end=3382 + _globals['_FLAGRESOLVEINFO']._serialized_start=3385 + _globals['_FLAGRESOLVEINFO']._serialized_end=3566 + _globals['_FLAGRESOLVEINFO_VARIANTRESOLVEINFO']._serialized_start=3514 + _globals['_FLAGRESOLVEINFO_VARIANTRESOLVEINFO']._serialized_end=3566 + _globals['_WRITEOPERATIONSREQUEST']._serialized_start=3568 + _globals['_WRITEOPERATIONSREQUEST']._serialized_end=3661 + _globals['_WRITEOPERATIONSRESULT']._serialized_start=3663 + _globals['_WRITEOPERATIONSRESULT']._serialized_end=3686 + _globals['_VARIANTREADOP']._serialized_start=3688 + _globals['_VARIANTREADOP']._serialized_end=3756 + _globals['_INCLUSIONREADOP']._serialized_start=3758 + _globals['_INCLUSIONREADOP']._serialized_end=3814 + _globals['_READOP']._serialized_start=3817 + _globals['_READOP']._serialized_end=3979 + _globals['_READOPERATIONSREQUEST']._serialized_start=3981 + _globals['_READOPERATIONSREQUEST']._serialized_end=4055 + _globals['_VARIANTDATA']._serialized_start=4057 + _globals['_VARIANTDATA']._serialized_end=4140 + _globals['_INCLUSIONDATA']._serialized_start=4142 + _globals['_INCLUSIONDATA']._serialized_end=4217 + _globals['_READRESULT']._serialized_start=4220 + _globals['_READRESULT']._serialized_end=4384 + _globals['_READOPERATIONSRESULT']._serialized_start=4386 + _globals['_READOPERATIONSRESULT']._serialized_end=4467 + _globals['_INTERNALFLAGLOGGERSERVICE']._serialized_start=4470 + _globals['_INTERNALFLAGLOGGERSERVICE']._serialized_end=4904 # @@protoc_insertion_point(module_scope) From 4c36d92bf9b026a804700649bdea710c017c01fc Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Wed, 2 Sep 2026 16:08:05 +0200 Subject: [PATCH 13/25] refactor: use nested FlushTelemetry/EventsTelemetry proto messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- confidence-cloudflare-resolver/src/lib.rs | 10 +- .../flags/resolver/v1/internal_api.proto | 23 +- confidence-resolver/src/telemetry.rs | 139 ++++--- .../confidence/internal/flag_logger/grpc.go | 18 +- .../confidence/internal/flag_logger/multi.go | 18 +- .../assets/confidence_resolver.wasm | Bin 509841 -> 510175 bytes .../proto/resolverinternal/internal_api.pb.go | 347 +++++++++++------- .../sdk/ProviderTelemetryResolver.java | 14 +- .../js/src/ConfidenceServerProviderLocal.ts | 25 +- .../flags/resolver/v1/internal_api.proto | 22 +- .../flags/resolver/v1/internal_api_pb2.py | 128 +++---- .../python/src/confidence/provider.py | 10 +- 12 files changed, 446 insertions(+), 308 deletions(-) diff --git a/confidence-cloudflare-resolver/src/lib.rs b/confidence-cloudflare-resolver/src/lib.rs index ab0b847e5..d57fdae0d 100644 --- a/confidence-cloudflare-resolver/src/lib.rs +++ b/confidence-cloudflare-resolver/src/lib.rs @@ -817,10 +817,10 @@ async fn update_prometheus_kv( match flush_result { Some(true) => { - cumulative.flush_succeeded = cumulative.flush_succeeded.wrapping_add(1); + cumulative.flush.succeeded = cumulative.flush.succeeded.wrapping_add(1); } Some(false) => { - cumulative.flush_failed = cumulative.flush_failed.wrapping_add(1); + cumulative.flush.failed = cumulative.flush.failed.wrapping_add(1); } None => {} } @@ -1060,10 +1060,10 @@ async fn update_events_kv(kv: &kv::KvStore, event_count: u64, succeeded: bool) { }; if succeeded { - cumulative.events_published = cumulative.events_published.wrapping_add(event_count); - cumulative.event_batches_succeeded = cumulative.event_batches_succeeded.wrapping_add(1); + cumulative.events.published = cumulative.events.published.wrapping_add(event_count); + cumulative.events.batches_succeeded = cumulative.events.batches_succeeded.wrapping_add(1); } else { - cumulative.event_batches_failed = cumulative.event_batches_failed.wrapping_add(1); + cumulative.events.batches_failed = cumulative.events.batches_failed.wrapping_add(1); } let prom_text = cumulative.to_prometheus( diff --git a/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto b/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto index 47b74017d..a800e0ec3 100644 --- a/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto +++ b/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto @@ -134,16 +134,19 @@ message TelemetryData { ApplyDedupTelemetry apply_dedup = 10; - // Delta counters: WriteFlagLogs batch delivery outcomes since last flush. - // Populated by the host SDK after each delivery attempt. - uint32 flush_succeeded = 11; - uint32 flush_failed = 12; - - // Delta counters: event delivery stats since last flush. - // Piggybacked here because the events pipeline has no TelemetryData channel. - uint32 events_published = 13; - uint32 event_batches_succeeded = 14; - uint32 event_batches_failed = 15; + FlushTelemetry flush = 11; + EventsTelemetry events = 12; + + message FlushTelemetry { + uint32 succeeded = 1; + uint32 failed = 2; + } + + message EventsTelemetry { + uint32 published = 1; + uint32 batches_succeeded = 2; + uint32 batches_failed = 3; + } message ApplyDedupTelemetry { // Delta counters (since last flush): diff --git a/confidence-resolver/src/telemetry.rs b/confidence-resolver/src/telemetry.rs index b3d0a61f1..57e14e480 100644 --- a/confidence-resolver/src/telemetry.rs +++ b/confidence-resolver/src/telemetry.rs @@ -114,11 +114,23 @@ pub struct TelemetrySnapshot { pub resolve_rates: Vec, pub memory_bytes: u64, pub apply_dedup: Option, - pub flush_succeeded: u64, - pub flush_failed: u64, - pub events_published: u64, - pub event_batches_succeeded: u64, - pub event_batches_failed: u64, + pub flush: FlushSnapshot, + pub events: EventsSnapshot, +} + +#[derive(Clone, Default)] +#[cfg_attr(feature = "json", derive(serde::Serialize, serde::Deserialize))] +pub struct FlushSnapshot { + pub succeeded: u64, + pub failed: u64, +} + +#[derive(Clone, Default)] +#[cfg_attr(feature = "json", derive(serde::Serialize, serde::Deserialize))] +pub struct EventsSnapshot { + pub published: u64, + pub batches_succeeded: u64, + pub batches_failed: u64, } #[derive(Clone, Default)] @@ -213,17 +225,22 @@ impl TelemetrySnapshot { ad.map_capacity = dedup.map_capacity; } - self.flush_succeeded = self.flush_succeeded.wrapping_add(td.flush_succeeded as u64); - self.flush_failed = self.flush_failed.wrapping_add(td.flush_failed as u64); - self.events_published = self - .events_published - .wrapping_add(td.events_published as u64); - self.event_batches_succeeded = self - .event_batches_succeeded - .wrapping_add(td.event_batches_succeeded as u64); - self.event_batches_failed = self - .event_batches_failed - .wrapping_add(td.event_batches_failed as u64); + if let Some(flush) = &td.flush { + self.flush.succeeded = self.flush.succeeded.wrapping_add(flush.succeeded as u64); + self.flush.failed = self.flush.failed.wrapping_add(flush.failed as u64); + } + + if let Some(events) = &td.events { + self.events.published = self.events.published.wrapping_add(events.published as u64); + self.events.batches_succeeded = self + .events + .batches_succeeded + .wrapping_add(events.batches_succeeded as u64); + self.events.batches_failed = self + .events + .batches_failed + .wrapping_add(events.batches_failed as u64); + } } /// Format the snapshot as Prometheus exposition text. @@ -496,7 +513,7 @@ impl TelemetrySnapshot { resolver_id: &str, config: &PrometheusConfig, ) -> fmt::Result { - if self.flush_succeeded == 0 && self.flush_failed == 0 { + if self.flush.succeeded == 0 && self.flush.failed == 0 { return Ok(()); } let suffix = if config.openmetrics { ".0" } else { "" }; @@ -514,7 +531,7 @@ impl TelemetrySnapshot { writeln!( w, "confidence_flush_succeeded_total{{resolver_id=\"{resolver_id}\"}} {}{suffix}", - self.flush_succeeded + self.flush.succeeded )?; let type_name = if config.openmetrics { @@ -530,7 +547,7 @@ impl TelemetrySnapshot { writeln!( w, "confidence_flush_failed_total{{resolver_id=\"{resolver_id}\"}} {}{suffix}", - self.flush_failed + self.flush.failed ) } @@ -540,15 +557,15 @@ impl TelemetrySnapshot { resolver_id: &str, config: &PrometheusConfig, ) -> fmt::Result { - if self.events_published == 0 - && self.event_batches_succeeded == 0 - && self.event_batches_failed == 0 + if self.events.published == 0 + && self.events.batches_succeeded == 0 + && self.events.batches_failed == 0 { return Ok(()); } let suffix = if config.openmetrics { ".0" } else { "" }; - if self.events_published > 0 { + if self.events.published > 0 { let type_name = if config.openmetrics { "confidence_events_published" } else { @@ -559,11 +576,11 @@ impl TelemetrySnapshot { writeln!( w, "confidence_events_published_total{{resolver_id=\"{resolver_id}\"}} {}{suffix}", - self.events_published + self.events.published )?; } - if self.event_batches_succeeded > 0 { + if self.events.batches_succeeded > 0 { let type_name = if config.openmetrics { "confidence_event_batches_succeeded" } else { @@ -574,11 +591,11 @@ impl TelemetrySnapshot { writeln!( w, "confidence_event_batches_succeeded_total{{resolver_id=\"{resolver_id}\"}} {}{suffix}", - self.event_batches_succeeded + self.events.batches_succeeded )?; } - if self.event_batches_failed > 0 { + if self.events.batches_failed > 0 { let type_name = if config.openmetrics { "confidence_event_batches_failed" } else { @@ -589,7 +606,7 @@ impl TelemetrySnapshot { writeln!( w, "confidence_event_batches_failed_total{{resolver_id=\"{resolver_id}\"}} {}{suffix}", - self.event_batches_failed + self.events.batches_failed )?; } @@ -662,11 +679,8 @@ impl Telemetry { .collect(), memory_bytes: (self.memory_provider)(), apply_dedup: None, - flush_succeeded: 0, - flush_failed: 0, - events_published: 0, - event_batches_succeeded: 0, - event_batches_failed: 0, + flush: FlushSnapshot::default(), + events: EventsSnapshot::default(), } } @@ -747,11 +761,8 @@ impl Telemetry { resolver_version: crate::version::VERSION.to_string(), provider_init_rate: Vec::new(), apply_dedup: None, - flush_succeeded: 0, - flush_failed: 0, - events_published: 0, - event_batches_succeeded: 0, - event_batches_failed: 0, + flush: None, + events: None, } } } @@ -1454,8 +1465,8 @@ mod tests { #[test] fn prometheus_flush_counters() { let mut snap = TelemetrySnapshot::default(); - snap.flush_succeeded = 10; - snap.flush_failed = 2; + snap.flush.succeeded = 10; + snap.flush.failed = 2; let config = PrometheusConfig::default(); let prom = snap.to_prometheus("w0", &config); @@ -1466,41 +1477,49 @@ mod tests { #[test] fn accumulate_delta_flush_counters() { + use crate::proto::confidence::flags::resolver::v1::telemetry_data::FlushTelemetry; + let mut snap = TelemetrySnapshot::default(); let td = pb::TelemetryData { - flush_succeeded: 5, - flush_failed: 1, + flush: Some(FlushTelemetry { + succeeded: 5, + failed: 1, + }), ..Default::default() }; snap.accumulate_delta(&td); - assert_eq!(snap.flush_succeeded, 5); - assert_eq!(snap.flush_failed, 1); + assert_eq!(snap.flush.succeeded, 5); + assert_eq!(snap.flush.failed, 1); snap.accumulate_delta(&td); - assert_eq!(snap.flush_succeeded, 10); - assert_eq!(snap.flush_failed, 2); + assert_eq!(snap.flush.succeeded, 10); + assert_eq!(snap.flush.failed, 2); } #[test] fn accumulate_delta_event_counters() { + use crate::proto::confidence::flags::resolver::v1::telemetry_data::EventsTelemetry; + let mut snap = TelemetrySnapshot::default(); let td = pb::TelemetryData { - events_published: 42, - event_batches_succeeded: 3, - event_batches_failed: 1, + events: Some(EventsTelemetry { + published: 42, + batches_succeeded: 3, + batches_failed: 1, + }), ..Default::default() }; snap.accumulate_delta(&td); - assert_eq!(snap.events_published, 42); - assert_eq!(snap.event_batches_succeeded, 3); - assert_eq!(snap.event_batches_failed, 1); + assert_eq!(snap.events.published, 42); + assert_eq!(snap.events.batches_succeeded, 3); + assert_eq!(snap.events.batches_failed, 1); snap.accumulate_delta(&td); - assert_eq!(snap.events_published, 84); - assert_eq!(snap.event_batches_succeeded, 6); - assert_eq!(snap.event_batches_failed, 2); + assert_eq!(snap.events.published, 84); + assert_eq!(snap.events.batches_succeeded, 6); + assert_eq!(snap.events.batches_failed, 2); } #[test] @@ -1518,11 +1537,11 @@ mod tests { map_size: 5, map_capacity: 100_000, }); - snap.flush_succeeded = 2; - snap.flush_failed = 1; - snap.events_published = 50; - snap.event_batches_succeeded = 4; - snap.event_batches_failed = 1; + snap.flush.succeeded = 2; + snap.flush.failed = 1; + snap.events.published = 50; + snap.events.batches_succeeded = 4; + snap.events.batches_failed = 1; let config = PrometheusConfig { openmetrics: true, diff --git a/openfeature-provider/go/confidence/internal/flag_logger/grpc.go b/openfeature-provider/go/confidence/internal/flag_logger/grpc.go index 8bb6d9fd8..674c48b88 100644 --- a/openfeature-provider/go/confidence/internal/flag_logger/grpc.go +++ b/openfeature-provider/go/confidence/internal/flag_logger/grpc.go @@ -71,11 +71,19 @@ func (g *GrpcFlagLogger) Write(request *resolverv1.WriteFlagLogsRequest) { if request.TelemetryData == nil { request.TelemetryData = &resolverv1.TelemetryData{} } - request.TelemetryData.FlushSucceeded = succeeded - request.TelemetryData.FlushFailed = failed - request.TelemetryData.EventsPublished = evPub - request.TelemetryData.EventBatchesSucceeded = evOk - request.TelemetryData.EventBatchesFailed = evFail + if succeeded > 0 || failed > 0 { + request.TelemetryData.Flush = &resolverv1.TelemetryData_FlushTelemetry{ + Succeeded: succeeded, + Failed: failed, + } + } + if evPub > 0 || evOk > 0 || evFail > 0 { + request.TelemetryData.Events = &resolverv1.TelemetryData_EventsTelemetry{ + Published: evPub, + BatchesSucceeded: evOk, + BatchesFailed: evFail, + } + } } g.sendAsync(request) diff --git a/openfeature-provider/go/confidence/internal/flag_logger/multi.go b/openfeature-provider/go/confidence/internal/flag_logger/multi.go index 907e3179a..a2314a296 100644 --- a/openfeature-provider/go/confidence/internal/flag_logger/multi.go +++ b/openfeature-provider/go/confidence/internal/flag_logger/multi.go @@ -97,11 +97,19 @@ func (m *MultiDestinationFlagLogger) Write(request *resolverv1.WriteFlagLogsRequ if request.TelemetryData == nil { request.TelemetryData = &resolverv1.TelemetryData{} } - request.TelemetryData.FlushSucceeded = succeeded - request.TelemetryData.FlushFailed = failed - request.TelemetryData.EventsPublished = evPub - request.TelemetryData.EventBatchesSucceeded = evOk - request.TelemetryData.EventBatchesFailed = evFail + if succeeded > 0 || failed > 0 { + request.TelemetryData.Flush = &resolverv1.TelemetryData_FlushTelemetry{ + Succeeded: succeeded, + Failed: failed, + } + } + if evPub > 0 || evOk > 0 || evFail > 0 { + request.TelemetryData.Events = &resolverv1.TelemetryData_EventsTelemetry{ + Published: evPub, + BatchesSucceeded: evOk, + BatchesFailed: evFail, + } + } } m.wg.Add(1) diff --git a/openfeature-provider/go/confidence/internal/local_resolver/assets/confidence_resolver.wasm b/openfeature-provider/go/confidence/internal/local_resolver/assets/confidence_resolver.wasm index 34e909bd5ca71c8eab5615cba73b902ef55c8631..911b10d064ad50b237e084e77253efbb2db58358 100755 GIT binary patch delta 66964 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 D1-0R7 delta 66557 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 SX>X6s7-Dy24DoHz_J07$x$>a^ diff --git a/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go b/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go index 2064a5479..d7921b887 100644 --- a/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go +++ b/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go @@ -255,16 +255,10 @@ type TelemetryData struct { ResolverVersion string `protobuf:"bytes,8,opt,name=resolver_version,json=resolverVersion,proto3" json:"resolver_version,omitempty"` ProviderInitRate []*TelemetryData_ProviderInitRate `protobuf:"bytes,9,rep,name=provider_init_rate,json=providerInitRate,proto3" json:"provider_init_rate,omitempty"` ApplyDedup *TelemetryData_ApplyDedupTelemetry `protobuf:"bytes,10,opt,name=apply_dedup,json=applyDedup,proto3" json:"apply_dedup,omitempty"` - // Delta counters: WriteFlagLogs batch delivery outcomes since last flush. - // Populated by the host SDK after each delivery attempt. - FlushSucceeded uint32 `protobuf:"varint,11,opt,name=flush_succeeded,json=flushSucceeded,proto3" json:"flush_succeeded,omitempty"` - FlushFailed uint32 `protobuf:"varint,12,opt,name=flush_failed,json=flushFailed,proto3" json:"flush_failed,omitempty"` - // Delta counters: event delivery stats since last flush. - EventsPublished uint32 `protobuf:"varint,13,opt,name=events_published,json=eventsPublished,proto3" json:"events_published,omitempty"` - EventBatchesSucceeded uint32 `protobuf:"varint,14,opt,name=event_batches_succeeded,json=eventBatchesSucceeded,proto3" json:"event_batches_succeeded,omitempty"` - EventBatchesFailed uint32 `protobuf:"varint,15,opt,name=event_batches_failed,json=eventBatchesFailed,proto3" json:"event_batches_failed,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + Flush *TelemetryData_FlushTelemetry `protobuf:"bytes,11,opt,name=flush,proto3" json:"flush,omitempty"` + Events *TelemetryData_EventsTelemetry `protobuf:"bytes,12,opt,name=events,proto3" json:"events,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *TelemetryData) Reset() { @@ -353,39 +347,18 @@ func (x *TelemetryData) GetApplyDedup() *TelemetryData_ApplyDedupTelemetry { return nil } -func (x *TelemetryData) GetFlushSucceeded() uint32 { - if x != nil { - return x.FlushSucceeded - } - return 0 -} - -func (x *TelemetryData) GetFlushFailed() uint32 { +func (x *TelemetryData) GetFlush() *TelemetryData_FlushTelemetry { if x != nil { - return x.FlushFailed + return x.Flush } - return 0 -} - -func (x *TelemetryData) GetEventsPublished() uint32 { - if x != nil { - return x.EventsPublished - } - return 0 -} - -func (x *TelemetryData) GetEventBatchesSucceeded() uint32 { - if x != nil { - return x.EventBatchesSucceeded - } - return 0 + return nil } -func (x *TelemetryData) GetEventBatchesFailed() uint32 { +func (x *TelemetryData) GetEvents() *TelemetryData_EventsTelemetry { if x != nil { - return x.EventBatchesFailed + return x.Events } - return 0 + return nil } type ClientInfo struct { @@ -1266,6 +1239,118 @@ func (x *ReadOperationsResult) GetResults() []*ReadResult { return nil } +type TelemetryData_FlushTelemetry struct { + state protoimpl.MessageState `protogen:"open.v1"` + Succeeded uint32 `protobuf:"varint,1,opt,name=succeeded,proto3" json:"succeeded,omitempty"` + Failed uint32 `protobuf:"varint,2,opt,name=failed,proto3" json:"failed,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TelemetryData_FlushTelemetry) Reset() { + *x = TelemetryData_FlushTelemetry{} + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TelemetryData_FlushTelemetry) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TelemetryData_FlushTelemetry) ProtoMessage() {} + +func (x *TelemetryData_FlushTelemetry) ProtoReflect() protoreflect.Message { + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TelemetryData_FlushTelemetry.ProtoReflect.Descriptor instead. +func (*TelemetryData_FlushTelemetry) Descriptor() ([]byte, []int) { + return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 0} +} + +func (x *TelemetryData_FlushTelemetry) GetSucceeded() uint32 { + if x != nil { + return x.Succeeded + } + return 0 +} + +func (x *TelemetryData_FlushTelemetry) GetFailed() uint32 { + if x != nil { + return x.Failed + } + return 0 +} + +type TelemetryData_EventsTelemetry struct { + state protoimpl.MessageState `protogen:"open.v1"` + Published uint32 `protobuf:"varint,1,opt,name=published,proto3" json:"published,omitempty"` + BatchesSucceeded uint32 `protobuf:"varint,2,opt,name=batches_succeeded,json=batchesSucceeded,proto3" json:"batches_succeeded,omitempty"` + BatchesFailed uint32 `protobuf:"varint,3,opt,name=batches_failed,json=batchesFailed,proto3" json:"batches_failed,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TelemetryData_EventsTelemetry) Reset() { + *x = TelemetryData_EventsTelemetry{} + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TelemetryData_EventsTelemetry) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TelemetryData_EventsTelemetry) ProtoMessage() {} + +func (x *TelemetryData_EventsTelemetry) ProtoReflect() protoreflect.Message { + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[20] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TelemetryData_EventsTelemetry.ProtoReflect.Descriptor instead. +func (*TelemetryData_EventsTelemetry) Descriptor() ([]byte, []int) { + return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 1} +} + +func (x *TelemetryData_EventsTelemetry) GetPublished() uint32 { + if x != nil { + return x.Published + } + return 0 +} + +func (x *TelemetryData_EventsTelemetry) GetBatchesSucceeded() uint32 { + if x != nil { + return x.BatchesSucceeded + } + return 0 +} + +func (x *TelemetryData_EventsTelemetry) GetBatchesFailed() uint32 { + if x != nil { + return x.BatchesFailed + } + return 0 +} + type TelemetryData_ResolveLatency struct { state protoimpl.MessageState `protogen:"open.v1"` Sum uint32 `protobuf:"varint,1,opt,name=sum,proto3" json:"sum,omitempty"` @@ -1278,7 +1363,7 @@ type TelemetryData_ResolveLatency struct { func (x *TelemetryData_ResolveLatency) Reset() { *x = TelemetryData_ResolveLatency{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[19] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1290,7 +1375,7 @@ func (x *TelemetryData_ResolveLatency) String() string { func (*TelemetryData_ResolveLatency) ProtoMessage() {} func (x *TelemetryData_ResolveLatency) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[19] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1303,7 +1388,7 @@ func (x *TelemetryData_ResolveLatency) ProtoReflect() protoreflect.Message { // Deprecated: Use TelemetryData_ResolveLatency.ProtoReflect.Descriptor instead. func (*TelemetryData_ResolveLatency) Descriptor() ([]byte, []int) { - return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 0} + return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 2} } func (x *TelemetryData_ResolveLatency) GetSum() uint32 { @@ -1344,7 +1429,7 @@ type TelemetryData_ResolveRate struct { func (x *TelemetryData_ResolveRate) Reset() { *x = TelemetryData_ResolveRate{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[20] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1356,7 +1441,7 @@ func (x *TelemetryData_ResolveRate) String() string { func (*TelemetryData_ResolveRate) ProtoMessage() {} func (x *TelemetryData_ResolveRate) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[20] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1369,7 +1454,7 @@ func (x *TelemetryData_ResolveRate) ProtoReflect() protoreflect.Message { // Deprecated: Use TelemetryData_ResolveRate.ProtoReflect.Descriptor instead. func (*TelemetryData_ResolveRate) Descriptor() ([]byte, []int) { - return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 1} + return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 3} } func (x *TelemetryData_ResolveRate) GetCount() uint32 { @@ -1395,7 +1480,7 @@ type TelemetryData_StateAge struct { func (x *TelemetryData_StateAge) Reset() { *x = TelemetryData_StateAge{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[21] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1407,7 +1492,7 @@ func (x *TelemetryData_StateAge) String() string { func (*TelemetryData_StateAge) ProtoMessage() {} func (x *TelemetryData_StateAge) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[21] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1420,7 +1505,7 @@ func (x *TelemetryData_StateAge) ProtoReflect() protoreflect.Message { // Deprecated: Use TelemetryData_StateAge.ProtoReflect.Descriptor instead. func (*TelemetryData_StateAge) Descriptor() ([]byte, []int) { - return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 2} + return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 4} } func (x *TelemetryData_StateAge) GetLastStateUpdate() uint64 { @@ -1440,7 +1525,7 @@ type TelemetryData_BucketSpan struct { func (x *TelemetryData_BucketSpan) Reset() { *x = TelemetryData_BucketSpan{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[22] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1452,7 +1537,7 @@ func (x *TelemetryData_BucketSpan) String() string { func (*TelemetryData_BucketSpan) ProtoMessage() {} func (x *TelemetryData_BucketSpan) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[22] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1465,7 +1550,7 @@ func (x *TelemetryData_BucketSpan) ProtoReflect() protoreflect.Message { // Deprecated: Use TelemetryData_BucketSpan.ProtoReflect.Descriptor instead. func (*TelemetryData_BucketSpan) Descriptor() ([]byte, []int) { - return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 3} + return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 5} } func (x *TelemetryData_BucketSpan) GetOffset() int32 { @@ -1496,7 +1581,7 @@ type TelemetryData_ApplyDedupTelemetry struct { func (x *TelemetryData_ApplyDedupTelemetry) Reset() { *x = TelemetryData_ApplyDedupTelemetry{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[23] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1508,7 +1593,7 @@ func (x *TelemetryData_ApplyDedupTelemetry) String() string { func (*TelemetryData_ApplyDedupTelemetry) ProtoMessage() {} func (x *TelemetryData_ApplyDedupTelemetry) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[23] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1521,7 +1606,7 @@ func (x *TelemetryData_ApplyDedupTelemetry) ProtoReflect() protoreflect.Message // Deprecated: Use TelemetryData_ApplyDedupTelemetry.ProtoReflect.Descriptor instead. func (*TelemetryData_ApplyDedupTelemetry) Descriptor() ([]byte, []int) { - return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 4} + return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 6} } func (x *TelemetryData_ApplyDedupTelemetry) GetAppliesTotal() uint32 { @@ -1576,7 +1661,7 @@ type TelemetryData_ProviderInitRate struct { func (x *TelemetryData_ProviderInitRate) Reset() { *x = TelemetryData_ProviderInitRate{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[24] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1588,7 +1673,7 @@ func (x *TelemetryData_ProviderInitRate) String() string { func (*TelemetryData_ProviderInitRate) ProtoMessage() {} func (x *TelemetryData_ProviderInitRate) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[24] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1601,7 +1686,7 @@ func (x *TelemetryData_ProviderInitRate) ProtoReflect() protoreflect.Message { // Deprecated: Use TelemetryData_ProviderInitRate.ProtoReflect.Descriptor instead. func (*TelemetryData_ProviderInitRate) Descriptor() ([]byte, []int) { - return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 5} + return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 7} } func (x *TelemetryData_ProviderInitRate) GetCount() uint32 { @@ -1638,7 +1723,7 @@ type FlagAssigned_AppliedFlag struct { func (x *FlagAssigned_AppliedFlag) Reset() { *x = FlagAssigned_AppliedFlag{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[26] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1650,7 +1735,7 @@ func (x *FlagAssigned_AppliedFlag) String() string { func (*FlagAssigned_AppliedFlag) ProtoMessage() {} func (x *FlagAssigned_AppliedFlag) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[26] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1766,7 +1851,7 @@ type FlagAssigned_AssignmentInfo struct { func (x *FlagAssigned_AssignmentInfo) Reset() { *x = FlagAssigned_AssignmentInfo{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[27] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1778,7 +1863,7 @@ func (x *FlagAssigned_AssignmentInfo) String() string { func (*FlagAssigned_AssignmentInfo) ProtoMessage() {} func (x *FlagAssigned_AssignmentInfo) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[27] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1817,7 +1902,7 @@ type FlagAssigned_DefaultAssignment struct { func (x *FlagAssigned_DefaultAssignment) Reset() { *x = FlagAssigned_DefaultAssignment{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[28] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1829,7 +1914,7 @@ func (x *FlagAssigned_DefaultAssignment) String() string { func (*FlagAssigned_DefaultAssignment) ProtoMessage() {} func (x *FlagAssigned_DefaultAssignment) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[28] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1863,7 +1948,7 @@ type ClientResolveInfo_EvaluationContextSchemaInstance struct { func (x *ClientResolveInfo_EvaluationContextSchemaInstance) Reset() { *x = ClientResolveInfo_EvaluationContextSchemaInstance{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[29] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1875,7 +1960,7 @@ func (x *ClientResolveInfo_EvaluationContextSchemaInstance) String() string { func (*ClientResolveInfo_EvaluationContextSchemaInstance) ProtoMessage() {} func (x *ClientResolveInfo_EvaluationContextSchemaInstance) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[29] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1911,7 +1996,7 @@ type FlagResolveInfo_VariantResolveInfo struct { func (x *FlagResolveInfo_VariantResolveInfo) Reset() { *x = FlagResolveInfo_VariantResolveInfo{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[31] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1923,7 +2008,7 @@ func (x *FlagResolveInfo_VariantResolveInfo) String() string { func (*FlagResolveInfo_VariantResolveInfo) ProtoMessage() {} func (x *FlagResolveInfo_VariantResolveInfo) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[31] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1967,7 +2052,7 @@ const file_confidence_flags_resolver_v1_internal_api_proto_rawDesc = "" + "\x15IngestFlagLogsRequest\x12\x1d\n" + "\n" + "account_id\x18\x01 \x01(\tR\taccountId\x12H\n" + - "\x05batch\x18\x02 \x01(\v22.confidence.flags.resolver.v1.WriteFlagLogsRequestR\x05batch\"\xe8\f\n" + + "\x05batch\x18\x02 \x01(\v22.confidence.flags.resolver.v1.WriteFlagLogsRequestR\x05batch\"\xfc\r\n" + "\rTelemetryData\x123\n" + "\x03sdk\x18\x02 \x01(\v2!.confidence.flags.resolver.v1.SdkR\x03sdk\x12c\n" + "\x0fresolve_latency\x18\x04 \x01(\v2:.confidence.flags.resolver.v1.TelemetryData.ResolveLatencyR\x0eresolveLatency\x12Z\n" + @@ -1978,12 +2063,16 @@ const file_confidence_flags_resolver_v1_internal_api_proto_rawDesc = "" + "\x12provider_init_rate\x18\t \x03(\v2<.confidence.flags.resolver.v1.TelemetryData.ProviderInitRateR\x10providerInitRate\x12`\n" + "\vapply_dedup\x18\n" + " \x01(\v2?.confidence.flags.resolver.v1.TelemetryData.ApplyDedupTelemetryR\n" + - "applyDedup\x12'\n" + - "\x0fflush_succeeded\x18\v \x01(\rR\x0eflushSucceeded\x12!\n" + - "\fflush_failed\x18\f \x01(\rR\vflushFailed\x12)\n" + - "\x10events_published\x18\r \x01(\rR\x0feventsPublished\x126\n" + - "\x17event_batches_succeeded\x18\x0e \x01(\rR\x15eventBatchesSucceeded\x120\n" + - "\x14event_batches_failed\x18\x0f \x01(\rR\x12eventBatchesFailed\x1a\xa5\x01\n" + + "applyDedup\x12P\n" + + "\x05flush\x18\v \x01(\v2:.confidence.flags.resolver.v1.TelemetryData.FlushTelemetryR\x05flush\x12S\n" + + "\x06events\x18\f \x01(\v2;.confidence.flags.resolver.v1.TelemetryData.EventsTelemetryR\x06events\x1aF\n" + + "\x0eFlushTelemetry\x12\x1c\n" + + "\tsucceeded\x18\x01 \x01(\rR\tsucceeded\x12\x16\n" + + "\x06failed\x18\x02 \x01(\rR\x06failed\x1a\x83\x01\n" + + "\x0fEventsTelemetry\x12\x1c\n" + + "\tpublished\x18\x01 \x01(\rR\tpublished\x12+\n" + + "\x11batches_succeeded\x18\x02 \x01(\rR\x10batchesSucceeded\x12%\n" + + "\x0ebatches_failed\x18\x03 \x01(\rR\rbatchesFailed\x1a\xa5\x01\n" + "\x0eResolveLatency\x12\x10\n" + "\x03sum\x18\x01 \x01(\rR\x03sum\x12\x14\n" + "\x05count\x18\x02 \x01(\rR\x05count\x12P\n" + @@ -2118,7 +2207,7 @@ func file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP() []byte { } var file_confidence_flags_resolver_v1_internal_api_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_confidence_flags_resolver_v1_internal_api_proto_msgTypes = make([]protoimpl.MessageInfo, 32) +var file_confidence_flags_resolver_v1_internal_api_proto_msgTypes = make([]protoimpl.MessageInfo, 34) var file_confidence_flags_resolver_v1_internal_api_proto_goTypes = []any{ (FlagAssigned_DefaultAssignment_DefaultAssignmentReason)(0), // 0: confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.DefaultAssignmentReason (*WriteFlagLogsRequest)(nil), // 1: confidence.flags.resolver.v1.WriteFlagLogsRequest @@ -2140,21 +2229,23 @@ var file_confidence_flags_resolver_v1_internal_api_proto_goTypes = []any{ (*InclusionData)(nil), // 17: confidence.flags.resolver.v1.InclusionData (*ReadResult)(nil), // 18: confidence.flags.resolver.v1.ReadResult (*ReadOperationsResult)(nil), // 19: confidence.flags.resolver.v1.ReadOperationsResult - (*TelemetryData_ResolveLatency)(nil), // 20: confidence.flags.resolver.v1.TelemetryData.ResolveLatency - (*TelemetryData_ResolveRate)(nil), // 21: confidence.flags.resolver.v1.TelemetryData.ResolveRate - (*TelemetryData_StateAge)(nil), // 22: confidence.flags.resolver.v1.TelemetryData.StateAge - (*TelemetryData_BucketSpan)(nil), // 23: confidence.flags.resolver.v1.TelemetryData.BucketSpan - (*TelemetryData_ApplyDedupTelemetry)(nil), // 24: confidence.flags.resolver.v1.TelemetryData.ApplyDedupTelemetry - (*TelemetryData_ProviderInitRate)(nil), // 25: confidence.flags.resolver.v1.TelemetryData.ProviderInitRate - nil, // 26: confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry - (*FlagAssigned_AppliedFlag)(nil), // 27: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag - (*FlagAssigned_AssignmentInfo)(nil), // 28: confidence.flags.resolver.v1.FlagAssigned.AssignmentInfo - (*FlagAssigned_DefaultAssignment)(nil), // 29: confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment - (*ClientResolveInfo_EvaluationContextSchemaInstance)(nil), // 30: confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance - nil, // 31: confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry - (*FlagResolveInfo_VariantResolveInfo)(nil), // 32: confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo - (*resolver.Sdk)(nil), // 33: confidence.flags.resolver.v1.Sdk - (*timestamppb.Timestamp)(nil), // 34: google.protobuf.Timestamp + (*TelemetryData_FlushTelemetry)(nil), // 20: confidence.flags.resolver.v1.TelemetryData.FlushTelemetry + (*TelemetryData_EventsTelemetry)(nil), // 21: confidence.flags.resolver.v1.TelemetryData.EventsTelemetry + (*TelemetryData_ResolveLatency)(nil), // 22: confidence.flags.resolver.v1.TelemetryData.ResolveLatency + (*TelemetryData_ResolveRate)(nil), // 23: confidence.flags.resolver.v1.TelemetryData.ResolveRate + (*TelemetryData_StateAge)(nil), // 24: confidence.flags.resolver.v1.TelemetryData.StateAge + (*TelemetryData_BucketSpan)(nil), // 25: confidence.flags.resolver.v1.TelemetryData.BucketSpan + (*TelemetryData_ApplyDedupTelemetry)(nil), // 26: confidence.flags.resolver.v1.TelemetryData.ApplyDedupTelemetry + (*TelemetryData_ProviderInitRate)(nil), // 27: confidence.flags.resolver.v1.TelemetryData.ProviderInitRate + nil, // 28: confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry + (*FlagAssigned_AppliedFlag)(nil), // 29: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag + (*FlagAssigned_AssignmentInfo)(nil), // 30: confidence.flags.resolver.v1.FlagAssigned.AssignmentInfo + (*FlagAssigned_DefaultAssignment)(nil), // 31: confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment + (*ClientResolveInfo_EvaluationContextSchemaInstance)(nil), // 32: confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance + nil, // 33: confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry + (*FlagResolveInfo_VariantResolveInfo)(nil), // 34: confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo + (*resolver.Sdk)(nil), // 35: confidence.flags.resolver.v1.Sdk + (*timestamppb.Timestamp)(nil), // 36: google.protobuf.Timestamp } var file_confidence_flags_resolver_v1_internal_api_proto_depIdxs = []int32{ 6, // 0: confidence.flags.resolver.v1.WriteFlagLogsRequest.flag_assigned:type_name -> confidence.flags.resolver.v1.FlagAssigned @@ -2162,43 +2253,45 @@ var file_confidence_flags_resolver_v1_internal_api_proto_depIdxs = []int32{ 8, // 2: confidence.flags.resolver.v1.WriteFlagLogsRequest.client_resolve_info:type_name -> confidence.flags.resolver.v1.ClientResolveInfo 9, // 3: confidence.flags.resolver.v1.WriteFlagLogsRequest.flag_resolve_info:type_name -> confidence.flags.resolver.v1.FlagResolveInfo 1, // 4: confidence.flags.resolver.v1.IngestFlagLogsRequest.batch:type_name -> confidence.flags.resolver.v1.WriteFlagLogsRequest - 33, // 5: confidence.flags.resolver.v1.TelemetryData.sdk:type_name -> confidence.flags.resolver.v1.Sdk - 20, // 6: confidence.flags.resolver.v1.TelemetryData.resolve_latency:type_name -> confidence.flags.resolver.v1.TelemetryData.ResolveLatency - 21, // 7: confidence.flags.resolver.v1.TelemetryData.resolve_rate:type_name -> confidence.flags.resolver.v1.TelemetryData.ResolveRate - 22, // 8: confidence.flags.resolver.v1.TelemetryData.state_age:type_name -> confidence.flags.resolver.v1.TelemetryData.StateAge - 25, // 9: confidence.flags.resolver.v1.TelemetryData.provider_init_rate:type_name -> confidence.flags.resolver.v1.TelemetryData.ProviderInitRate - 24, // 10: confidence.flags.resolver.v1.TelemetryData.apply_dedup:type_name -> confidence.flags.resolver.v1.TelemetryData.ApplyDedupTelemetry - 33, // 11: confidence.flags.resolver.v1.ClientInfo.sdk:type_name -> confidence.flags.resolver.v1.Sdk - 5, // 12: confidence.flags.resolver.v1.FlagAssigned.client_info:type_name -> confidence.flags.resolver.v1.ClientInfo - 27, // 13: confidence.flags.resolver.v1.FlagAssigned.flags:type_name -> confidence.flags.resolver.v1.FlagAssigned.AppliedFlag - 30, // 14: confidence.flags.resolver.v1.ClientResolveInfo.schema:type_name -> confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance - 32, // 15: confidence.flags.resolver.v1.FlagResolveInfo.variant_resolve_info:type_name -> confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo - 16, // 16: confidence.flags.resolver.v1.WriteOperationsRequest.store_variant_op:type_name -> confidence.flags.resolver.v1.VariantData - 12, // 17: confidence.flags.resolver.v1.ReadOp.variant_read_op:type_name -> confidence.flags.resolver.v1.VariantReadOp - 13, // 18: confidence.flags.resolver.v1.ReadOp.inclusion_read_op:type_name -> confidence.flags.resolver.v1.InclusionReadOp - 14, // 19: confidence.flags.resolver.v1.ReadOperationsRequest.ops:type_name -> confidence.flags.resolver.v1.ReadOp - 16, // 20: confidence.flags.resolver.v1.ReadResult.variant_result:type_name -> confidence.flags.resolver.v1.VariantData - 17, // 21: confidence.flags.resolver.v1.ReadResult.inclusion_result:type_name -> confidence.flags.resolver.v1.InclusionData - 18, // 22: confidence.flags.resolver.v1.ReadOperationsResult.results:type_name -> confidence.flags.resolver.v1.ReadResult - 23, // 23: confidence.flags.resolver.v1.TelemetryData.ResolveLatency.buckets:type_name -> confidence.flags.resolver.v1.TelemetryData.BucketSpan - 26, // 24: confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.labels:type_name -> confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry - 28, // 25: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.assignment_info:type_name -> confidence.flags.resolver.v1.FlagAssigned.AssignmentInfo - 29, // 26: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.default_assignment:type_name -> confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment - 7, // 27: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.fallthrough_assignments:type_name -> confidence.flags.resolver.v1.FallthroughAssignment - 34, // 28: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.apply_time:type_name -> google.protobuf.Timestamp - 0, // 29: confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.reason:type_name -> confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.DefaultAssignmentReason - 31, // 30: confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.schema:type_name -> confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry - 1, // 31: confidence.flags.resolver.v1.InternalFlagLoggerService.ClientWriteFlagLogs:input_type -> confidence.flags.resolver.v1.WriteFlagLogsRequest - 10, // 32: confidence.flags.resolver.v1.InternalFlagLoggerService.WriteMaterializedOperations:input_type -> confidence.flags.resolver.v1.WriteOperationsRequest - 15, // 33: confidence.flags.resolver.v1.InternalFlagLoggerService.ReadMaterializedOperations:input_type -> confidence.flags.resolver.v1.ReadOperationsRequest - 2, // 34: confidence.flags.resolver.v1.InternalFlagLoggerService.ClientWriteFlagLogs:output_type -> confidence.flags.resolver.v1.WriteFlagLogsResponse - 11, // 35: confidence.flags.resolver.v1.InternalFlagLoggerService.WriteMaterializedOperations:output_type -> confidence.flags.resolver.v1.WriteOperationsResult - 19, // 36: confidence.flags.resolver.v1.InternalFlagLoggerService.ReadMaterializedOperations:output_type -> confidence.flags.resolver.v1.ReadOperationsResult - 34, // [34:37] is the sub-list for method output_type - 31, // [31:34] is the sub-list for method input_type - 31, // [31:31] is the sub-list for extension type_name - 31, // [31:31] is the sub-list for extension extendee - 0, // [0:31] is the sub-list for field type_name + 35, // 5: confidence.flags.resolver.v1.TelemetryData.sdk:type_name -> confidence.flags.resolver.v1.Sdk + 22, // 6: confidence.flags.resolver.v1.TelemetryData.resolve_latency:type_name -> confidence.flags.resolver.v1.TelemetryData.ResolveLatency + 23, // 7: confidence.flags.resolver.v1.TelemetryData.resolve_rate:type_name -> confidence.flags.resolver.v1.TelemetryData.ResolveRate + 24, // 8: confidence.flags.resolver.v1.TelemetryData.state_age:type_name -> confidence.flags.resolver.v1.TelemetryData.StateAge + 27, // 9: confidence.flags.resolver.v1.TelemetryData.provider_init_rate:type_name -> confidence.flags.resolver.v1.TelemetryData.ProviderInitRate + 26, // 10: confidence.flags.resolver.v1.TelemetryData.apply_dedup:type_name -> confidence.flags.resolver.v1.TelemetryData.ApplyDedupTelemetry + 20, // 11: confidence.flags.resolver.v1.TelemetryData.flush:type_name -> confidence.flags.resolver.v1.TelemetryData.FlushTelemetry + 21, // 12: confidence.flags.resolver.v1.TelemetryData.events:type_name -> confidence.flags.resolver.v1.TelemetryData.EventsTelemetry + 35, // 13: confidence.flags.resolver.v1.ClientInfo.sdk:type_name -> confidence.flags.resolver.v1.Sdk + 5, // 14: confidence.flags.resolver.v1.FlagAssigned.client_info:type_name -> confidence.flags.resolver.v1.ClientInfo + 29, // 15: confidence.flags.resolver.v1.FlagAssigned.flags:type_name -> confidence.flags.resolver.v1.FlagAssigned.AppliedFlag + 32, // 16: confidence.flags.resolver.v1.ClientResolveInfo.schema:type_name -> confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance + 34, // 17: confidence.flags.resolver.v1.FlagResolveInfo.variant_resolve_info:type_name -> confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo + 16, // 18: confidence.flags.resolver.v1.WriteOperationsRequest.store_variant_op:type_name -> confidence.flags.resolver.v1.VariantData + 12, // 19: confidence.flags.resolver.v1.ReadOp.variant_read_op:type_name -> confidence.flags.resolver.v1.VariantReadOp + 13, // 20: confidence.flags.resolver.v1.ReadOp.inclusion_read_op:type_name -> confidence.flags.resolver.v1.InclusionReadOp + 14, // 21: confidence.flags.resolver.v1.ReadOperationsRequest.ops:type_name -> confidence.flags.resolver.v1.ReadOp + 16, // 22: confidence.flags.resolver.v1.ReadResult.variant_result:type_name -> confidence.flags.resolver.v1.VariantData + 17, // 23: confidence.flags.resolver.v1.ReadResult.inclusion_result:type_name -> confidence.flags.resolver.v1.InclusionData + 18, // 24: confidence.flags.resolver.v1.ReadOperationsResult.results:type_name -> confidence.flags.resolver.v1.ReadResult + 25, // 25: confidence.flags.resolver.v1.TelemetryData.ResolveLatency.buckets:type_name -> confidence.flags.resolver.v1.TelemetryData.BucketSpan + 28, // 26: confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.labels:type_name -> confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry + 30, // 27: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.assignment_info:type_name -> confidence.flags.resolver.v1.FlagAssigned.AssignmentInfo + 31, // 28: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.default_assignment:type_name -> confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment + 7, // 29: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.fallthrough_assignments:type_name -> confidence.flags.resolver.v1.FallthroughAssignment + 36, // 30: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.apply_time:type_name -> google.protobuf.Timestamp + 0, // 31: confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.reason:type_name -> confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.DefaultAssignmentReason + 33, // 32: confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.schema:type_name -> confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry + 1, // 33: confidence.flags.resolver.v1.InternalFlagLoggerService.ClientWriteFlagLogs:input_type -> confidence.flags.resolver.v1.WriteFlagLogsRequest + 10, // 34: confidence.flags.resolver.v1.InternalFlagLoggerService.WriteMaterializedOperations:input_type -> confidence.flags.resolver.v1.WriteOperationsRequest + 15, // 35: confidence.flags.resolver.v1.InternalFlagLoggerService.ReadMaterializedOperations:input_type -> confidence.flags.resolver.v1.ReadOperationsRequest + 2, // 36: confidence.flags.resolver.v1.InternalFlagLoggerService.ClientWriteFlagLogs:output_type -> confidence.flags.resolver.v1.WriteFlagLogsResponse + 11, // 37: confidence.flags.resolver.v1.InternalFlagLoggerService.WriteMaterializedOperations:output_type -> confidence.flags.resolver.v1.WriteOperationsResult + 19, // 38: confidence.flags.resolver.v1.InternalFlagLoggerService.ReadMaterializedOperations:output_type -> confidence.flags.resolver.v1.ReadOperationsResult + 36, // [36:39] is the sub-list for method output_type + 33, // [33:36] is the sub-list for method input_type + 33, // [33:33] is the sub-list for extension type_name + 33, // [33:33] is the sub-list for extension extendee + 0, // [0:33] is the sub-list for field type_name } func init() { file_confidence_flags_resolver_v1_internal_api_proto_init() } @@ -2214,7 +2307,7 @@ func file_confidence_flags_resolver_v1_internal_api_proto_init() { (*ReadResult_VariantResult)(nil), (*ReadResult_InclusionResult)(nil), } - file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[26].OneofWrappers = []any{ + file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[28].OneofWrappers = []any{ (*FlagAssigned_AppliedFlag_AssignmentInfo)(nil), (*FlagAssigned_AppliedFlag_DefaultAssignment)(nil), } @@ -2224,7 +2317,7 @@ func file_confidence_flags_resolver_v1_internal_api_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_confidence_flags_resolver_v1_internal_api_proto_rawDesc), len(file_confidence_flags_resolver_v1_internal_api_proto_rawDesc)), NumEnums: 1, - NumMessages: 32, + NumMessages: 34, NumExtensions: 0, NumServices: 1, }, diff --git a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java index ba69ab573..566d3c562 100644 --- a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java +++ b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java @@ -71,8 +71,10 @@ private WriteFlagLogsRequest addFlushCounters(WriteFlagLogsRequest request) { return request.toBuilder() .setTelemetryData( request.getTelemetryData().toBuilder() - .setFlushSucceeded((int) counters[0]) - .setFlushFailed((int) counters[1]) + .setFlush(TelemetryData.FlushTelemetry.newBuilder() + .setSucceeded((int) counters[0]) + .setFailed((int) counters[1]) + .build()) .build()) .build(); } @@ -85,9 +87,11 @@ private WriteFlagLogsRequest addEventCounters(WriteFlagLogsRequest request) { return request.toBuilder() .setTelemetryData( request.getTelemetryData().toBuilder() - .setEventsPublished((int) counters[0]) - .setEventBatchesSucceeded((int) counters[1]) - .setEventBatchesFailed((int) counters[2]) + .setEvents(TelemetryData.EventsTelemetry.newBuilder() + .setPublished((int) counters[0]) + .setBatchesSucceeded((int) counters[1]) + .setBatchesFailed((int) counters[2]) + .build()) .build()) .build(); } diff --git a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts index 1e9b3c593..b089d19a3 100644 --- a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts +++ b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts @@ -584,19 +584,19 @@ export class ConfidenceServerProviderLocal implements Provider { providerInitRate: [], resolveRate: [], memoryBytes: 0, - flushSucceeded: 0, - flushFailed: 0, - eventsPublished: 0, - eventBatchesSucceeded: 0, - eventBatchesFailed: 0, }; } const td = request.telemetryData!; - td.flushSucceeded = this.flushSucceeded; - td.flushFailed = this.flushFailed; - td.eventsPublished = this.eventsPublished; - td.eventBatchesSucceeded = this.eventBatchesSucceeded; - td.eventBatchesFailed = this.eventBatchesFailed; + if (hasFlush) { + td.flush = { succeeded: this.flushSucceeded, failed: this.flushFailed }; + } + if (hasEvents) { + td.events = { + published: this.eventsPublished, + batchesSucceeded: this.eventBatchesSucceeded, + batchesFailed: this.eventBatchesFailed, + }; + } this.flushSucceeded = 0; this.flushFailed = 0; this.eventsPublished = 0; @@ -613,11 +613,6 @@ export class ConfidenceServerProviderLocal implements Provider { providerInitRate: [], resolveRate: [], memoryBytes: 0, - flushSucceeded: 0, - flushFailed: 0, - eventsPublished: 0, - eventBatchesSucceeded: 0, - eventBatchesFailed: 0, }; } request.telemetryData.sdk = { diff --git a/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto b/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto index 5ea5b0e21..f04b27409 100644 --- a/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto +++ b/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto @@ -66,15 +66,19 @@ message TelemetryData { ApplyDedupTelemetry apply_dedup = 10; - // Delta counters: WriteFlagLogs batch delivery outcomes since last flush. - // Populated by the host SDK after each delivery attempt. - uint32 flush_succeeded = 11; - uint32 flush_failed = 12; - - // Delta counters: event delivery stats since last flush. - uint32 events_published = 13; - uint32 event_batches_succeeded = 14; - uint32 event_batches_failed = 15; + FlushTelemetry flush = 11; + EventsTelemetry events = 12; + + message FlushTelemetry { + uint32 succeeded = 1; + uint32 failed = 2; + } + + message EventsTelemetry { + uint32 published = 1; + uint32 batches_succeeded = 2; + uint32 batches_failed = 3; + } message ResolveLatency { uint32 sum = 1; diff --git a/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2.py b/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2.py index 25154a728..d3e0a0a64 100644 --- a/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2.py +++ b/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2.py @@ -26,7 +26,7 @@ from confidence.flags.resolver.v1 import types_pb2 as confidence_dot_flags_dot_resolver_dot_v1_dot_types__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n/confidence/flags/resolver/v1/internal_api.proto\x12\x1c\x63onfidence.flags.resolver.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a(confidence/flags/resolver/v1/types.proto\"\xb6\x02\n\x14WriteFlagLogsRequest\x12\x41\n\rflag_assigned\x18\x01 \x03(\x0b\x32*.confidence.flags.resolver.v1.FlagAssigned\x12\x43\n\x0etelemetry_data\x18\x02 \x01(\x0b\x32+.confidence.flags.resolver.v1.TelemetryData\x12L\n\x13\x63lient_resolve_info\x18\x03 \x03(\x0b\x32/.confidence.flags.resolver.v1.ClientResolveInfo\x12H\n\x11\x66lag_resolve_info\x18\x04 \x03(\x0b\x32-.confidence.flags.resolver.v1.FlagResolveInfo\"\x17\n\x15WriteFlagLogsResponse\"n\n\x15IngestFlagLogsRequest\x12\x12\n\naccount_id\x18\x01 \x01(\t\x12\x41\n\x05\x62\x61tch\x18\x02 \x01(\x0b\x32\x32.confidence.flags.resolver.v1.WriteFlagLogsRequest\"\xf0\t\n\rTelemetryData\x12.\n\x03sdk\x18\x02 \x01(\x0b\x32!.confidence.flags.resolver.v1.Sdk\x12S\n\x0fresolve_latency\x18\x04 \x01(\x0b\x32:.confidence.flags.resolver.v1.TelemetryData.ResolveLatency\x12M\n\x0cresolve_rate\x18\x05 \x03(\x0b\x32\x37.confidence.flags.resolver.v1.TelemetryData.ResolveRate\x12G\n\tstate_age\x18\x06 \x01(\x0b\x32\x34.confidence.flags.resolver.v1.TelemetryData.StateAge\x12\x14\n\x0cmemory_bytes\x18\x07 \x01(\x04\x12\x18\n\x10resolver_version\x18\x08 \x01(\t\x12X\n\x12provider_init_rate\x18\t \x03(\x0b\x32<.confidence.flags.resolver.v1.TelemetryData.ProviderInitRate\x12T\n\x0b\x61pply_dedup\x18\n \x01(\x0b\x32?.confidence.flags.resolver.v1.TelemetryData.ApplyDedupTelemetry\x12\x17\n\x0f\x66lush_succeeded\x18\x0b \x01(\r\x12\x14\n\x0c\x66lush_failed\x18\x0c \x01(\r\x12\x18\n\x10\x65vents_published\x18\r \x01(\r\x12\x1f\n\x17\x65vent_batches_succeeded\x18\x0e \x01(\r\x12\x1c\n\x14\x65vent_batches_failed\x18\x0f \x01(\r\x1a\x87\x01\n\x0eResolveLatency\x12\x0b\n\x03sum\x18\x01 \x01(\r\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12G\n\x07\x62uckets\x18\x03 \x03(\x0b\x32\x36.confidence.flags.resolver.v1.TelemetryData.BucketSpan\x12\x10\n\x08ln_ratio\x18\x04 \x01(\x01\x1a,\n\x0bResolveRate\x12\r\n\x05\x63ount\x18\x01 \x01(\r\x12\x0e\n\x06reason\x18\x02 \x01(\r\x1a%\n\x08StateAge\x12\x19\n\x11last_state_update\x18\x01 \x01(\x04\x1a,\n\nBucketSpan\x12\x0e\n\x06offset\x18\x01 \x01(\x05\x12\x0e\n\x06\x63ounts\x18\x02 \x03(\r\x1a\x99\x01\n\x13\x41pplyDedupTelemetry\x12\x15\n\rapplies_total\x18\x01 \x01(\r\x12\x17\n\x0f\x61pplies_deduped\x18\x02 \x01(\r\x12\x1a\n\x12\x61pplies_not_cached\x18\x03 \x01(\r\x12\x0e\n\x06sweeps\x18\x04 \x01(\r\x12\x10\n\x08map_size\x18\x05 \x01(\r\x12\x14\n\x0cmap_capacity\x18\x06 \x01(\r\x1a\xb0\x01\n\x10ProviderInitRate\x12\r\n\x05\x63ount\x18\x01 \x01(\r\x12X\n\x06labels\x18\x03 \x03(\x0b\x32H.confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01J\x04\x08\x02\x10\x03\"g\n\nClientInfo\x12\x0e\n\x06\x63lient\x18\x01 \x01(\t\x12\x19\n\x11\x63lient_credential\x18\x02 \x01(\t\x12.\n\x03sdk\x18\x03 \x01(\x0b\x32!.confidence.flags.resolver.v1.Sdk\"\xa4\x07\n\x0c\x46lagAssigned\x12\x12\n\nresolve_id\x18\n \x01(\t\x12=\n\x0b\x63lient_info\x18\x03 \x01(\x0b\x32(.confidence.flags.resolver.v1.ClientInfo\x12\x45\n\x05\x66lags\x18\x0f \x03(\x0b\x32\x36.confidence.flags.resolver.v1.FlagAssigned.AppliedFlag\x1a\xbd\x03\n\x0b\x41ppliedFlag\x12\x0c\n\x04\x66lag\x18\x01 \x01(\t\x12\x15\n\rtargeting_key\x18\x02 \x01(\t\x12\x1e\n\x16targeting_key_selector\x18\x03 \x01(\t\x12T\n\x0f\x61ssignment_info\x18\x04 \x01(\x0b\x32\x39.confidence.flags.resolver.v1.FlagAssigned.AssignmentInfoH\x00\x12Z\n\x12\x64\x65\x66\x61ult_assignment\x18\x05 \x01(\x0b\x32<.confidence.flags.resolver.v1.FlagAssigned.DefaultAssignmentH\x00\x12\x15\n\rassignment_id\x18\x06 \x01(\t\x12\x0c\n\x04rule\x18\x07 \x01(\t\x12T\n\x17\x66\x61llthrough_assignments\x18\x08 \x03(\x0b\x32\x33.confidence.flags.resolver.v1.FallthroughAssignment\x12.\n\napply_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x0c\n\nassignment\x1a\x32\n\x0e\x41ssignmentInfo\x12\x0f\n\x07segment\x18\x01 \x01(\t\x12\x0f\n\x07variant\x18\x02 \x01(\t\x1a\x85\x02\n\x11\x44\x65\x66\x61ultAssignment\x12\x64\n\x06reason\x18\x01 \x01(\x0e\x32T.confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.DefaultAssignmentReason\"\x89\x01\n\x17\x44\x65\x66\x61ultAssignmentReason\x12)\n%DEFAULT_ASSIGNMENT_REASON_UNSPECIFIED\x10\x00\x12\x14\n\x10NO_SEGMENT_MATCH\x10\x01\x12\x1a\n\x12NO_TREATMENT_MATCH\x10\x02\x1a\x02\x08\x01\x12\x11\n\rFLAG_ARCHIVED\x10\x03\"s\n\x15\x46\x61llthroughAssignment\x12\x0c\n\x04rule\x18\x01 \x01(\t\x12\x15\n\rassignment_id\x18\x02 \x01(\t\x12\x15\n\rtargeting_key\x18\x03 \x01(\t\x12\x1e\n\x16targeting_key_selector\x18\x04 \x01(\t\"\xdf\x02\n\x11\x43lientResolveInfo\x12\x0e\n\x06\x63lient\x18\x01 \x01(\t\x12\x19\n\x11\x63lient_credential\x18\x02 \x01(\t\x12_\n\x06schema\x18\x03 \x03(\x0b\x32O.confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance\x1a\xbd\x01\n\x1f\x45valuationContextSchemaInstance\x12k\n\x06schema\x18\x01 \x03(\x0b\x32[.confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry\x1a-\n\x0bSchemaEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"\xb5\x01\n\x0f\x46lagResolveInfo\x12\x0c\n\x04\x66lag\x18\x01 \x01(\t\x12^\n\x14variant_resolve_info\x18\x02 \x03(\x0b\x32@.confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo\x1a\x34\n\x12VariantResolveInfo\x12\x0f\n\x07variant\x18\x01 \x01(\t\x12\r\n\x05\x63ount\x18\x03 \x01(\x03\"]\n\x16WriteOperationsRequest\x12\x43\n\x10store_variant_op\x18\x01 \x03(\x0b\x32).confidence.flags.resolver.v1.VariantData\"\x17\n\x15WriteOperationsResult\"D\n\rVariantReadOp\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x0c\n\x04rule\x18\x03 \x01(\t\"8\n\x0fInclusionReadOp\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\"\xa2\x01\n\x06ReadOp\x12\x46\n\x0fvariant_read_op\x18\x01 \x01(\x0b\x32+.confidence.flags.resolver.v1.VariantReadOpH\x00\x12J\n\x11inclusion_read_op\x18\x02 \x01(\x0b\x32-.confidence.flags.resolver.v1.InclusionReadOpH\x00\x42\x04\n\x02op\"J\n\x15ReadOperationsRequest\x12\x31\n\x03ops\x18\x03 \x03(\x0b\x32$.confidence.flags.resolver.v1.ReadOp\"S\n\x0bVariantData\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x0c\n\x04rule\x18\x03 \x01(\t\x12\x0f\n\x07variant\x18\x04 \x01(\t\"K\n\rInclusionData\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x13\n\x0bis_included\x18\x03 \x01(\x08\"\xa4\x01\n\nReadResult\x12\x43\n\x0evariant_result\x18\x01 \x01(\x0b\x32).confidence.flags.resolver.v1.VariantDataH\x00\x12G\n\x10inclusion_result\x18\x02 \x01(\x0b\x32+.confidence.flags.resolver.v1.InclusionDataH\x00\x42\x08\n\x06result\"Q\n\x14ReadOperationsResult\x12\x39\n\x07results\x18\x01 \x03(\x0b\x32(.confidence.flags.resolver.v1.ReadResult2\xb2\x03\n\x19InternalFlagLoggerService\x12~\n\x13\x43lientWriteFlagLogs\x12\x32.confidence.flags.resolver.v1.WriteFlagLogsRequest\x1a\x33.confidence.flags.resolver.v1.WriteFlagLogsResponse\x12\x8a\x01\n\x1bWriteMaterializedOperations\x12\x34.confidence.flags.resolver.v1.WriteOperationsRequest\x1a\x33.confidence.flags.resolver.v1.WriteOperationsResult\"\x00\x12\x87\x01\n\x1aReadMaterializedOperations\x12\x33.confidence.flags.resolver.v1.ReadOperationsRequest\x1a\x32.confidence.flags.resolver.v1.ReadOperationsResult\"\x00\x42\xad\x01\n,com.spotify.confidence.sdk.flags.resolver.v1B\x10InternalApiProtoP\x01Zigithub.com/spotify/confidence-resolver/openfeature-provider/go/confidence/internal/proto/resolverinternalb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n/confidence/flags/resolver/v1/internal_api.proto\x12\x1c\x63onfidence.flags.resolver.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a(confidence/flags/resolver/v1/types.proto\"\xb6\x02\n\x14WriteFlagLogsRequest\x12\x41\n\rflag_assigned\x18\x01 \x03(\x0b\x32*.confidence.flags.resolver.v1.FlagAssigned\x12\x43\n\x0etelemetry_data\x18\x02 \x01(\x0b\x32+.confidence.flags.resolver.v1.TelemetryData\x12L\n\x13\x63lient_resolve_info\x18\x03 \x03(\x0b\x32/.confidence.flags.resolver.v1.ClientResolveInfo\x12H\n\x11\x66lag_resolve_info\x18\x04 \x03(\x0b\x32-.confidence.flags.resolver.v1.FlagResolveInfo\"\x17\n\x15WriteFlagLogsResponse\"n\n\x15IngestFlagLogsRequest\x12\x12\n\naccount_id\x18\x01 \x01(\t\x12\x41\n\x05\x62\x61tch\x18\x02 \x01(\x0b\x32\x32.confidence.flags.resolver.v1.WriteFlagLogsRequest\"\x8e\x0b\n\rTelemetryData\x12.\n\x03sdk\x18\x02 \x01(\x0b\x32!.confidence.flags.resolver.v1.Sdk\x12S\n\x0fresolve_latency\x18\x04 \x01(\x0b\x32:.confidence.flags.resolver.v1.TelemetryData.ResolveLatency\x12M\n\x0cresolve_rate\x18\x05 \x03(\x0b\x32\x37.confidence.flags.resolver.v1.TelemetryData.ResolveRate\x12G\n\tstate_age\x18\x06 \x01(\x0b\x32\x34.confidence.flags.resolver.v1.TelemetryData.StateAge\x12\x14\n\x0cmemory_bytes\x18\x07 \x01(\x04\x12\x18\n\x10resolver_version\x18\x08 \x01(\t\x12X\n\x12provider_init_rate\x18\t \x03(\x0b\x32<.confidence.flags.resolver.v1.TelemetryData.ProviderInitRate\x12T\n\x0b\x61pply_dedup\x18\n \x01(\x0b\x32?.confidence.flags.resolver.v1.TelemetryData.ApplyDedupTelemetry\x12I\n\x05\x66lush\x18\x0b \x01(\x0b\x32:.confidence.flags.resolver.v1.TelemetryData.FlushTelemetry\x12K\n\x06\x65vents\x18\x0c \x01(\x0b\x32;.confidence.flags.resolver.v1.TelemetryData.EventsTelemetry\x1a\x33\n\x0e\x46lushTelemetry\x12\x11\n\tsucceeded\x18\x01 \x01(\r\x12\x0e\n\x06\x66\x61iled\x18\x02 \x01(\r\x1aW\n\x0f\x45ventsTelemetry\x12\x11\n\tpublished\x18\x01 \x01(\r\x12\x19\n\x11\x62\x61tches_succeeded\x18\x02 \x01(\r\x12\x16\n\x0e\x62\x61tches_failed\x18\x03 \x01(\r\x1a\x87\x01\n\x0eResolveLatency\x12\x0b\n\x03sum\x18\x01 \x01(\r\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12G\n\x07\x62uckets\x18\x03 \x03(\x0b\x32\x36.confidence.flags.resolver.v1.TelemetryData.BucketSpan\x12\x10\n\x08ln_ratio\x18\x04 \x01(\x01\x1a,\n\x0bResolveRate\x12\r\n\x05\x63ount\x18\x01 \x01(\r\x12\x0e\n\x06reason\x18\x02 \x01(\r\x1a%\n\x08StateAge\x12\x19\n\x11last_state_update\x18\x01 \x01(\x04\x1a,\n\nBucketSpan\x12\x0e\n\x06offset\x18\x01 \x01(\x05\x12\x0e\n\x06\x63ounts\x18\x02 \x03(\r\x1a\x99\x01\n\x13\x41pplyDedupTelemetry\x12\x15\n\rapplies_total\x18\x01 \x01(\r\x12\x17\n\x0f\x61pplies_deduped\x18\x02 \x01(\r\x12\x1a\n\x12\x61pplies_not_cached\x18\x03 \x01(\r\x12\x0e\n\x06sweeps\x18\x04 \x01(\r\x12\x10\n\x08map_size\x18\x05 \x01(\r\x12\x14\n\x0cmap_capacity\x18\x06 \x01(\r\x1a\xb0\x01\n\x10ProviderInitRate\x12\r\n\x05\x63ount\x18\x01 \x01(\r\x12X\n\x06labels\x18\x03 \x03(\x0b\x32H.confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01J\x04\x08\x02\x10\x03\"g\n\nClientInfo\x12\x0e\n\x06\x63lient\x18\x01 \x01(\t\x12\x19\n\x11\x63lient_credential\x18\x02 \x01(\t\x12.\n\x03sdk\x18\x03 \x01(\x0b\x32!.confidence.flags.resolver.v1.Sdk\"\xa4\x07\n\x0c\x46lagAssigned\x12\x12\n\nresolve_id\x18\n \x01(\t\x12=\n\x0b\x63lient_info\x18\x03 \x01(\x0b\x32(.confidence.flags.resolver.v1.ClientInfo\x12\x45\n\x05\x66lags\x18\x0f \x03(\x0b\x32\x36.confidence.flags.resolver.v1.FlagAssigned.AppliedFlag\x1a\xbd\x03\n\x0b\x41ppliedFlag\x12\x0c\n\x04\x66lag\x18\x01 \x01(\t\x12\x15\n\rtargeting_key\x18\x02 \x01(\t\x12\x1e\n\x16targeting_key_selector\x18\x03 \x01(\t\x12T\n\x0f\x61ssignment_info\x18\x04 \x01(\x0b\x32\x39.confidence.flags.resolver.v1.FlagAssigned.AssignmentInfoH\x00\x12Z\n\x12\x64\x65\x66\x61ult_assignment\x18\x05 \x01(\x0b\x32<.confidence.flags.resolver.v1.FlagAssigned.DefaultAssignmentH\x00\x12\x15\n\rassignment_id\x18\x06 \x01(\t\x12\x0c\n\x04rule\x18\x07 \x01(\t\x12T\n\x17\x66\x61llthrough_assignments\x18\x08 \x03(\x0b\x32\x33.confidence.flags.resolver.v1.FallthroughAssignment\x12.\n\napply_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x0c\n\nassignment\x1a\x32\n\x0e\x41ssignmentInfo\x12\x0f\n\x07segment\x18\x01 \x01(\t\x12\x0f\n\x07variant\x18\x02 \x01(\t\x1a\x85\x02\n\x11\x44\x65\x66\x61ultAssignment\x12\x64\n\x06reason\x18\x01 \x01(\x0e\x32T.confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.DefaultAssignmentReason\"\x89\x01\n\x17\x44\x65\x66\x61ultAssignmentReason\x12)\n%DEFAULT_ASSIGNMENT_REASON_UNSPECIFIED\x10\x00\x12\x14\n\x10NO_SEGMENT_MATCH\x10\x01\x12\x1a\n\x12NO_TREATMENT_MATCH\x10\x02\x1a\x02\x08\x01\x12\x11\n\rFLAG_ARCHIVED\x10\x03\"s\n\x15\x46\x61llthroughAssignment\x12\x0c\n\x04rule\x18\x01 \x01(\t\x12\x15\n\rassignment_id\x18\x02 \x01(\t\x12\x15\n\rtargeting_key\x18\x03 \x01(\t\x12\x1e\n\x16targeting_key_selector\x18\x04 \x01(\t\"\xdf\x02\n\x11\x43lientResolveInfo\x12\x0e\n\x06\x63lient\x18\x01 \x01(\t\x12\x19\n\x11\x63lient_credential\x18\x02 \x01(\t\x12_\n\x06schema\x18\x03 \x03(\x0b\x32O.confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance\x1a\xbd\x01\n\x1f\x45valuationContextSchemaInstance\x12k\n\x06schema\x18\x01 \x03(\x0b\x32[.confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry\x1a-\n\x0bSchemaEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"\xb5\x01\n\x0f\x46lagResolveInfo\x12\x0c\n\x04\x66lag\x18\x01 \x01(\t\x12^\n\x14variant_resolve_info\x18\x02 \x03(\x0b\x32@.confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo\x1a\x34\n\x12VariantResolveInfo\x12\x0f\n\x07variant\x18\x01 \x01(\t\x12\r\n\x05\x63ount\x18\x03 \x01(\x03\"]\n\x16WriteOperationsRequest\x12\x43\n\x10store_variant_op\x18\x01 \x03(\x0b\x32).confidence.flags.resolver.v1.VariantData\"\x17\n\x15WriteOperationsResult\"D\n\rVariantReadOp\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x0c\n\x04rule\x18\x03 \x01(\t\"8\n\x0fInclusionReadOp\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\"\xa2\x01\n\x06ReadOp\x12\x46\n\x0fvariant_read_op\x18\x01 \x01(\x0b\x32+.confidence.flags.resolver.v1.VariantReadOpH\x00\x12J\n\x11inclusion_read_op\x18\x02 \x01(\x0b\x32-.confidence.flags.resolver.v1.InclusionReadOpH\x00\x42\x04\n\x02op\"J\n\x15ReadOperationsRequest\x12\x31\n\x03ops\x18\x03 \x03(\x0b\x32$.confidence.flags.resolver.v1.ReadOp\"S\n\x0bVariantData\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x0c\n\x04rule\x18\x03 \x01(\t\x12\x0f\n\x07variant\x18\x04 \x01(\t\"K\n\rInclusionData\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x13\n\x0bis_included\x18\x03 \x01(\x08\"\xa4\x01\n\nReadResult\x12\x43\n\x0evariant_result\x18\x01 \x01(\x0b\x32).confidence.flags.resolver.v1.VariantDataH\x00\x12G\n\x10inclusion_result\x18\x02 \x01(\x0b\x32+.confidence.flags.resolver.v1.InclusionDataH\x00\x42\x08\n\x06result\"Q\n\x14ReadOperationsResult\x12\x39\n\x07results\x18\x01 \x03(\x0b\x32(.confidence.flags.resolver.v1.ReadResult2\xb2\x03\n\x19InternalFlagLoggerService\x12~\n\x13\x43lientWriteFlagLogs\x12\x32.confidence.flags.resolver.v1.WriteFlagLogsRequest\x1a\x33.confidence.flags.resolver.v1.WriteFlagLogsResponse\x12\x8a\x01\n\x1bWriteMaterializedOperations\x12\x34.confidence.flags.resolver.v1.WriteOperationsRequest\x1a\x33.confidence.flags.resolver.v1.WriteOperationsResult\"\x00\x12\x87\x01\n\x1aReadMaterializedOperations\x12\x33.confidence.flags.resolver.v1.ReadOperationsRequest\x1a\x32.confidence.flags.resolver.v1.ReadOperationsResult\"\x00\x42\xad\x01\n,com.spotify.confidence.sdk.flags.resolver.v1B\x10InternalApiProtoP\x01Zigithub.com/spotify/confidence-resolver/openfeature-provider/go/confidence/internal/proto/resolverinternalb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -47,65 +47,69 @@ _globals['_INGESTFLAGLOGSREQUEST']._serialized_start=494 _globals['_INGESTFLAGLOGSREQUEST']._serialized_end=604 _globals['_TELEMETRYDATA']._serialized_start=607 - _globals['_TELEMETRYDATA']._serialized_end=1871 - _globals['_TELEMETRYDATA_RESOLVELATENCY']._serialized_start=1270 - _globals['_TELEMETRYDATA_RESOLVELATENCY']._serialized_end=1405 - _globals['_TELEMETRYDATA_RESOLVERATE']._serialized_start=1407 - _globals['_TELEMETRYDATA_RESOLVERATE']._serialized_end=1451 - _globals['_TELEMETRYDATA_STATEAGE']._serialized_start=1453 - _globals['_TELEMETRYDATA_STATEAGE']._serialized_end=1490 - _globals['_TELEMETRYDATA_BUCKETSPAN']._serialized_start=1492 - _globals['_TELEMETRYDATA_BUCKETSPAN']._serialized_end=1536 - _globals['_TELEMETRYDATA_APPLYDEDUPTELEMETRY']._serialized_start=1539 - _globals['_TELEMETRYDATA_APPLYDEDUPTELEMETRY']._serialized_end=1692 - _globals['_TELEMETRYDATA_PROVIDERINITRATE']._serialized_start=1695 - _globals['_TELEMETRYDATA_PROVIDERINITRATE']._serialized_end=1871 - _globals['_TELEMETRYDATA_PROVIDERINITRATE_LABELSENTRY']._serialized_start=1820 - _globals['_TELEMETRYDATA_PROVIDERINITRATE_LABELSENTRY']._serialized_end=1865 - _globals['_CLIENTINFO']._serialized_start=1873 - _globals['_CLIENTINFO']._serialized_end=1976 - _globals['_FLAGASSIGNED']._serialized_start=1979 - _globals['_FLAGASSIGNED']._serialized_end=2911 - _globals['_FLAGASSIGNED_APPLIEDFLAG']._serialized_start=2150 - _globals['_FLAGASSIGNED_APPLIEDFLAG']._serialized_end=2595 - _globals['_FLAGASSIGNED_ASSIGNMENTINFO']._serialized_start=2597 - _globals['_FLAGASSIGNED_ASSIGNMENTINFO']._serialized_end=2647 - _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT']._serialized_start=2650 - _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT']._serialized_end=2911 - _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT_DEFAULTASSIGNMENTREASON']._serialized_start=2774 - _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT_DEFAULTASSIGNMENTREASON']._serialized_end=2911 - _globals['_FALLTHROUGHASSIGNMENT']._serialized_start=2913 - _globals['_FALLTHROUGHASSIGNMENT']._serialized_end=3028 - _globals['_CLIENTRESOLVEINFO']._serialized_start=3031 - _globals['_CLIENTRESOLVEINFO']._serialized_end=3382 - _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE']._serialized_start=3193 - _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE']._serialized_end=3382 - _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE_SCHEMAENTRY']._serialized_start=3337 - _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE_SCHEMAENTRY']._serialized_end=3382 - _globals['_FLAGRESOLVEINFO']._serialized_start=3385 - _globals['_FLAGRESOLVEINFO']._serialized_end=3566 - _globals['_FLAGRESOLVEINFO_VARIANTRESOLVEINFO']._serialized_start=3514 - _globals['_FLAGRESOLVEINFO_VARIANTRESOLVEINFO']._serialized_end=3566 - _globals['_WRITEOPERATIONSREQUEST']._serialized_start=3568 - _globals['_WRITEOPERATIONSREQUEST']._serialized_end=3661 - _globals['_WRITEOPERATIONSRESULT']._serialized_start=3663 - _globals['_WRITEOPERATIONSRESULT']._serialized_end=3686 - _globals['_VARIANTREADOP']._serialized_start=3688 - _globals['_VARIANTREADOP']._serialized_end=3756 - _globals['_INCLUSIONREADOP']._serialized_start=3758 - _globals['_INCLUSIONREADOP']._serialized_end=3814 - _globals['_READOP']._serialized_start=3817 - _globals['_READOP']._serialized_end=3979 - _globals['_READOPERATIONSREQUEST']._serialized_start=3981 - _globals['_READOPERATIONSREQUEST']._serialized_end=4055 - _globals['_VARIANTDATA']._serialized_start=4057 - _globals['_VARIANTDATA']._serialized_end=4140 - _globals['_INCLUSIONDATA']._serialized_start=4142 - _globals['_INCLUSIONDATA']._serialized_end=4217 - _globals['_READRESULT']._serialized_start=4220 - _globals['_READRESULT']._serialized_end=4384 - _globals['_READOPERATIONSRESULT']._serialized_start=4386 - _globals['_READOPERATIONSRESULT']._serialized_end=4467 - _globals['_INTERNALFLAGLOGGERSERVICE']._serialized_start=4470 - _globals['_INTERNALFLAGLOGGERSERVICE']._serialized_end=4904 + _globals['_TELEMETRYDATA']._serialized_end=2029 + _globals['_TELEMETRYDATA_FLUSHTELEMETRY']._serialized_start=1285 + _globals['_TELEMETRYDATA_FLUSHTELEMETRY']._serialized_end=1336 + _globals['_TELEMETRYDATA_EVENTSTELEMETRY']._serialized_start=1338 + _globals['_TELEMETRYDATA_EVENTSTELEMETRY']._serialized_end=1425 + _globals['_TELEMETRYDATA_RESOLVELATENCY']._serialized_start=1428 + _globals['_TELEMETRYDATA_RESOLVELATENCY']._serialized_end=1563 + _globals['_TELEMETRYDATA_RESOLVERATE']._serialized_start=1565 + _globals['_TELEMETRYDATA_RESOLVERATE']._serialized_end=1609 + _globals['_TELEMETRYDATA_STATEAGE']._serialized_start=1611 + _globals['_TELEMETRYDATA_STATEAGE']._serialized_end=1648 + _globals['_TELEMETRYDATA_BUCKETSPAN']._serialized_start=1650 + _globals['_TELEMETRYDATA_BUCKETSPAN']._serialized_end=1694 + _globals['_TELEMETRYDATA_APPLYDEDUPTELEMETRY']._serialized_start=1697 + _globals['_TELEMETRYDATA_APPLYDEDUPTELEMETRY']._serialized_end=1850 + _globals['_TELEMETRYDATA_PROVIDERINITRATE']._serialized_start=1853 + _globals['_TELEMETRYDATA_PROVIDERINITRATE']._serialized_end=2029 + _globals['_TELEMETRYDATA_PROVIDERINITRATE_LABELSENTRY']._serialized_start=1978 + _globals['_TELEMETRYDATA_PROVIDERINITRATE_LABELSENTRY']._serialized_end=2023 + _globals['_CLIENTINFO']._serialized_start=2031 + _globals['_CLIENTINFO']._serialized_end=2134 + _globals['_FLAGASSIGNED']._serialized_start=2137 + _globals['_FLAGASSIGNED']._serialized_end=3069 + _globals['_FLAGASSIGNED_APPLIEDFLAG']._serialized_start=2308 + _globals['_FLAGASSIGNED_APPLIEDFLAG']._serialized_end=2753 + _globals['_FLAGASSIGNED_ASSIGNMENTINFO']._serialized_start=2755 + _globals['_FLAGASSIGNED_ASSIGNMENTINFO']._serialized_end=2805 + _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT']._serialized_start=2808 + _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT']._serialized_end=3069 + _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT_DEFAULTASSIGNMENTREASON']._serialized_start=2932 + _globals['_FLAGASSIGNED_DEFAULTASSIGNMENT_DEFAULTASSIGNMENTREASON']._serialized_end=3069 + _globals['_FALLTHROUGHASSIGNMENT']._serialized_start=3071 + _globals['_FALLTHROUGHASSIGNMENT']._serialized_end=3186 + _globals['_CLIENTRESOLVEINFO']._serialized_start=3189 + _globals['_CLIENTRESOLVEINFO']._serialized_end=3540 + _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE']._serialized_start=3351 + _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE']._serialized_end=3540 + _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE_SCHEMAENTRY']._serialized_start=3495 + _globals['_CLIENTRESOLVEINFO_EVALUATIONCONTEXTSCHEMAINSTANCE_SCHEMAENTRY']._serialized_end=3540 + _globals['_FLAGRESOLVEINFO']._serialized_start=3543 + _globals['_FLAGRESOLVEINFO']._serialized_end=3724 + _globals['_FLAGRESOLVEINFO_VARIANTRESOLVEINFO']._serialized_start=3672 + _globals['_FLAGRESOLVEINFO_VARIANTRESOLVEINFO']._serialized_end=3724 + _globals['_WRITEOPERATIONSREQUEST']._serialized_start=3726 + _globals['_WRITEOPERATIONSREQUEST']._serialized_end=3819 + _globals['_WRITEOPERATIONSRESULT']._serialized_start=3821 + _globals['_WRITEOPERATIONSRESULT']._serialized_end=3844 + _globals['_VARIANTREADOP']._serialized_start=3846 + _globals['_VARIANTREADOP']._serialized_end=3914 + _globals['_INCLUSIONREADOP']._serialized_start=3916 + _globals['_INCLUSIONREADOP']._serialized_end=3972 + _globals['_READOP']._serialized_start=3975 + _globals['_READOP']._serialized_end=4137 + _globals['_READOPERATIONSREQUEST']._serialized_start=4139 + _globals['_READOPERATIONSREQUEST']._serialized_end=4213 + _globals['_VARIANTDATA']._serialized_start=4215 + _globals['_VARIANTDATA']._serialized_end=4298 + _globals['_INCLUSIONDATA']._serialized_start=4300 + _globals['_INCLUSIONDATA']._serialized_end=4375 + _globals['_READRESULT']._serialized_start=4378 + _globals['_READRESULT']._serialized_end=4542 + _globals['_READOPERATIONSRESULT']._serialized_start=4544 + _globals['_READOPERATIONSRESULT']._serialized_end=4625 + _globals['_INTERNALFLAGLOGGERSERVICE']._serialized_start=4628 + _globals['_INTERNALFLAGLOGGERSERVICE']._serialized_end=5062 # @@protoc_insertion_point(module_scope) diff --git a/openfeature-provider/python/src/confidence/provider.py b/openfeature-provider/python/src/confidence/provider.py index c1a1eca5f..54660e954 100644 --- a/openfeature-provider/python/src/confidence/provider.py +++ b/openfeature-provider/python/src/confidence/provider.py @@ -946,14 +946,14 @@ def _write_logs(self, log_data: bytes) -> None: for k, v in self._init_labels.items(): init_rate.labels[k] = v if has_flush: - request.telemetry_data.flush_succeeded = flush_ok - request.telemetry_data.flush_failed = flush_err + request.telemetry_data.flush.succeeded = flush_ok + request.telemetry_data.flush.failed = flush_err self._flush_succeeded = 0 self._flush_failed = 0 if has_events: - request.telemetry_data.events_published = ev_published - request.telemetry_data.event_batches_succeeded = ev_ok - request.telemetry_data.event_batches_failed = ev_err + request.telemetry_data.events.published = ev_published + request.telemetry_data.events.batches_succeeded = ev_ok + request.telemetry_data.events.batches_failed = ev_err log_data = request.SerializeToString() try: From 6490dc81c60b62568d18f2919adcab88950cf222 Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Wed, 2 Sep 2026 16:19:59 +0200 Subject: [PATCH 14/25] fix(java): fmt ProviderTelemetryResolver.java Co-Authored-By: Claude Opus 4.6 (1M context) --- .../sdk/ProviderTelemetryResolver.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java index 566d3c562..4f33a16f7 100644 --- a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java +++ b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java @@ -71,10 +71,11 @@ private WriteFlagLogsRequest addFlushCounters(WriteFlagLogsRequest request) { return request.toBuilder() .setTelemetryData( request.getTelemetryData().toBuilder() - .setFlush(TelemetryData.FlushTelemetry.newBuilder() - .setSucceeded((int) counters[0]) - .setFailed((int) counters[1]) - .build()) + .setFlush( + TelemetryData.FlushTelemetry.newBuilder() + .setSucceeded((int) counters[0]) + .setFailed((int) counters[1]) + .build()) .build()) .build(); } @@ -87,11 +88,12 @@ private WriteFlagLogsRequest addEventCounters(WriteFlagLogsRequest request) { return request.toBuilder() .setTelemetryData( request.getTelemetryData().toBuilder() - .setEvents(TelemetryData.EventsTelemetry.newBuilder() - .setPublished((int) counters[0]) - .setBatchesSucceeded((int) counters[1]) - .setBatchesFailed((int) counters[2]) - .build()) + .setEvents( + TelemetryData.EventsTelemetry.newBuilder() + .setPublished((int) counters[0]) + .setBatchesSucceeded((int) counters[1]) + .setBatchesFailed((int) counters[2]) + .build()) .build()) .build(); } From 2c9468eaaa0debce00e2ccce8b7252b88f860c8e Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Thu, 3 Sep 2026 10:54:37 +0200 Subject: [PATCH 15/25] fix: restore drained telemetry counters on send failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On failed WriteFlagLogs send, the drained flush/events counters were lost — causing N consecutive failures to report flush_failed=1 instead of flush_failed=N. Fix: on failure, add the drained values back to the atomics so the next successful send carries the full accumulated count. Includes Go test proving 3 consecutive failures → flush_failed=3. Providers fixed: Go, JS, Java, Python. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../flag_logger/counter_restore_test.go | 109 ++++++++++++++++++ .../confidence/internal/flag_logger/grpc.go | 11 ++ .../confidence/internal/flag_logger/multi.go | 11 ++ .../confidence/sdk/GrpcWasmFlagLogger.java | 29 +++++ .../sdk/OpenFeatureLocalResolveProvider.java | 2 + .../sdk/ProviderTelemetryResolver.java | 32 ++++- .../confidence/sdk/WasmFlagLogger.java | 8 ++ .../js/src/ConfidenceServerProviderLocal.ts | 10 ++ .../python/src/confidence/provider.py | 6 + 9 files changed, 214 insertions(+), 4 deletions(-) create mode 100644 openfeature-provider/go/confidence/internal/flag_logger/counter_restore_test.go diff --git a/openfeature-provider/go/confidence/internal/flag_logger/counter_restore_test.go b/openfeature-provider/go/confidence/internal/flag_logger/counter_restore_test.go new file mode 100644 index 000000000..e64f140ad --- /dev/null +++ b/openfeature-provider/go/confidence/internal/flag_logger/counter_restore_test.go @@ -0,0 +1,109 @@ +package flag_logger + +import ( + "sync/atomic" + "testing" + + resolverv1 "github.com/spotify/confidence-resolver/openfeature-provider/go/confidence/internal/proto/resolverinternal" +) + +// TestCounterRestoreOnFailure verifies that after N consecutive failures +// followed by 1 success, the backend sees flush_failed=N (not 1). +func TestCounterRestoreOnFailure(t *testing.T) { + // Simulate the counter drain → set on request → failure → restore cycle + // using raw atomics (same logic as GrpcFlagLogger/MultiDestinationFlagLogger). + + var flushSucceeded, flushFailed atomic.Int64 + var eventsPublished, eventBatchesSucceeded, eventBatchesFailed atomic.Int64 + + drain := func() *resolverv1.TelemetryData { + fs := uint32(flushSucceeded.Swap(0)) + ff := uint32(flushFailed.Swap(0)) + ep := uint32(eventsPublished.Swap(0)) + ebs := uint32(eventBatchesSucceeded.Swap(0)) + ebf := uint32(eventBatchesFailed.Swap(0)) + td := &resolverv1.TelemetryData{} + if fs > 0 || ff > 0 { + td.Flush = &resolverv1.TelemetryData_FlushTelemetry{Succeeded: fs, Failed: ff} + } + if ep > 0 || ebs > 0 || ebf > 0 { + td.Events = &resolverv1.TelemetryData_EventsTelemetry{ + Published: ep, BatchesSucceeded: ebs, BatchesFailed: ebf, + } + } + return td + } + + restoreOnFailure := func(td *resolverv1.TelemetryData) { + flushFailed.Add(1) // record this failure + if td.Flush != nil { + flushSucceeded.Add(int64(td.Flush.Succeeded)) + flushFailed.Add(int64(td.Flush.Failed)) + } + if td.Events != nil { + eventsPublished.Add(int64(td.Events.Published)) + eventBatchesSucceeded.Add(int64(td.Events.BatchesSucceeded)) + eventBatchesFailed.Add(int64(td.Events.BatchesFailed)) + } + } + + recordSuccess := func() { + flushSucceeded.Add(1) + } + + // Simulate some event activity before flushes start + eventsPublished.Add(500) + eventBatchesSucceeded.Add(3) + eventBatchesFailed.Add(1) + + // Flush 1: drain → FAIL + td1 := drain() + restoreOnFailure(td1) + // After: flushFailed=1, eventsPublished=500, eventBatchesSucceeded=3, eventBatchesFailed=1 + + // Flush 2: drain → FAIL + td2 := drain() + restoreOnFailure(td2) + // After: flushFailed=2 (1 restored + 1 new), events restored + + // Flush 3: drain → FAIL + td3 := drain() + restoreOnFailure(td3) + // After: flushFailed=3 + + // Flush 4: drain → SUCCESS + td4 := drain() + recordSuccess() + + // Verify: the backend (td4) should see flush_failed=3 and all event counters + if td4.Flush == nil { + t.Fatal("flush telemetry should be present") + } + if td4.Flush.Failed != 3 { + t.Errorf("flush.failed: got %d, want 3", td4.Flush.Failed) + } + if td4.Flush.Succeeded != 0 { + t.Errorf("flush.succeeded: got %d, want 0", td4.Flush.Succeeded) + } + + if td4.Events == nil { + t.Fatal("events telemetry should be present") + } + if td4.Events.Published != 500 { + t.Errorf("events.published: got %d, want 500", td4.Events.Published) + } + if td4.Events.BatchesSucceeded != 3 { + t.Errorf("events.batches_succeeded: got %d, want 3", td4.Events.BatchesSucceeded) + } + if td4.Events.BatchesFailed != 1 { + t.Errorf("events.batches_failed: got %d, want 1", td4.Events.BatchesFailed) + } + + // After success: only the new success should be in the atomics + if v := flushSucceeded.Load(); v != 1 { + t.Errorf("post-success flushSucceeded: got %d, want 1", v) + } + if v := flushFailed.Load(); v != 0 { + t.Errorf("post-success flushFailed: got %d, want 0", v) + } +} diff --git a/openfeature-provider/go/confidence/internal/flag_logger/grpc.go b/openfeature-provider/go/confidence/internal/flag_logger/grpc.go index 674c48b88..d09eddd83 100644 --- a/openfeature-provider/go/confidence/internal/flag_logger/grpc.go +++ b/openfeature-provider/go/confidence/internal/flag_logger/grpc.go @@ -114,6 +114,17 @@ func (g *GrpcFlagLogger) sendAsync(request *resolverv1.WriteFlagLogsRequest) { if _, err := g.stub.ClientWriteFlagLogs(rpcCtx, request); err != nil { g.failures.Add(1) g.flushFailed.Add(1) + if td := request.TelemetryData; td != nil { + if td.Flush != nil { + g.flushSucceeded.Add(int64(td.Flush.Succeeded)) + g.flushFailed.Add(int64(td.Flush.Failed)) + } + if td.Events != nil { + g.eventsPublished.Add(int64(td.Events.Published)) + g.eventBatchesSucceeded.Add(int64(td.Events.BatchesSucceeded)) + g.eventBatchesFailed.Add(int64(td.Events.BatchesFailed)) + } + } } else { g.flushSucceeded.Add(1) g.logger.Debug("Successfully sent flag log", diff --git a/openfeature-provider/go/confidence/internal/flag_logger/multi.go b/openfeature-provider/go/confidence/internal/flag_logger/multi.go index a2314a296..6de1d74ce 100644 --- a/openfeature-provider/go/confidence/internal/flag_logger/multi.go +++ b/openfeature-provider/go/confidence/internal/flag_logger/multi.go @@ -152,6 +152,17 @@ func (m *MultiDestinationFlagLogger) Write(request *resolverv1.WriteFlagLogsRequ if lastErr != nil { m.failures.Add(1) m.flushFailed.Add(1) + if td := request.TelemetryData; td != nil { + if td.Flush != nil { + m.flushSucceeded.Add(int64(td.Flush.Succeeded)) + m.flushFailed.Add(int64(td.Flush.Failed)) + } + if td.Events != nil { + m.eventsPublished.Add(int64(td.Events.Published)) + m.eventBatchesSucceeded.Add(int64(td.Events.BatchesSucceeded)) + m.eventBatchesFailed.Add(int64(td.Events.BatchesFailed)) + } + } } else { m.flushSucceeded.Add(1) } diff --git a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java index 456559826..a8c3f0507 100644 --- a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java +++ b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java @@ -6,6 +6,7 @@ import com.spotify.confidence.sdk.flags.admin.v1.LogDestination; import com.spotify.confidence.sdk.flags.resolver.v1.IngestFlagLogsRequest; import com.spotify.confidence.sdk.flags.resolver.v1.InternalFlagLoggerServiceGrpc; +import com.spotify.confidence.sdk.flags.resolver.v1.TelemetryData; import com.spotify.confidence.sdk.flags.resolver.v1.WriteFlagLogsRequest; import io.grpc.*; import java.io.OutputStream; @@ -40,6 +41,9 @@ public class GrpcWasmFlagLogger implements WasmFlagLogger { private final AtomicLong failures = new AtomicLong(); private final AtomicLong telemetryFlushSucceeded = new AtomicLong(); private final AtomicLong telemetryFlushFailed = new AtomicLong(); + private final AtomicLong restoredEventsPublished = new AtomicLong(); + private final AtomicLong restoredEventBatchesSucceeded = new AtomicLong(); + private final AtomicLong restoredEventBatchesFailed = new AtomicLong(); private final String clientSecret; private final HttpClientFactory httpClientFactory; private final AtomicReference> logDestinations = @@ -135,6 +139,7 @@ private void sendWithFailover(WriteFlagLogsRequest request) { } catch (Exception e) { failures.incrementAndGet(); telemetryFlushFailed.incrementAndGet(); + restoreDrainedCounters(request); } return; } @@ -165,15 +170,30 @@ private void sendWithFailover(WriteFlagLogsRequest request) { } catch (Exception fallbackEx) { failures.incrementAndGet(); telemetryFlushFailed.incrementAndGet(); + restoreDrainedCounters(request); logger.warn("Fallback destination {} also failed", fallback, fallbackEx); } } else { failures.incrementAndGet(); telemetryFlushFailed.incrementAndGet(); + restoreDrainedCounters(request); } } } + private void restoreDrainedCounters(WriteFlagLogsRequest request) { + final TelemetryData td = request.getTelemetryData(); + if (td.hasFlush()) { + telemetryFlushSucceeded.addAndGet(td.getFlush().getSucceeded()); + telemetryFlushFailed.addAndGet(td.getFlush().getFailed()); + } + if (td.hasEvents()) { + restoredEventsPublished.addAndGet(td.getEvents().getPublished()); + restoredEventBatchesSucceeded.addAndGet(td.getEvents().getBatchesSucceeded()); + restoredEventBatchesFailed.addAndGet(td.getEvents().getBatchesFailed()); + } + } + private void sendToDestination(LogDestination destination, WriteFlagLogsRequest request) { switch (destination) { case LOG_DESTINATION_CLOUDFLARE: @@ -224,6 +244,15 @@ public long[] drainFlushCounters() { return new long[] {telemetryFlushSucceeded.getAndSet(0), telemetryFlushFailed.getAndSet(0)}; } + @Override + public long[] drainRestoredEventCounters() { + return new long[] { + restoredEventsPublished.getAndSet(0), + restoredEventBatchesSucceeded.getAndSet(0), + restoredEventBatchesFailed.getAndSet(0) + }; + } + /** * Shutdown the executor service and wait for pending async writes to complete. This method will * block for up to the configured shutdown timeout (default 10 seconds) waiting for pending log diff --git a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java index 7504996c8..8d416ebce 100644 --- a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java +++ b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java @@ -213,6 +213,7 @@ public OpenFeatureLocalResolveProvider( flagLogger::write, wasmFlagLogger::drainFlushCounters, this::drainEventCounters, + wasmFlagLogger::drainRestoredEventCounters, SDK, initLabels, providerLogSink -> @@ -289,6 +290,7 @@ public OpenFeatureLocalResolveProvider( wasmFlagLogger::write, wasmFlagLogger::drainFlushCounters, this::drainEventCounters, + wasmFlagLogger::drainRestoredEventCounters, SDK, Map.of(), providerLogSink -> diff --git a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java index 4f33a16f7..f4f2a32ef 100644 --- a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java +++ b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/ProviderTelemetryResolver.java @@ -18,6 +18,7 @@ final class ProviderTelemetryResolver implements LocalResolver { private final Consumer logSink; private final Supplier flushCounterDrain; private final Supplier eventCounterDrain; + private final Supplier restoredEventCounterDrain; private final Sdk sdk; private final Map labels; private final LocalResolver delegate; @@ -47,9 +48,28 @@ final class ProviderTelemetryResolver implements LocalResolver { Sdk sdk, Map labels, Function, LocalResolver> innerFactory) { + this( + logSink, + flushCounterDrain, + eventCounterDrain, + () -> new long[] {0, 0, 0}, + sdk, + labels, + innerFactory); + } + + ProviderTelemetryResolver( + Consumer logSink, + Supplier flushCounterDrain, + Supplier eventCounterDrain, + Supplier restoredEventCounterDrain, + Sdk sdk, + Map labels, + Function, LocalResolver> innerFactory) { this.logSink = logSink; this.flushCounterDrain = flushCounterDrain; this.eventCounterDrain = eventCounterDrain; + this.restoredEventCounterDrain = restoredEventCounterDrain; this.sdk = sdk; this.labels = Map.copyOf(labels); this.delegate = innerFactory.apply(this::writeLogs); @@ -82,7 +102,11 @@ private WriteFlagLogsRequest addFlushCounters(WriteFlagLogsRequest request) { private WriteFlagLogsRequest addEventCounters(WriteFlagLogsRequest request) { final long[] counters = eventCounterDrain.get(); - if (counters[0] == 0 && counters[1] == 0 && counters[2] == 0) { + final long[] restored = restoredEventCounterDrain.get(); + final long published = counters[0] + restored[0]; + final long succeeded = counters[1] + restored[1]; + final long failed = counters[2] + restored[2]; + if (published == 0 && succeeded == 0 && failed == 0) { return request; } return request.toBuilder() @@ -90,9 +114,9 @@ private WriteFlagLogsRequest addEventCounters(WriteFlagLogsRequest request) { request.getTelemetryData().toBuilder() .setEvents( TelemetryData.EventsTelemetry.newBuilder() - .setPublished((int) counters[0]) - .setBatchesSucceeded((int) counters[1]) - .setBatchesFailed((int) counters[2]) + .setPublished((int) published) + .setBatchesSucceeded((int) succeeded) + .setBatchesFailed((int) failed) .build()) .build()) .build(); diff --git a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/WasmFlagLogger.java b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/WasmFlagLogger.java index b1dc50eab..dcfff5f90 100644 --- a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/WasmFlagLogger.java +++ b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/WasmFlagLogger.java @@ -26,4 +26,12 @@ default void updateLogRouting(List destinations, String accountI default long[] drainFlushCounters() { return new long[] {0, 0}; } + + /** + * Drains event counters restored from failed sends. Returns [published, succeeded, failed]. These + * are merged with the provider's own event counters before the next send. + */ + default long[] drainRestoredEventCounters() { + return new long[] {0, 0, 0}; + } } diff --git a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts index b089d19a3..d6247c7ae 100644 --- a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts +++ b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts @@ -521,6 +521,11 @@ export class ConfidenceServerProviderLocal implements Provider { this.initTelemetryState = 'sending'; writeFlagLogRequest = this.addProviderInitTelemetry(writeFlagLogRequest); } + const drainedFlushSucceeded = this.flushSucceeded; + const drainedFlushFailed = this.flushFailed; + const drainedEventsPublished = this.eventsPublished; + const drainedEventBatchesSucceeded = this.eventBatchesSucceeded; + const drainedEventBatchesFailed = this.eventBatchesFailed; writeFlagLogRequest = this.addFlushDeliveryTelemetry(writeFlagLogRequest); try { await this.sendFlagLogs(writeFlagLogRequest, signal); @@ -530,6 +535,11 @@ export class ConfidenceServerProviderLocal implements Provider { } } catch (error) { this.flushFailed++; + this.flushSucceeded += drainedFlushSucceeded; + this.flushFailed += drainedFlushFailed; + this.eventsPublished += drainedEventsPublished; + this.eventBatchesSucceeded += drainedEventBatchesSucceeded; + this.eventBatchesFailed += drainedEventBatchesFailed; if (includeInit) { this.initTelemetryState = 'pending'; } diff --git a/openfeature-provider/python/src/confidence/provider.py b/openfeature-provider/python/src/confidence/provider.py index 54660e954..2aa7d1521 100644 --- a/openfeature-provider/python/src/confidence/provider.py +++ b/openfeature-provider/python/src/confidence/provider.py @@ -960,6 +960,12 @@ def _write_logs(self, log_data: bytes) -> None: self._flag_logger.write(log_data) except Exception: self._flush_failed += 1 + self._flush_succeeded += flush_ok + self._flush_failed += flush_err + with self._event_stats_lock: + self._event_telemetry_published += ev_published + self._event_telemetry_succeeded += ev_ok + self._event_telemetry_failed += ev_err if include_init: with self._init_telemetry_lock: self._init_telemetry_state = "pending" From a34cdc3901582f15f0095a14dd5f708822812457 Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Thu, 3 Sep 2026 11:06:44 +0200 Subject: [PATCH 16/25] refactor(js): co-locate drain and restore for flush/events counters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace fragile save-before-drain + restore-from-saved pattern with restoreDrainedCounters() that reads values directly from the encoded request on failure. The drain stays in addFlushDeliveryTelemetry, the restore reads from the same proto — no coupling through captured locals. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../js/src/ConfidenceServerProviderLocal.ts | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts index d6247c7ae..ab305bc92 100644 --- a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts +++ b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts @@ -521,11 +521,6 @@ export class ConfidenceServerProviderLocal implements Provider { this.initTelemetryState = 'sending'; writeFlagLogRequest = this.addProviderInitTelemetry(writeFlagLogRequest); } - const drainedFlushSucceeded = this.flushSucceeded; - const drainedFlushFailed = this.flushFailed; - const drainedEventsPublished = this.eventsPublished; - const drainedEventBatchesSucceeded = this.eventBatchesSucceeded; - const drainedEventBatchesFailed = this.eventBatchesFailed; writeFlagLogRequest = this.addFlushDeliveryTelemetry(writeFlagLogRequest); try { await this.sendFlagLogs(writeFlagLogRequest, signal); @@ -535,11 +530,7 @@ export class ConfidenceServerProviderLocal implements Provider { } } catch (error) { this.flushFailed++; - this.flushSucceeded += drainedFlushSucceeded; - this.flushFailed += drainedFlushFailed; - this.eventsPublished += drainedEventsPublished; - this.eventBatchesSucceeded += drainedEventBatchesSucceeded; - this.eventBatchesFailed += drainedEventBatchesFailed; + this.restoreDrainedCounters(writeFlagLogRequest); if (includeInit) { this.initTelemetryState = 'pending'; } @@ -581,6 +572,24 @@ export class ConfidenceServerProviderLocal implements Provider { } } + private restoreDrainedCounters(encodedWriteFlagLogRequest: Uint8Array): void { + try { + const request = WriteFlagLogsRequest.decode(encodedWriteFlagLogRequest); + const td = request.telemetryData; + if (td?.flush) { + this.flushSucceeded += td.flush.succeeded; + this.flushFailed += td.flush.failed; + } + if (td?.events) { + this.eventsPublished += td.events.published; + this.eventBatchesSucceeded += td.events.batchesSucceeded; + this.eventBatchesFailed += td.events.batchesFailed; + } + } catch { + // Best-effort restore — don't mask the original send error + } + } + private addFlushDeliveryTelemetry(encodedWriteFlagLogRequest: Uint8Array): Uint8Array { const hasFlush = this.flushSucceeded > 0 || this.flushFailed > 0; const hasEvents = this.eventsPublished > 0 || this.eventBatchesSucceeded > 0 || this.eventBatchesFailed > 0; From b3ddbed21bd5e5b4b7d79e540ddd346cd370dc9c Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Thu, 3 Sep 2026 11:09:37 +0200 Subject: [PATCH 17/25] refactor(python): read drained counters from request proto on failure Replace saved-before-drain locals with reading values from the request proto on failure, matching the JS/Go/Java pattern. Event counter drain also moved inside the rewrite block under _event_stats_lock. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../python/src/confidence/provider.py | 53 +++++++++++-------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/openfeature-provider/python/src/confidence/provider.py b/openfeature-provider/python/src/confidence/provider.py index 2aa7d1521..bb22479d1 100644 --- a/openfeature-provider/python/src/confidence/provider.py +++ b/openfeature-provider/python/src/confidence/provider.py @@ -919,19 +919,16 @@ def _write_logs(self, log_data: bytes) -> None: self._init_telemetry_state = "sending" include_init = True - flush_ok = self._flush_succeeded - flush_err = self._flush_failed + has_flush = self._flush_succeeded > 0 or self._flush_failed > 0 with self._event_stats_lock: - ev_published = self._event_telemetry_published - ev_ok = self._event_telemetry_succeeded - ev_err = self._event_telemetry_failed - self._event_telemetry_published = 0 - self._event_telemetry_succeeded = 0 - self._event_telemetry_failed = 0 - has_flush = flush_ok > 0 or flush_err > 0 - has_events = ev_published > 0 or ev_ok > 0 or ev_err > 0 + has_events = ( + self._event_telemetry_published > 0 + or self._event_telemetry_succeeded > 0 + or self._event_telemetry_failed > 0 + ) need_rewrite = include_init or has_flush or has_events + request = None if need_rewrite: request = internal_api_pb2.WriteFlagLogsRequest.FromString(log_data) if include_init: @@ -946,26 +943,40 @@ def _write_logs(self, log_data: bytes) -> None: for k, v in self._init_labels.items(): init_rate.labels[k] = v if has_flush: - request.telemetry_data.flush.succeeded = flush_ok - request.telemetry_data.flush.failed = flush_err + request.telemetry_data.flush.succeeded = self._flush_succeeded + request.telemetry_data.flush.failed = self._flush_failed self._flush_succeeded = 0 self._flush_failed = 0 if has_events: - request.telemetry_data.events.published = ev_published - request.telemetry_data.events.batches_succeeded = ev_ok - request.telemetry_data.events.batches_failed = ev_err + with self._event_stats_lock: + request.telemetry_data.events.published = ( + self._event_telemetry_published + ) + request.telemetry_data.events.batches_succeeded = ( + self._event_telemetry_succeeded + ) + request.telemetry_data.events.batches_failed = ( + self._event_telemetry_failed + ) + self._event_telemetry_published = 0 + self._event_telemetry_succeeded = 0 + self._event_telemetry_failed = 0 log_data = request.SerializeToString() try: self._flag_logger.write(log_data) except Exception: self._flush_failed += 1 - self._flush_succeeded += flush_ok - self._flush_failed += flush_err - with self._event_stats_lock: - self._event_telemetry_published += ev_published - self._event_telemetry_succeeded += ev_ok - self._event_telemetry_failed += ev_err + if request is not None: + td = request.telemetry_data + self._flush_succeeded += td.flush.succeeded + self._flush_failed += td.flush.failed + with self._event_stats_lock: + self._event_telemetry_published += td.events.published + self._event_telemetry_succeeded += ( + td.events.batches_succeeded + ) + self._event_telemetry_failed += td.events.batches_failed if include_init: with self._init_telemetry_lock: self._init_telemetry_state = "pending" From 9095ed6821e8d75a40d75da11f7265bf3a3c4ff7 Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Thu, 3 Sep 2026 11:15:44 +0200 Subject: [PATCH 18/25] fix: address all review findings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #1 Python flush counter race: protect _flush_succeeded/_flush_failed with _event_stats_lock (read, drain, restore all under lock). #2 Cloudflare cross-queue KV race: merge update_prometheus_kv and update_events_kv into single update_kv_snapshot — one read-modify- write per call, no cross-queue clobber. #3 Java silent exception: add logger.warn in empty-destinations catch. #4 Go drain/restore duplication: extract TelemetryCounters struct with DrainAndStamp, RestoreOnFailure, RecordEventBatch. Both grpc.go and multi.go embed it — ~47 lines of duplication removed. #5 JS double decode/encode: merge addProviderInitTelemetry and addFlushDeliveryTelemetry into single enrichTelemetry method — one decode/encode pass on first flush. Co-Authored-By: Claude Opus 4.6 (1M context) --- confidence-cloudflare-resolver/src/lib.rs | 62 ++++++---------- .../confidence/internal/flag_logger/grpc.go | 67 +++-------------- .../confidence/internal/flag_logger/multi.go | 66 +++-------------- .../flag_logger/telemetry_counters.go | 74 +++++++++++++++++++ .../confidence/sdk/GrpcWasmFlagLogger.java | 1 + .../js/src/ConfidenceServerProviderLocal.ts | 32 +++----- .../python/src/confidence/provider.py | 33 +++++---- 7 files changed, 146 insertions(+), 189 deletions(-) create mode 100644 openfeature-provider/go/confidence/internal/flag_logger/telemetry_counters.go diff --git a/confidence-cloudflare-resolver/src/lib.rs b/confidence-cloudflare-resolver/src/lib.rs index d57fdae0d..5db136f87 100644 --- a/confidence-cloudflare-resolver/src/lib.rs +++ b/confidence-cloudflare-resolver/src/lib.rs @@ -759,7 +759,7 @@ async fn consume_flag_logs( }; if let Ok(kv) = env.kv("CONFIDENCE_METRICS_KV") { - update_prometheus_kv(&kv, &req, Some(delivered)).await; + update_kv_snapshot(&kv, req.telemetry_data.as_ref(), Some(delivered), None).await; } if !delivered { @@ -792,26 +792,28 @@ async fn deliver_flag_logs( } } -/// Accumulate telemetry deltas from all isolates into a cumulative -/// `TelemetrySnapshot` stored in KV, then write its Prometheus text -/// representation for the /metrics endpoint. +/// Single read-modify-write of the KV-backed cumulative telemetry snapshot. /// -/// `flush_result` records the outcome of the batch delivery: `Some(true)` -/// for success, `Some(false)` for failure, `None` to skip. +/// Merges flag-log telemetry deltas, flush delivery results, and event +/// delivery results into one KV update — avoiding cross-queue races that +/// would occur if flag-log and event consumers each did independent +/// read-modify-write cycles on the same "snapshot" key. /// -/// Note: concurrent queue consumer invocations can race on KV read-modify-write. -/// Acceptable for metrics — at worst one batch's deltas are lost, not cumulative state. -async fn update_prometheus_kv( +/// Note: concurrent invocations of the *same* queue can still race on +/// KV read-modify-write. Acceptable for metrics — at worst one batch's +/// deltas are lost, not cumulative state. +async fn update_kv_snapshot( kv: &kv::KvStore, - req: &WriteFlagLogsRequest, + telemetry_delta: Option<&confidence_resolver::proto::confidence::flags::resolver::v1::TelemetryData>, flush_result: Option, + event_result: Option<(u64, bool)>, ) { let mut cumulative = match kv.get("snapshot").text().await { Ok(Some(text)) => serde_json::from_str::(&text).unwrap_or_default(), _ => TelemetrySnapshot::default(), }; - if let Some(td) = &req.telemetry_data { + if let Some(td) = telemetry_delta { cumulative.accumulate_delta(td); } @@ -825,6 +827,16 @@ async fn update_prometheus_kv( None => {} } + if let Some((event_count, succeeded)) = event_result { + if succeeded { + cumulative.events.published = cumulative.events.published.wrapping_add(event_count); + cumulative.events.batches_succeeded = + cumulative.events.batches_succeeded.wrapping_add(1); + } else { + cumulative.events.batches_failed = cumulative.events.batches_failed.wrapping_add(1); + } + } + let prom_text = cumulative.to_prometheus( "cf-resolver", &confidence_resolver::telemetry::PrometheusConfig::default(), @@ -1041,7 +1053,7 @@ async fn consume_events_queue( }; if let Ok(kv) = env.kv("CONFIDENCE_METRICS_KV") { - update_events_kv(&kv, event_count, delivered).await; + update_kv_snapshot(&kv, None, None, Some((event_count, delivered))).await; } if !delivered { @@ -1053,32 +1065,6 @@ async fn consume_events_queue( Ok(()) } -async fn update_events_kv(kv: &kv::KvStore, event_count: u64, succeeded: bool) { - let mut cumulative = match kv.get("snapshot").text().await { - Ok(Some(text)) => serde_json::from_str::(&text).unwrap_or_default(), - _ => TelemetrySnapshot::default(), - }; - - if succeeded { - cumulative.events.published = cumulative.events.published.wrapping_add(event_count); - cumulative.events.batches_succeeded = cumulative.events.batches_succeeded.wrapping_add(1); - } else { - cumulative.events.batches_failed = cumulative.events.batches_failed.wrapping_add(1); - } - - let prom_text = cumulative.to_prometheus( - "cf-resolver", - &confidence_resolver::telemetry::PrometheusConfig::default(), - ); - - if let Ok(builder) = kv.put("snapshot", serde_json::to_string(&cumulative).unwrap_or_default()) - { - let _ = builder.execute().await; - } - if let Ok(builder) = kv.put("prometheus", prom_text) { - let _ = builder.execute().await; - } -} async fn send_events(body: &serde_json::Value) -> Result { let mut init = RequestInit::new(); diff --git a/openfeature-provider/go/confidence/internal/flag_logger/grpc.go b/openfeature-provider/go/confidence/internal/flag_logger/grpc.go index d09eddd83..c43c19fc5 100644 --- a/openfeature-provider/go/confidence/internal/flag_logger/grpc.go +++ b/openfeature-provider/go/confidence/internal/flag_logger/grpc.go @@ -13,17 +13,13 @@ import ( ) type GrpcFlagLogger struct { - stub resolverv1.InternalFlagLoggerServiceClient - clientSecret string - logger *slog.Logger - wg sync.WaitGroup - attempts atomic.Int64 - failures atomic.Int64 - flushSucceeded atomic.Int64 - flushFailed atomic.Int64 - eventsPublished atomic.Int64 - eventBatchesSucceeded atomic.Int64 - eventBatchesFailed atomic.Int64 + stub resolverv1.InternalFlagLoggerServiceClient + clientSecret string + logger *slog.Logger + wg sync.WaitGroup + attempts atomic.Int64 + failures atomic.Int64 + TelemetryCounters } func NewGrpcWasmFlagLogger(stub resolverv1.InternalFlagLoggerServiceClient, clientSecret string, logger *slog.Logger) *GrpcFlagLogger { @@ -62,43 +58,11 @@ func (g *GrpcFlagLogger) Write(request *resolverv1.WriteFlagLogsRequest) { "client_resolve_info", clientResolveCount, "flag_resolve_info", flagResolveCount) - succeeded := uint32(g.flushSucceeded.Swap(0)) - failed := uint32(g.flushFailed.Swap(0)) - evPub := uint32(g.eventsPublished.Swap(0)) - evOk := uint32(g.eventBatchesSucceeded.Swap(0)) - evFail := uint32(g.eventBatchesFailed.Swap(0)) - if succeeded > 0 || failed > 0 || evPub > 0 || evOk > 0 || evFail > 0 { - if request.TelemetryData == nil { - request.TelemetryData = &resolverv1.TelemetryData{} - } - if succeeded > 0 || failed > 0 { - request.TelemetryData.Flush = &resolverv1.TelemetryData_FlushTelemetry{ - Succeeded: succeeded, - Failed: failed, - } - } - if evPub > 0 || evOk > 0 || evFail > 0 { - request.TelemetryData.Events = &resolverv1.TelemetryData_EventsTelemetry{ - Published: evPub, - BatchesSucceeded: evOk, - BatchesFailed: evFail, - } - } - } - + g.DrainAndStamp(request) g.sendAsync(request) } -func (g *GrpcFlagLogger) RecordEventBatch(eventCount int, succeeded bool) { - if succeeded { - g.eventsPublished.Add(int64(eventCount)) - g.eventBatchesSucceeded.Add(1) - } else { - g.eventBatchesFailed.Add(1) - } -} - func (g *GrpcFlagLogger) sendAsync(request *resolverv1.WriteFlagLogsRequest) { g.wg.Add(1) go func() { @@ -113,20 +77,9 @@ func (g *GrpcFlagLogger) sendAsync(request *resolverv1.WriteFlagLogsRequest) { if _, err := g.stub.ClientWriteFlagLogs(rpcCtx, request); err != nil { g.failures.Add(1) - g.flushFailed.Add(1) - if td := request.TelemetryData; td != nil { - if td.Flush != nil { - g.flushSucceeded.Add(int64(td.Flush.Succeeded)) - g.flushFailed.Add(int64(td.Flush.Failed)) - } - if td.Events != nil { - g.eventsPublished.Add(int64(td.Events.Published)) - g.eventBatchesSucceeded.Add(int64(td.Events.BatchesSucceeded)) - g.eventBatchesFailed.Add(int64(td.Events.BatchesFailed)) - } - } + g.RestoreOnFailure(request) } else { - g.flushSucceeded.Add(1) + g.FlushSucceeded.Add(1) g.logger.Debug("Successfully sent flag log", "flag_assigned", len(request.FlagAssigned), "client_resolve_info", len(request.ClientResolveInfo), diff --git a/openfeature-provider/go/confidence/internal/flag_logger/multi.go b/openfeature-provider/go/confidence/internal/flag_logger/multi.go index 6de1d74ce..5f1ce9b7d 100644 --- a/openfeature-provider/go/confidence/internal/flag_logger/multi.go +++ b/openfeature-provider/go/confidence/internal/flag_logger/multi.go @@ -20,17 +20,13 @@ type logSender func(ctx context.Context, request *resolverv1.WriteFlagLogsReques // CDN state. The first destination is primary; the second is fallback on error. // If no destinations are configured, it defaults to Spotify Edge (gRPC). type MultiDestinationFlagLogger struct { - senders map[admin.LogDestination]logSender - destinations func() []admin.LogDestination - logger *slog.Logger - wg sync.WaitGroup - attempts atomic.Int64 - failures atomic.Int64 - flushSucceeded atomic.Int64 - flushFailed atomic.Int64 - eventsPublished atomic.Int64 - eventBatchesSucceeded atomic.Int64 - eventBatchesFailed atomic.Int64 + senders map[admin.LogDestination]logSender + destinations func() []admin.LogDestination + logger *slog.Logger + wg sync.WaitGroup + attempts atomic.Int64 + failures atomic.Int64 + TelemetryCounters } // NewMultiDestinationFlagLogger creates a flag logger that routes to multiple @@ -88,29 +84,7 @@ func (m *MultiDestinationFlagLogger) Write(request *resolverv1.WriteFlagLogsRequ "client_resolve_info", clientResolveCount, "flag_resolve_info", flagResolveCount) - succeeded := uint32(m.flushSucceeded.Swap(0)) - failed := uint32(m.flushFailed.Swap(0)) - evPub := uint32(m.eventsPublished.Swap(0)) - evOk := uint32(m.eventBatchesSucceeded.Swap(0)) - evFail := uint32(m.eventBatchesFailed.Swap(0)) - if succeeded > 0 || failed > 0 || evPub > 0 || evOk > 0 || evFail > 0 { - if request.TelemetryData == nil { - request.TelemetryData = &resolverv1.TelemetryData{} - } - if succeeded > 0 || failed > 0 { - request.TelemetryData.Flush = &resolverv1.TelemetryData_FlushTelemetry{ - Succeeded: succeeded, - Failed: failed, - } - } - if evPub > 0 || evOk > 0 || evFail > 0 { - request.TelemetryData.Events = &resolverv1.TelemetryData_EventsTelemetry{ - Published: evPub, - BatchesSucceeded: evOk, - BatchesFailed: evFail, - } - } - } + m.DrainAndStamp(request) m.wg.Add(1) go func() { @@ -151,20 +125,9 @@ func (m *MultiDestinationFlagLogger) Write(request *resolverv1.WriteFlagLogsRequ if lastErr != nil { m.failures.Add(1) - m.flushFailed.Add(1) - if td := request.TelemetryData; td != nil { - if td.Flush != nil { - m.flushSucceeded.Add(int64(td.Flush.Succeeded)) - m.flushFailed.Add(int64(td.Flush.Failed)) - } - if td.Events != nil { - m.eventsPublished.Add(int64(td.Events.Published)) - m.eventBatchesSucceeded.Add(int64(td.Events.BatchesSucceeded)) - m.eventBatchesFailed.Add(int64(td.Events.BatchesFailed)) - } - } + m.RestoreOnFailure(request) } else { - m.flushSucceeded.Add(1) + m.FlushSucceeded.Add(1) } if m.attempts.Add(1)%10 == 0 { @@ -189,12 +152,3 @@ func (m *MultiDestinationFlagLogger) resolveDestinations() []admin.LogDestinatio func (m *MultiDestinationFlagLogger) Shutdown() { m.wg.Wait() } - -func (m *MultiDestinationFlagLogger) RecordEventBatch(eventCount int, succeeded bool) { - if succeeded { - m.eventsPublished.Add(int64(eventCount)) - m.eventBatchesSucceeded.Add(1) - } else { - m.eventBatchesFailed.Add(1) - } -} diff --git a/openfeature-provider/go/confidence/internal/flag_logger/telemetry_counters.go b/openfeature-provider/go/confidence/internal/flag_logger/telemetry_counters.go new file mode 100644 index 000000000..23c851566 --- /dev/null +++ b/openfeature-provider/go/confidence/internal/flag_logger/telemetry_counters.go @@ -0,0 +1,74 @@ +package flag_logger + +import ( + "sync/atomic" + + resolverv1 "github.com/spotify/confidence-resolver/openfeature-provider/go/confidence/internal/proto/resolverinternal" +) + +// TelemetryCounters holds atomic counters for flush and event delivery +// telemetry. Embedded by both GrpcFlagLogger and MultiDestinationFlagLogger +// to avoid duplicating drain/restore/record logic. +type TelemetryCounters struct { + FlushSucceeded atomic.Int64 + FlushFailed atomic.Int64 + EventsPublished atomic.Int64 + EventBatchesSucceeded atomic.Int64 + EventBatchesFailed atomic.Int64 +} + +// DrainAndStamp atomically drains all counters and stamps them onto the +// request's TelemetryData. Call before sending. +func (tc *TelemetryCounters) DrainAndStamp(request *resolverv1.WriteFlagLogsRequest) { + succeeded := uint32(tc.FlushSucceeded.Swap(0)) + failed := uint32(tc.FlushFailed.Swap(0)) + evPub := uint32(tc.EventsPublished.Swap(0)) + evOk := uint32(tc.EventBatchesSucceeded.Swap(0)) + evFail := uint32(tc.EventBatchesFailed.Swap(0)) + if succeeded > 0 || failed > 0 || evPub > 0 || evOk > 0 || evFail > 0 { + if request.TelemetryData == nil { + request.TelemetryData = &resolverv1.TelemetryData{} + } + if succeeded > 0 || failed > 0 { + request.TelemetryData.Flush = &resolverv1.TelemetryData_FlushTelemetry{ + Succeeded: succeeded, + Failed: failed, + } + } + if evPub > 0 || evOk > 0 || evFail > 0 { + request.TelemetryData.Events = &resolverv1.TelemetryData_EventsTelemetry{ + Published: evPub, + BatchesSucceeded: evOk, + BatchesFailed: evFail, + } + } + } +} + +// RestoreOnFailure adds the drained counters from the failed request back to +// the atomics so they are retried in the next flush. Also records the current +// failure (+1 to FlushFailed). +func (tc *TelemetryCounters) RestoreOnFailure(request *resolverv1.WriteFlagLogsRequest) { + tc.FlushFailed.Add(1) + if td := request.TelemetryData; td != nil { + if td.Flush != nil { + tc.FlushSucceeded.Add(int64(td.Flush.Succeeded)) + tc.FlushFailed.Add(int64(td.Flush.Failed)) + } + if td.Events != nil { + tc.EventsPublished.Add(int64(td.Events.Published)) + tc.EventBatchesSucceeded.Add(int64(td.Events.BatchesSucceeded)) + tc.EventBatchesFailed.Add(int64(td.Events.BatchesFailed)) + } + } +} + +// RecordEventBatch records an event batch delivery outcome. +func (tc *TelemetryCounters) RecordEventBatch(eventCount int, succeeded bool) { + if succeeded { + tc.EventsPublished.Add(int64(eventCount)) + tc.EventBatchesSucceeded.Add(1) + } else { + tc.EventBatchesFailed.Add(1) + } +} diff --git a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java index a8c3f0507..ca228fdef 100644 --- a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java +++ b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java @@ -140,6 +140,7 @@ private void sendWithFailover(WriteFlagLogsRequest request) { failures.incrementAndGet(); telemetryFlushFailed.incrementAndGet(); restoreDrainedCounters(request); + logger.warn("Edge flag log delivery failed", e); } return; } diff --git a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts index ab305bc92..741f05c35 100644 --- a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts +++ b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts @@ -244,7 +244,7 @@ export class ConfidenceServerProviderLocal implements Provider { } if (this.initTelemetryState !== 'sent') { try { - const request = this.addProviderInitTelemetry(new Uint8Array()); + const request = this.enrichTelemetry(new Uint8Array(), true); await this.sendFlagLogs(request, signal); this.initTelemetryState = 'sent'; } catch { @@ -519,9 +519,8 @@ export class ConfidenceServerProviderLocal implements Provider { const includeInit = this.initTelemetryState === 'pending'; if (includeInit) { this.initTelemetryState = 'sending'; - writeFlagLogRequest = this.addProviderInitTelemetry(writeFlagLogRequest); } - writeFlagLogRequest = this.addFlushDeliveryTelemetry(writeFlagLogRequest); + writeFlagLogRequest = this.enrichTelemetry(writeFlagLogRequest, includeInit); try { await this.sendFlagLogs(writeFlagLogRequest, signal); this.flushSucceeded++; @@ -590,10 +589,11 @@ export class ConfidenceServerProviderLocal implements Provider { } } - private addFlushDeliveryTelemetry(encodedWriteFlagLogRequest: Uint8Array): Uint8Array { + /** Single decode→enrich→encode pass for init + delivery telemetry. */ + private enrichTelemetry(encodedWriteFlagLogRequest: Uint8Array, includeInit: boolean): Uint8Array { const hasFlush = this.flushSucceeded > 0 || this.flushFailed > 0; const hasEvents = this.eventsPublished > 0 || this.eventBatchesSucceeded > 0 || this.eventBatchesFailed > 0; - if (!hasFlush && !hasEvents) { + if (!includeInit && !hasFlush && !hasEvents) { return encodedWriteFlagLogRequest; } const request = WriteFlagLogsRequest.decode(encodedWriteFlagLogRequest); @@ -606,6 +606,10 @@ export class ConfidenceServerProviderLocal implements Provider { }; } const td = request.telemetryData!; + if (includeInit) { + td.sdk = { id: SdkId.SDK_ID_JS_LOCAL_SERVER_PROVIDER, version: VERSION }; + td.providerInitRate.push({ count: 1, labels: this.initLabels }); + } if (hasFlush) { td.flush = { succeeded: this.flushSucceeded, failed: this.flushFailed }; } @@ -624,24 +628,6 @@ export class ConfidenceServerProviderLocal implements Provider { return WriteFlagLogsRequest.encode(request).finish(); } - private addProviderInitTelemetry(encodedWriteFlagLogRequest: Uint8Array): Uint8Array { - const request = WriteFlagLogsRequest.decode(encodedWriteFlagLogRequest); - if (!request.telemetryData) { - request.telemetryData = { - resolverVersion: '', - providerInitRate: [], - resolveRate: [], - memoryBytes: 0, - }; - } - request.telemetryData.sdk = { - id: SdkId.SDK_ID_JS_LOCAL_SERVER_PROVIDER, - version: VERSION, - }; - request.telemetryData.providerInitRate.push({ count: 1, labels: this.initLabels }); - return WriteFlagLogsRequest.encode(request).finish(); - } - /** * Send flag logs to a specific destination. Returns true on success (HTTP 2xx), * false on a non-OK HTTP response. Throws on network errors. diff --git a/openfeature-provider/python/src/confidence/provider.py b/openfeature-provider/python/src/confidence/provider.py index bb22479d1..899e7ceff 100644 --- a/openfeature-provider/python/src/confidence/provider.py +++ b/openfeature-provider/python/src/confidence/provider.py @@ -919,8 +919,8 @@ def _write_logs(self, log_data: bytes) -> None: self._init_telemetry_state = "sending" include_init = True - has_flush = self._flush_succeeded > 0 or self._flush_failed > 0 with self._event_stats_lock: + has_flush = self._flush_succeeded > 0 or self._flush_failed > 0 has_events = ( self._event_telemetry_published > 0 or self._event_telemetry_succeeded > 0 @@ -942,13 +942,15 @@ def _write_logs(self, log_data: bytes) -> None: init_rate.count = 1 for k, v in self._init_labels.items(): init_rate.labels[k] = v - if has_flush: - request.telemetry_data.flush.succeeded = self._flush_succeeded - request.telemetry_data.flush.failed = self._flush_failed - self._flush_succeeded = 0 - self._flush_failed = 0 - if has_events: - with self._event_stats_lock: + with self._event_stats_lock: + if has_flush: + request.telemetry_data.flush.succeeded = ( + self._flush_succeeded + ) + request.telemetry_data.flush.failed = self._flush_failed + self._flush_succeeded = 0 + self._flush_failed = 0 + if has_events: request.telemetry_data.events.published = ( self._event_telemetry_published ) @@ -966,12 +968,12 @@ def _write_logs(self, log_data: bytes) -> None: try: self._flag_logger.write(log_data) except Exception: - self._flush_failed += 1 - if request is not None: - td = request.telemetry_data - self._flush_succeeded += td.flush.succeeded - self._flush_failed += td.flush.failed - with self._event_stats_lock: + with self._event_stats_lock: + self._flush_failed += 1 + if request is not None: + td = request.telemetry_data + self._flush_succeeded += td.flush.succeeded + self._flush_failed += td.flush.failed self._event_telemetry_published += td.events.published self._event_telemetry_succeeded += ( td.events.batches_succeeded @@ -982,7 +984,8 @@ def _write_logs(self, log_data: bytes) -> None: self._init_telemetry_state = "pending" raise else: - self._flush_succeeded += 1 + with self._event_stats_lock: + self._flush_succeeded += 1 if include_init: with self._init_telemetry_lock: self._init_telemetry_state = "sent" From 50380d8adb6b967bced9be441271b72f21831907 Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Thu, 3 Sep 2026 11:20:42 +0200 Subject: [PATCH 19/25] fix(java): use logger.debug for edge delivery failure, not warn Co-Authored-By: Claude Opus 4.6 (1M context) --- .../java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java index ca228fdef..14b190752 100644 --- a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java +++ b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/GrpcWasmFlagLogger.java @@ -140,7 +140,7 @@ private void sendWithFailover(WriteFlagLogsRequest request) { failures.incrementAndGet(); telemetryFlushFailed.incrementAndGet(); restoreDrainedCounters(request); - logger.warn("Edge flag log delivery failed", e); + logger.debug("Edge flag log delivery failed", e); } return; } From 7dd79a0460f9ce48f8aac8269e1aceffa2d59e85 Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Thu, 3 Sep 2026 11:27:40 +0200 Subject: [PATCH 20/25] fix(python): ruff format provider.py Co-Authored-By: Claude Opus 4.6 (1M context) --- openfeature-provider/python/src/confidence/provider.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/openfeature-provider/python/src/confidence/provider.py b/openfeature-provider/python/src/confidence/provider.py index 899e7ceff..ce8525089 100644 --- a/openfeature-provider/python/src/confidence/provider.py +++ b/openfeature-provider/python/src/confidence/provider.py @@ -944,9 +944,7 @@ def _write_logs(self, log_data: bytes) -> None: init_rate.labels[k] = v with self._event_stats_lock: if has_flush: - request.telemetry_data.flush.succeeded = ( - self._flush_succeeded - ) + request.telemetry_data.flush.succeeded = self._flush_succeeded request.telemetry_data.flush.failed = self._flush_failed self._flush_succeeded = 0 self._flush_failed = 0 @@ -975,9 +973,7 @@ def _write_logs(self, log_data: bytes) -> None: self._flush_succeeded += td.flush.succeeded self._flush_failed += td.flush.failed self._event_telemetry_published += td.events.published - self._event_telemetry_succeeded += ( - td.events.batches_succeeded - ) + self._event_telemetry_succeeded += td.events.batches_succeeded self._event_telemetry_failed += td.events.batches_failed if include_init: with self._init_telemetry_lock: From 02274407ba51a61b3ea60dcf7b2e4cd607632116 Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Fri, 4 Sep 2026 15:52:52 +0200 Subject: [PATCH 21/25] fix: address remaining review comments - JS: throw when all flag log destinations fail with non-OK response - Go/Java/JS: subtract per-event errors from events_published count - Go: remove RecordEventBatch from public FlagLogger interface - Proto: rename applies_not_cached to unique_applies Co-Authored-By: Claude Opus 4.6 (1M context) --- .../flags/resolver/v1/internal_api.proto | 2 +- confidence-resolver/src/apply_dedup.rs | 22 ++++++++-------- confidence-resolver/src/telemetry.rs | 26 +++++++++---------- .../go/confidence/flag_logger.go | 1 - .../go/confidence/provider.go | 20 +++++++------- .../sdk/OpenFeatureLocalResolveProvider.java | 3 ++- .../js/src/ConfidenceServerProviderLocal.ts | 4 ++- .../flags/resolver/v1/internal_api.proto | 2 +- 8 files changed, 42 insertions(+), 38 deletions(-) diff --git a/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto b/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto index a800e0ec3..737b6b762 100644 --- a/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto +++ b/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto @@ -152,7 +152,7 @@ message TelemetryData { // Delta counters (since last flush): uint32 applies_total = 1; uint32 applies_deduped = 2; - uint32 applies_not_cached = 3; + uint32 unique_applies = 3; uint32 sweeps = 4; // Gauges (point-in-time): diff --git a/confidence-resolver/src/apply_dedup.rs b/confidence-resolver/src/apply_dedup.rs index 56dafb14c..3532e0bb4 100644 --- a/confidence-resolver/src/apply_dedup.rs +++ b/confidence-resolver/src/apply_dedup.rs @@ -162,7 +162,7 @@ const SWEEP_MIN_INTERVAL_SECONDS: i64 = 10; pub struct ApplyDedupSnapshot { pub applies_total: u64, pub applies_deduped: u64, - pub applies_not_cached: u64, + pub unique_applies: u64, pub sweeps: u64, pub map_size: u32, pub map_capacity: u32, @@ -175,9 +175,9 @@ impl ApplyDedupSnapshot { ApplyDedupTelemetry { applies_total: self.applies_total.wrapping_sub(previous.applies_total) as u32, applies_deduped: self.applies_deduped.wrapping_sub(previous.applies_deduped) as u32, - applies_not_cached: self - .applies_not_cached - .wrapping_sub(previous.applies_not_cached) as u32, + unique_applies: self + .unique_applies + .wrapping_sub(previous.unique_applies) as u32, sweeps: self.sweeps.wrapping_sub(previous.sweeps) as u32, map_size: self.map_size, map_capacity: self.map_capacity, @@ -196,7 +196,7 @@ pub struct ApplyDedup { last_sweep_seconds: i64, applies_total: u64, applies_deduped: u64, - applies_not_cached: u64, + unique_applies: u64, sweeps: u64, } @@ -213,7 +213,7 @@ impl ApplyDedup { last_sweep_seconds: 0, applies_total: 0, applies_deduped: 0, - applies_not_cached: 0, + unique_applies: 0, sweeps: 0, } } @@ -222,7 +222,7 @@ impl ApplyDedup { ApplyDedupSnapshot { applies_total: self.applies_total, applies_deduped: self.applies_deduped, - applies_not_cached: self.applies_not_cached, + unique_applies: self.unique_applies, sweeps: self.sweeps, map_size: self.seen.len() as u32, map_capacity: self.max_entries as u32, @@ -257,7 +257,7 @@ impl ApplyDedup { if self.seen.len() < self.max_entries { self.seen.insert(hash, now_seconds); } else { - self.applies_not_cached = self.applies_not_cached.wrapping_add(1); + self.unique_applies = self.unique_applies.wrapping_add(1); } keep.mark(i); } @@ -1245,7 +1245,7 @@ mod tests { let snap = dedup.telemetry_snapshot(); assert_eq!(snap.applies_total, 2); assert_eq!(snap.applies_deduped, 0); - assert_eq!(snap.applies_not_cached, 0); + assert_eq!(snap.unique_applies, 0); assert_eq!(snap.map_size, 2); assert_eq!(snap.map_capacity, 1000); @@ -1257,7 +1257,7 @@ mod tests { } #[test] - fn telemetry_not_cached_when_full() { + fn telemetry_unique_applies_when_full() { let mut dedup = ApplyDedup::new(120, 2); dedup.filter_duplicates(&[make_flag_to_apply("flags/a", "u1", "on")], 1000); @@ -1267,7 +1267,7 @@ mod tests { let snap = dedup.telemetry_snapshot(); assert_eq!(snap.applies_total, 3); - assert_eq!(snap.applies_not_cached, 1); + assert_eq!(snap.unique_applies, 1); assert_eq!(snap.map_size, 2); } diff --git a/confidence-resolver/src/telemetry.rs b/confidence-resolver/src/telemetry.rs index 57e14e480..8d4c5f480 100644 --- a/confidence-resolver/src/telemetry.rs +++ b/confidence-resolver/src/telemetry.rs @@ -217,9 +217,9 @@ impl TelemetrySnapshot { ad.applies_deduped = ad .applies_deduped .wrapping_add(dedup.applies_deduped as u64); - ad.applies_not_cached = ad - .applies_not_cached - .wrapping_add(dedup.applies_not_cached as u64); + ad.unique_applies = ad + .unique_applies + .wrapping_add(dedup.unique_applies as u64); ad.sweeps = ad.sweeps.wrapping_add(dedup.sweeps as u64); ad.map_size = dedup.map_size; ad.map_capacity = dedup.map_capacity; @@ -453,19 +453,19 @@ impl TelemetrySnapshot { )?; let type_name = if config.openmetrics { - "confidence_apply_dedup_not_cached" + "confidence_apply_dedup_unique_applies" } else { - "confidence_apply_dedup_not_cached_total" + "confidence_apply_dedup_unique_applies_total" }; writeln!( w, - "# HELP {type_name} Apply events passed through but not cached (map full)." + "# HELP {type_name} Unique apply events that passed the dedup filter but could not be cached (map full)." )?; writeln!(w, "# TYPE {type_name} counter")?; writeln!( w, - "confidence_apply_dedup_not_cached_total{{resolver_id=\"{resolver_id}\"}} {}{suffix}", - ad.applies_not_cached + "confidence_apply_dedup_unique_applies_total{{resolver_id=\"{resolver_id}\"}} {}{suffix}", + ad.unique_applies )?; let type_name = if config.openmetrics { @@ -1398,7 +1398,7 @@ mod tests { apply_dedup: Some(ApplyDedupTelemetry { applies_total: 10, applies_deduped: 3, - applies_not_cached: 1, + unique_applies: 1, sweeps: 2, map_size: 50, map_capacity: 100_000, @@ -1410,7 +1410,7 @@ mod tests { let ad = snap.apply_dedup.as_ref().unwrap(); assert_eq!(ad.applies_total, 10); assert_eq!(ad.applies_deduped, 3); - assert_eq!(ad.applies_not_cached, 1); + assert_eq!(ad.unique_applies, 1); assert_eq!(ad.sweeps, 2); assert_eq!(ad.map_size, 50); assert_eq!(ad.map_capacity, 100_000); @@ -1429,7 +1429,7 @@ mod tests { snap.apply_dedup = Some(ApplyDedupSnapshot { applies_total: 100, applies_deduped: 40, - applies_not_cached: 5, + unique_applies: 5, sweeps: 3, map_size: 200, map_capacity: 100_000, @@ -1444,7 +1444,7 @@ mod tests { assert!(prom.contains(r#"confidence_apply_dedup_deduped_total{resolver_id="w0"} 40"#)); - assert!(prom.contains(r#"confidence_apply_dedup_not_cached_total{resolver_id="w0"} 5"#)); + assert!(prom.contains(r#"confidence_apply_dedup_unique_applies_total{resolver_id="w0"} 5"#)); assert!(prom.contains(r#"confidence_apply_dedup_sweeps_total{resolver_id="w0"} 3"#)); @@ -1532,7 +1532,7 @@ mod tests { snap.apply_dedup = Some(ApplyDedupSnapshot { applies_total: 10, applies_deduped: 3, - applies_not_cached: 0, + unique_applies: 0, sweeps: 1, map_size: 5, map_capacity: 100_000, diff --git a/openfeature-provider/go/confidence/flag_logger.go b/openfeature-provider/go/confidence/flag_logger.go index 6cccddb33..eacc44c2c 100644 --- a/openfeature-provider/go/confidence/flag_logger.go +++ b/openfeature-provider/go/confidence/flag_logger.go @@ -7,5 +7,4 @@ import ( type FlagLogger interface { Write(request *resolverv1.WriteFlagLogsRequest) Shutdown() - RecordEventBatch(eventCount int, succeeded bool) } diff --git a/openfeature-provider/go/confidence/provider.go b/openfeature-provider/go/confidence/provider.go index 1c7948ac3..99057ffdf 100644 --- a/openfeature-provider/go/confidence/provider.go +++ b/openfeature-provider/go/confidence/provider.go @@ -633,14 +633,15 @@ func (p *LocalResolverProvider) flushAndPublishEvents(ctx context.Context) int { } eventCount := len(batch.Events) - if err := p.publishEvents(ctx, batch); err != nil { + rejected, err := p.publishEvents(ctx, batch) + if err != nil { p.eventPublishFailures.Add(1) p.logger.Debug("Failed to publish events", "error", err) - if p.flagLogger != nil { - p.flagLogger.RecordEventBatch(eventCount, false) + if recorder, ok := p.flagLogger.(interface{ RecordEventBatch(int, bool) }); ok { + recorder.RecordEventBatch(eventCount, false) } - } else if p.flagLogger != nil { - p.flagLogger.RecordEventBatch(eventCount, true) + } else if recorder, ok := p.flagLogger.(interface{ RecordEventBatch(int, bool) }); ok { + recorder.RecordEventBatch(eventCount-rejected, true) } if p.eventPublishAttempts.Add(1)%eventPublishLogWindow == 0 { @@ -677,9 +678,9 @@ func (p *LocalResolverProvider) drainEvents(ctx context.Context) { // publishEvents wraps a flushed batch in a PublishEventsRequest and sends it to // the Confidence events service. -func (p *LocalResolverProvider) publishEvents(ctx context.Context, batch *eventswasm.FlushEventsResponse) error { +func (p *LocalResolverProvider) publishEvents(ctx context.Context, batch *eventswasm.FlushEventsResponse) (int, error) { if p.eventsClient == nil { - return errors.New("events service client is not configured") + return 0, errors.New("events service client is not configured") } rpcCtx, cancel := context.WithTimeout(ctx, eventsPublishTimeout) @@ -694,9 +695,10 @@ func (p *LocalResolverProvider) publishEvents(ctx context.Context, batch *events response, err := p.eventsClient.PublishEvents(rpcCtx, request) if err != nil { - return fmt.Errorf("failed to publish events: %w", err) + return 0, fmt.Errorf("failed to publish events: %w", err) } + rejected := len(response.GetErrors()) for _, e := range response.GetErrors() { p.logger.Error("Event publish error", "index", e.GetIndex(), @@ -704,7 +706,7 @@ func (p *LocalResolverProvider) publishEvents(ctx context.Context, batch *events "message", e.GetMessage()) } - return nil + return rejected, nil } // Resolve resolves multiple flags for the given context. If flagNames is empty, diff --git a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java index 8d416ebce..7144ef650 100644 --- a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java +++ b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java @@ -784,7 +784,8 @@ private void sendEvents(FlushEventsResponse batch) { .build(); try { final PublishEventsResponse response = eventsStub.publishEvents(request); - telemetryEventsPublished.addAndGet(batch.getEventsCount()); + final int rejected = response.getErrorsCount(); + telemetryEventsPublished.addAndGet(batch.getEventsCount() - rejected); telemetryEventBatchesSucceeded.incrementAndGet(); for (final EventError error : response.getErrorsList()) { log.error( diff --git a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts index 741f05c35..8618e8862 100644 --- a/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts +++ b/openfeature-provider/js/src/ConfidenceServerProviderLocal.ts @@ -325,8 +325,8 @@ export class ConfidenceServerProviderLocal implements Provider { return; } this.eventBatchesSucceeded++; - this.eventsPublished += batch.events?.length ?? 0; const { errors } = PublishEventsResponse.decode(new Uint8Array(await response.arrayBuffer())); + this.eventsPublished += (batch.events?.length ?? 0) - errors.length; for (const error of errors) { logger.error( `Failed to publish event at index ${error.index}: ${EventError_Reason[error.reason]} ${error.message}`, @@ -569,6 +569,8 @@ export class ConfidenceServerProviderLocal implements Provider { throw err; } } + // All destinations returned non-OK responses without throwing + throw new Error('All flag log destinations returned error responses'); } private restoreDrainedCounters(encodedWriteFlagLogRequest: Uint8Array): void { diff --git a/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto b/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto index f04b27409..119b8a98b 100644 --- a/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto +++ b/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto @@ -104,7 +104,7 @@ message TelemetryData { message ApplyDedupTelemetry { uint32 applies_total = 1; uint32 applies_deduped = 2; - uint32 applies_not_cached = 3; + uint32 unique_applies = 3; uint32 sweeps = 4; uint32 map_size = 5; uint32 map_capacity = 6; From ab8d90627f1d321dd6cf709dcd0f61f3673fbb86 Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Fri, 4 Sep 2026 16:09:39 +0200 Subject: [PATCH 22/25] fix: rename unique_applies to overflow in ApplyDedupTelemetry Co-Authored-By: Claude Opus 4.6 (1M context) --- .../flags/resolver/v1/internal_api.proto | 2 +- confidence-resolver/src/apply_dedup.rs | 22 ++++++++--------- confidence-resolver/src/telemetry.rs | 24 +++++++++---------- .../flags/resolver/v1/internal_api.proto | 2 +- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto b/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto index 737b6b762..fc650ff84 100644 --- a/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto +++ b/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto @@ -152,7 +152,7 @@ message TelemetryData { // Delta counters (since last flush): uint32 applies_total = 1; uint32 applies_deduped = 2; - uint32 unique_applies = 3; + uint32 overflow = 3; uint32 sweeps = 4; // Gauges (point-in-time): diff --git a/confidence-resolver/src/apply_dedup.rs b/confidence-resolver/src/apply_dedup.rs index 3532e0bb4..b0c7714d5 100644 --- a/confidence-resolver/src/apply_dedup.rs +++ b/confidence-resolver/src/apply_dedup.rs @@ -162,7 +162,7 @@ const SWEEP_MIN_INTERVAL_SECONDS: i64 = 10; pub struct ApplyDedupSnapshot { pub applies_total: u64, pub applies_deduped: u64, - pub unique_applies: u64, + pub overflow: u64, pub sweeps: u64, pub map_size: u32, pub map_capacity: u32, @@ -175,9 +175,9 @@ impl ApplyDedupSnapshot { ApplyDedupTelemetry { applies_total: self.applies_total.wrapping_sub(previous.applies_total) as u32, applies_deduped: self.applies_deduped.wrapping_sub(previous.applies_deduped) as u32, - unique_applies: self - .unique_applies - .wrapping_sub(previous.unique_applies) as u32, + overflow: self + .overflow + .wrapping_sub(previous.overflow) as u32, sweeps: self.sweeps.wrapping_sub(previous.sweeps) as u32, map_size: self.map_size, map_capacity: self.map_capacity, @@ -196,7 +196,7 @@ pub struct ApplyDedup { last_sweep_seconds: i64, applies_total: u64, applies_deduped: u64, - unique_applies: u64, + overflow: u64, sweeps: u64, } @@ -213,7 +213,7 @@ impl ApplyDedup { last_sweep_seconds: 0, applies_total: 0, applies_deduped: 0, - unique_applies: 0, + overflow: 0, sweeps: 0, } } @@ -222,7 +222,7 @@ impl ApplyDedup { ApplyDedupSnapshot { applies_total: self.applies_total, applies_deduped: self.applies_deduped, - unique_applies: self.unique_applies, + overflow: self.overflow, sweeps: self.sweeps, map_size: self.seen.len() as u32, map_capacity: self.max_entries as u32, @@ -257,7 +257,7 @@ impl ApplyDedup { if self.seen.len() < self.max_entries { self.seen.insert(hash, now_seconds); } else { - self.unique_applies = self.unique_applies.wrapping_add(1); + self.overflow = self.overflow.wrapping_add(1); } keep.mark(i); } @@ -1245,7 +1245,7 @@ mod tests { let snap = dedup.telemetry_snapshot(); assert_eq!(snap.applies_total, 2); assert_eq!(snap.applies_deduped, 0); - assert_eq!(snap.unique_applies, 0); + assert_eq!(snap.overflow, 0); assert_eq!(snap.map_size, 2); assert_eq!(snap.map_capacity, 1000); @@ -1257,7 +1257,7 @@ mod tests { } #[test] - fn telemetry_unique_applies_when_full() { + fn telemetry_overflow_when_full() { let mut dedup = ApplyDedup::new(120, 2); dedup.filter_duplicates(&[make_flag_to_apply("flags/a", "u1", "on")], 1000); @@ -1267,7 +1267,7 @@ mod tests { let snap = dedup.telemetry_snapshot(); assert_eq!(snap.applies_total, 3); - assert_eq!(snap.unique_applies, 1); + assert_eq!(snap.overflow, 1); assert_eq!(snap.map_size, 2); } diff --git a/confidence-resolver/src/telemetry.rs b/confidence-resolver/src/telemetry.rs index 8d4c5f480..328bfbb71 100644 --- a/confidence-resolver/src/telemetry.rs +++ b/confidence-resolver/src/telemetry.rs @@ -217,9 +217,9 @@ impl TelemetrySnapshot { ad.applies_deduped = ad .applies_deduped .wrapping_add(dedup.applies_deduped as u64); - ad.unique_applies = ad - .unique_applies - .wrapping_add(dedup.unique_applies as u64); + ad.overflow = ad + .overflow + .wrapping_add(dedup.overflow as u64); ad.sweeps = ad.sweeps.wrapping_add(dedup.sweeps as u64); ad.map_size = dedup.map_size; ad.map_capacity = dedup.map_capacity; @@ -453,9 +453,9 @@ impl TelemetrySnapshot { )?; let type_name = if config.openmetrics { - "confidence_apply_dedup_unique_applies" + "confidence_apply_dedup_overflow" } else { - "confidence_apply_dedup_unique_applies_total" + "confidence_apply_dedup_overflow_total" }; writeln!( w, @@ -464,8 +464,8 @@ impl TelemetrySnapshot { writeln!(w, "# TYPE {type_name} counter")?; writeln!( w, - "confidence_apply_dedup_unique_applies_total{{resolver_id=\"{resolver_id}\"}} {}{suffix}", - ad.unique_applies + "confidence_apply_dedup_overflow_total{{resolver_id=\"{resolver_id}\"}} {}{suffix}", + ad.overflow )?; let type_name = if config.openmetrics { @@ -1398,7 +1398,7 @@ mod tests { apply_dedup: Some(ApplyDedupTelemetry { applies_total: 10, applies_deduped: 3, - unique_applies: 1, + overflow: 1, sweeps: 2, map_size: 50, map_capacity: 100_000, @@ -1410,7 +1410,7 @@ mod tests { let ad = snap.apply_dedup.as_ref().unwrap(); assert_eq!(ad.applies_total, 10); assert_eq!(ad.applies_deduped, 3); - assert_eq!(ad.unique_applies, 1); + assert_eq!(ad.overflow, 1); assert_eq!(ad.sweeps, 2); assert_eq!(ad.map_size, 50); assert_eq!(ad.map_capacity, 100_000); @@ -1429,7 +1429,7 @@ mod tests { snap.apply_dedup = Some(ApplyDedupSnapshot { applies_total: 100, applies_deduped: 40, - unique_applies: 5, + overflow: 5, sweeps: 3, map_size: 200, map_capacity: 100_000, @@ -1444,7 +1444,7 @@ mod tests { assert!(prom.contains(r#"confidence_apply_dedup_deduped_total{resolver_id="w0"} 40"#)); - assert!(prom.contains(r#"confidence_apply_dedup_unique_applies_total{resolver_id="w0"} 5"#)); + assert!(prom.contains(r#"confidence_apply_dedup_overflow_total{resolver_id="w0"} 5"#)); assert!(prom.contains(r#"confidence_apply_dedup_sweeps_total{resolver_id="w0"} 3"#)); @@ -1532,7 +1532,7 @@ mod tests { snap.apply_dedup = Some(ApplyDedupSnapshot { applies_total: 10, applies_deduped: 3, - unique_applies: 0, + overflow: 0, sweeps: 1, map_size: 5, map_capacity: 100_000, diff --git a/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto b/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto index 119b8a98b..79f019c99 100644 --- a/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto +++ b/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto @@ -104,7 +104,7 @@ message TelemetryData { message ApplyDedupTelemetry { uint32 applies_total = 1; uint32 applies_deduped = 2; - uint32 unique_applies = 3; + uint32 overflow = 3; uint32 sweeps = 4; uint32 map_size = 5; uint32 map_capacity = 6; From 6ec96757ab54f26337469a8f466b842caed1facd Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Fri, 4 Sep 2026 16:15:51 +0200 Subject: [PATCH 23/25] fix: rename proto field overflow to apply_dedup_overflow Co-Authored-By: Claude Opus 4.6 (1M context) --- .../flags/resolver/v1/internal_api.proto | 2 +- confidence-resolver/src/apply_dedup.rs | 21 ++++++++++--------- confidence-resolver/src/telemetry.rs | 16 +++++++------- .../flags/resolver/v1/internal_api.proto | 2 +- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto b/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto index fc650ff84..7d422a207 100644 --- a/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto +++ b/confidence-resolver/protos/confidence/flags/resolver/v1/internal_api.proto @@ -152,7 +152,7 @@ message TelemetryData { // Delta counters (since last flush): uint32 applies_total = 1; uint32 applies_deduped = 2; - uint32 overflow = 3; + uint32 apply_dedup_overflow = 3; uint32 sweeps = 4; // Gauges (point-in-time): diff --git a/confidence-resolver/src/apply_dedup.rs b/confidence-resolver/src/apply_dedup.rs index b0c7714d5..1c62ae580 100644 --- a/confidence-resolver/src/apply_dedup.rs +++ b/confidence-resolver/src/apply_dedup.rs @@ -162,7 +162,8 @@ const SWEEP_MIN_INTERVAL_SECONDS: i64 = 10; pub struct ApplyDedupSnapshot { pub applies_total: u64, pub applies_deduped: u64, - pub overflow: u64, + #[cfg_attr(feature = "json", serde(alias = "overflow"))] + pub apply_dedup_overflow: u64, pub sweeps: u64, pub map_size: u32, pub map_capacity: u32, @@ -175,9 +176,9 @@ impl ApplyDedupSnapshot { ApplyDedupTelemetry { applies_total: self.applies_total.wrapping_sub(previous.applies_total) as u32, applies_deduped: self.applies_deduped.wrapping_sub(previous.applies_deduped) as u32, - overflow: self - .overflow - .wrapping_sub(previous.overflow) as u32, + apply_dedup_overflow: self + .apply_dedup_overflow + .wrapping_sub(previous.apply_dedup_overflow) as u32, sweeps: self.sweeps.wrapping_sub(previous.sweeps) as u32, map_size: self.map_size, map_capacity: self.map_capacity, @@ -196,7 +197,7 @@ pub struct ApplyDedup { last_sweep_seconds: i64, applies_total: u64, applies_deduped: u64, - overflow: u64, + apply_dedup_overflow: u64, sweeps: u64, } @@ -213,7 +214,7 @@ impl ApplyDedup { last_sweep_seconds: 0, applies_total: 0, applies_deduped: 0, - overflow: 0, + apply_dedup_overflow: 0, sweeps: 0, } } @@ -222,7 +223,7 @@ impl ApplyDedup { ApplyDedupSnapshot { applies_total: self.applies_total, applies_deduped: self.applies_deduped, - overflow: self.overflow, + apply_dedup_overflow: self.apply_dedup_overflow, sweeps: self.sweeps, map_size: self.seen.len() as u32, map_capacity: self.max_entries as u32, @@ -257,7 +258,7 @@ impl ApplyDedup { if self.seen.len() < self.max_entries { self.seen.insert(hash, now_seconds); } else { - self.overflow = self.overflow.wrapping_add(1); + self.apply_dedup_overflow = self.apply_dedup_overflow.wrapping_add(1); } keep.mark(i); } @@ -1245,7 +1246,7 @@ mod tests { let snap = dedup.telemetry_snapshot(); assert_eq!(snap.applies_total, 2); assert_eq!(snap.applies_deduped, 0); - assert_eq!(snap.overflow, 0); + assert_eq!(snap.apply_dedup_overflow, 0); assert_eq!(snap.map_size, 2); assert_eq!(snap.map_capacity, 1000); @@ -1267,7 +1268,7 @@ mod tests { let snap = dedup.telemetry_snapshot(); assert_eq!(snap.applies_total, 3); - assert_eq!(snap.overflow, 1); + assert_eq!(snap.apply_dedup_overflow, 1); assert_eq!(snap.map_size, 2); } diff --git a/confidence-resolver/src/telemetry.rs b/confidence-resolver/src/telemetry.rs index 328bfbb71..6209612c4 100644 --- a/confidence-resolver/src/telemetry.rs +++ b/confidence-resolver/src/telemetry.rs @@ -217,9 +217,9 @@ impl TelemetrySnapshot { ad.applies_deduped = ad .applies_deduped .wrapping_add(dedup.applies_deduped as u64); - ad.overflow = ad - .overflow - .wrapping_add(dedup.overflow as u64); + ad.apply_dedup_overflow = ad + .apply_dedup_overflow + .wrapping_add(dedup.apply_dedup_overflow as u64); ad.sweeps = ad.sweeps.wrapping_add(dedup.sweeps as u64); ad.map_size = dedup.map_size; ad.map_capacity = dedup.map_capacity; @@ -465,7 +465,7 @@ impl TelemetrySnapshot { writeln!( w, "confidence_apply_dedup_overflow_total{{resolver_id=\"{resolver_id}\"}} {}{suffix}", - ad.overflow + ad.apply_dedup_overflow )?; let type_name = if config.openmetrics { @@ -1398,7 +1398,7 @@ mod tests { apply_dedup: Some(ApplyDedupTelemetry { applies_total: 10, applies_deduped: 3, - overflow: 1, + apply_dedup_overflow: 1, sweeps: 2, map_size: 50, map_capacity: 100_000, @@ -1410,7 +1410,7 @@ mod tests { let ad = snap.apply_dedup.as_ref().unwrap(); assert_eq!(ad.applies_total, 10); assert_eq!(ad.applies_deduped, 3); - assert_eq!(ad.overflow, 1); + assert_eq!(ad.apply_dedup_overflow, 1); assert_eq!(ad.sweeps, 2); assert_eq!(ad.map_size, 50); assert_eq!(ad.map_capacity, 100_000); @@ -1429,7 +1429,7 @@ mod tests { snap.apply_dedup = Some(ApplyDedupSnapshot { applies_total: 100, applies_deduped: 40, - overflow: 5, + apply_dedup_overflow: 5, sweeps: 3, map_size: 200, map_capacity: 100_000, @@ -1532,7 +1532,7 @@ mod tests { snap.apply_dedup = Some(ApplyDedupSnapshot { applies_total: 10, applies_deduped: 3, - overflow: 0, + apply_dedup_overflow: 0, sweeps: 1, map_size: 5, map_capacity: 100_000, diff --git a/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto b/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto index 79f019c99..fe68446c0 100644 --- a/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto +++ b/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto @@ -104,7 +104,7 @@ message TelemetryData { message ApplyDedupTelemetry { uint32 applies_total = 1; uint32 applies_deduped = 2; - uint32 overflow = 3; + uint32 apply_dedup_overflow = 3; uint32 sweeps = 4; uint32 map_size = 5; uint32 map_capacity = 6; From d6a4eb666c76fcf16808cf3b0c1a7bf005201066 Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Sun, 6 Sep 2026 23:48:25 +0200 Subject: [PATCH 24/25] chore: sync WASM module for Go provider Co-Authored-By: Claude Opus 4.6 (1M context) --- .../assets/confidence_resolver.wasm | Bin 510175 -> 510199 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/openfeature-provider/go/confidence/internal/local_resolver/assets/confidence_resolver.wasm b/openfeature-provider/go/confidence/internal/local_resolver/assets/confidence_resolver.wasm index 911b10d064ad50b237e084e77253efbb2db58358..a451100ebac5826b42605fe6b8d3d3136134c56a 100755 GIT binary patch delta 12752 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 From b17b43c71f4ef2f40ce63c3ac199c9ccd7d419f0 Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Sun, 6 Sep 2026 23:55:22 +0200 Subject: [PATCH 25/25] fix: cargo fmt apply_dedup_overflow line wrapping Co-Authored-By: Claude Opus 4.6 (1M context) --- .../wrangler-test.toml | 32 + confidence-resolver/src/apply_dedup.rs | 3 +- openfeature-provider/java/wrangler-test.toml | 32 + openfeature-provider/js/package-lock.json | 3221 +++++++++++++++++ .../proto/confidence/events/v1/api_pb2.py | 10 +- .../confidence/events/v1/api_pb2_grpc.py | 4 +- .../proto/confidence/events/v1/types_pb2.py | 8 +- .../confidence/events/v1/types_pb2_grpc.py | 4 +- .../confidence/events/wasm/v1/wasm_api_pb2.py | 10 +- .../events/wasm/v1/wasm_api_pb2_grpc.py | 4 +- .../confidence/flags/admin/v1/resolver_pb2.py | 4 +- .../confidence/flags/resolver/v1/api_pb2.py | 4 +- .../flags/resolver/v1/api_pb2_grpc.py | 2 +- .../resolver/v1/internal_api_pb2_grpc.py | 2 +- .../proto/confidence/wasm/messages_pb2.py | 12 +- .../confidence/wasm/messages_pb2_grpc.py | 4 +- .../proto/confidence/wasm/wasm_api_pb2.py | 4 +- 17 files changed, 3323 insertions(+), 37 deletions(-) create mode 100644 confidence-cloudflare-resolver/wrangler-test.toml create mode 100644 openfeature-provider/java/wrangler-test.toml create mode 100644 openfeature-provider/js/package-lock.json diff --git a/confidence-cloudflare-resolver/wrangler-test.toml b/confidence-cloudflare-resolver/wrangler-test.toml new file mode 100644 index 000000000..93138bbda --- /dev/null +++ b/confidence-cloudflare-resolver/wrangler-test.toml @@ -0,0 +1,32 @@ +name = "confidence-telemetry-test" +main = "build/worker/shim.mjs" +compatibility_date = "2025-01-28" + +[observability] +enabled = true + +[[queues.consumers]] +queue = "telemetry-test-flag-logs" +max_batch_size = 100 +max_batch_timeout = 10 + +[[queues.producers]] +queue = "telemetry-test-flag-logs" +binding = "flag_logs_queue" + +[[queues.consumers]] +queue = "telemetry-test-events" +max_batch_size = 100 +max_batch_timeout = 10 + +[[queues.producers]] +queue = "telemetry-test-events" +binding = "events_queue" + +[[kv_namespaces]] +binding = "CONFIDENCE_METRICS_KV" +id = "05a77023635a4dbaa4744a20d6419a53" + +[vars] +CONFIDENCE_CLIENT_SECRET = "mkjJruAATQWjeY7foFIWfVAcBWnci2YF" +ENABLE_APPLY_DEDUP = "true" diff --git a/confidence-resolver/src/apply_dedup.rs b/confidence-resolver/src/apply_dedup.rs index 1c62ae580..df432c541 100644 --- a/confidence-resolver/src/apply_dedup.rs +++ b/confidence-resolver/src/apply_dedup.rs @@ -178,7 +178,8 @@ impl ApplyDedupSnapshot { applies_deduped: self.applies_deduped.wrapping_sub(previous.applies_deduped) as u32, apply_dedup_overflow: self .apply_dedup_overflow - .wrapping_sub(previous.apply_dedup_overflow) as u32, + .wrapping_sub(previous.apply_dedup_overflow) + as u32, sweeps: self.sweeps.wrapping_sub(previous.sweeps) as u32, map_size: self.map_size, map_capacity: self.map_capacity, diff --git a/openfeature-provider/java/wrangler-test.toml b/openfeature-provider/java/wrangler-test.toml new file mode 100644 index 000000000..326065a08 --- /dev/null +++ b/openfeature-provider/java/wrangler-test.toml @@ -0,0 +1,32 @@ +name = "confidence-telemetry-test" +main = "build/worker/shim.mjs" +compatibility_date = "2025-01-28" + +[observability] +enabled = true + +[[queues.consumers]] +queue = "telemetry-test-flag-logs" +max_batch_size = 100 +max_batch_timeout = 10 + +[[queues.producers]] +queue = "telemetry-test-flag-logs" +binding = "flag_logs_queue" + +[[queues.consumers]] +queue = "telemetry-test-events" +max_batch_size = 100 +max_batch_timeout = 10 + +[[queues.producers]] +queue = "telemetry-test-events" +binding = "events_queue" + +[[kv_namespaces]] +binding = "CONFIDENCE_METRICS_KV" +id = "placeholder" + +[vars] +CONFIDENCE_CLIENT_SECRET = "mkjJruAATQWjeY7foFIWfVAcBWnci2YF" +ENABLE_APPLY_DEDUP = "true" diff --git a/openfeature-provider/js/package-lock.json b/openfeature-provider/js/package-lock.json new file mode 100644 index 000000000..e3048124b --- /dev/null +++ b/openfeature-provider/js/package-lock.json @@ -0,0 +1,3221 @@ +{ + "name": "@spotify-confidence/openfeature-server-provider-local", + "version": "0.21.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@spotify-confidence/openfeature-server-provider-local", + "version": "0.21.0", + "license": "Apache-2.0", + "dependencies": { + "@bufbuild/protobuf": "^2.9.0" + }, + "devDependencies": { + "@openfeature/core": "^1.9.0", + "@openfeature/server-sdk": "^1.19.0", + "@spotify/prettier-config": "^15.0.0", + "@testing-library/dom": "^10.4.1", + "@testing-library/react": "^16.3.2", + "@types/debug": "^4", + "@types/node": "^24.0.1", + "@types/react": "^19", + "@types/react-dom": "^19", + "@vitest/coverage-v8": "^4.1.7", + "debug": "^4.4.3", + "dotenv": "^17.2.2", + "happy-dom": "^20.3.4", + "next": "^16.0.0", + "prettier": "^2.8.8", + "react": "^19", + "react-dom": "^19.2.3", + "rolldown": "1.0.0-beta.38", + "ts-proto": "^2.7.3", + "tsdown": "latest", + "typescript": "^5.9.3", + "vitest": "^4.1.7" + }, + "peerDependencies": { + "@openfeature/core": "^1.0.0", + "debug": "^4.4.3", + "next": ">=13.0.0", + "react": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@openfeature/core": { + "optional": true + }, + "debug": { + "optional": true + }, + "next": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/@babel/code-frame": { + "version": "7.28.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.6", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@bufbuild/protobuf": { + "version": "2.9.0", + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.2.3", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.3.tgz", + "integrity": "sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" + } + }, + "node_modules/@next/env": { + "version": "16.2.12", + "dev": true, + "license": "MIT" + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "16.2.12", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@openfeature/core": { + "version": "1.9.0", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@openfeature/server-sdk": { + "version": "1.19.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "@openfeature/core": "^1.9.0" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.89.0", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@quansync/fs": { + "version": "1.0.0", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@quansync/fs/-/fs-1.0.0.tgz", + "integrity": "sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "quansync": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/@rolldown/binding-android-arm-eabi": { + "version": "1.2.6", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.6.tgz", + "integrity": "sha512-b+jTcARdTiFLI6jB4a5XjTm0RWd6KcRfQj/I2356fxUZemiho9zQLxo0RtCuMDAyKcLo6cEltkgbQp6d1+sjjQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.2.6", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.6.tgz", + "integrity": "sha512-lkWU8ZJaRk9q3CIEY1Tc7vIFALp3Xw5NfGJo2hQg5oIqNgxWi1zI+IiDEK3r70BF5Dzol1tcXsnzsRc8NLhG+Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-beta.38", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.2.6", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.6.tgz", + "integrity": "sha512-vpVxFvUCFioJqug7OTvqptkc4yb8UX0AwfDmJpaR/0sWz+BUmqSVAf7c8JkUgnN8YLspb4a/N6NhTyMAmdyQ7Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.2.6", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.6.tgz", + "integrity": "sha512-h1wG6Y6K3JlRswxsI64qQJqBAy4vrLuHgRbc8CZMGSWTOFRY6ghMApM1NKzB2I0n5xV1fjkE18SuVl2QpLeNpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.2.6", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.6.tgz", + "integrity": "sha512-tbCiqub0q2MVWJKgF5PoAlNWCtQydiOYSLIkd8sByqK/6MMYLJRcSXSYodqYtd0O+Fw7QaVmKKlS4oL94YRZ0w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.2.6", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.6.tgz", + "integrity": "sha512-oxK9+baEBPhZG5HB4URY+uU04zJWeZlH6Tb9rB5DK4DF9XR1uXNLXt5Q5ZsugTKayNCNLhkcwz/ye74hRI98dg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.2.6", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.6.tgz", + "integrity": "sha512-muWCk27FVBEZtv0MsK8gnfSmgczA8KQ0uRVJbTABKhkRfQc38aUrcb7fhi3BNiyseFmgcRsoMfQsSNJ+DbZdSw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.2.6", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.6.tgz", + "integrity": "sha512-eWDoSfU7Co2qj3vgB3Dt4lj1mG6CoWbcJQkRMP3XJplyCMtuaq3LHvPFjS9QIPvMGWVadJC04Xiy0IdcVPtnwQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.2.6", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.6.tgz", + "integrity": "sha512-2bWNjRSIayvupRKxXUY2tWG9fYdoUlTqWywHRvE8Eq3GvuQ+f2HeIkve697fIt+IQs/PV8yFsdWuhp1aJ1PdnA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.2.6", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.6.tgz", + "integrity": "sha512-KekI0gS0wLxe1UBSQSjenBVwou/JkcQPDzBPICGZjxUv9k3RteHDPBQaiOicZUFKRIH2wKEimGwVpnJsbPzu7w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.2.6", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.6.tgz", + "integrity": "sha512-TvtPnfVr+HtyGiDmPK4VWmlNm7QhNNAcK5Q9A7aOXsI8545yCyaoMaicXrFZ72JzeYjaUVk7yT243zT0jzjFKQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.2.6", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.6.tgz", + "integrity": "sha512-iOo0VEay2XFhaCcH0sps5XIimkSuOnNaZrf6+ZkoSOQBJPKNU48RkmJv0/lSpipexu5P+ouFgafe5IGr/DiQfg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-beta.38", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-beta.38.tgz", + "integrity": "sha512-fnLtHyjwEsG4/aNV3Uv3Qd1ZbdH+CopwJNoV0RgBqrcQB8V6/Qdikd5JKvnO23kb3QvIpP+dAMGZMv1c2PJMzw==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.0.5" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.2.6", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.6.tgz", + "integrity": "sha512-y5NTmmasMS455JlOCO4ZM9krIchv3Mvm1crL1iUPGOPgEzSkves9n0SdC5Sjz6+qWDFhd8/JpfWMH8NSWNHe+A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-ia32-msvc": { + "version": "1.0.0-beta.38", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.0.0-beta.38.tgz", + "integrity": "sha512-HcICm4YzFJZV+fI0O0bFLVVlsWvRNo/AB9EfUXvNYbtAxakCnQZ15oq22deFdz6sfi9Y4/SagH2kPU723dhCFA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.2.6", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.6.tgz", + "integrity": "sha512-np8iZSLfXlAD4kWhiyq/u0Yt8oZDtRQ8lGhQaCXo2rl37KNjeU0GjJuwr4P3oeZ++ROfofsKNBqR5LTO8aXyWQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.38", + "dev": true, + "license": "MIT" + }, + "node_modules/@spotify/prettier-config": { + "version": "15.0.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "prettier": "2.x" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@swc/helpers": { + "version": "0.5.15", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "picocolors": "1.1.1", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/react": { + "version": "16.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0 || ^19.0.0", + "@types/react-dom": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai": { + "version": "5.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.12.0" + } + }, + "node_modules/@types/react": { + "version": "19.2.9", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@types/whatwg-mimetype": { + "version": "3.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ws/node_modules/@types/node": { + "version": "25.0.10", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/ws/node_modules/undici-types": { + "version": "7.16.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitest/coverage-v8": { + "version": "4.1.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^1.0.2", + "@vitest/utils": "4.1.8", + "ast-v8-to-istanbul": "^1.0.0", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.2.0", + "magicast": "^0.5.2", + "obug": "^2.1.1", + "std-env": "^4.0.0-rc.1", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "4.1.8", + "vitest": "4.1.8" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } + } + }, + "node_modules/@vitest/expect": { + "version": "4.1.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.8", + "@vitest/utils": "4.1.8", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.8", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.8", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.8", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.8", + "@vitest/utils": "4.1.8", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.8", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.8", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@yuku-codegen/binding-android-arm64": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-codegen/binding-android-arm64/-/binding-android-arm64-0.8.7.tgz", + "integrity": "sha512-C/0zV5IhgVdYhGJTwrY0v8dknxlhiKwtVJkMUaexu9/QvRmzlV4vfU3hZlUSgqc2BxQHntL1mCVbDq8j0FRFDw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@yuku-codegen/binding-darwin-arm64": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-codegen/binding-darwin-arm64/-/binding-darwin-arm64-0.8.7.tgz", + "integrity": "sha512-/u+REDMI4a0/lsJXTM4c53/w31OGZLOReZIyg62uhgLs0kc8NHsj/nOcxTdlQjq5gi0zhdkccD9LaLTXcdzPvw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@yuku-codegen/binding-darwin-x64": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-codegen/binding-darwin-x64/-/binding-darwin-x64-0.8.7.tgz", + "integrity": "sha512-sMMzFOwCo4WXR+/6zIBThOocSC50iIIZZdfiIDbaLvj0Ax/rWt/iavyfEAqajyvzydLyCqR/ZItdLWSRlu1umw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@yuku-codegen/binding-freebsd-x64": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-codegen/binding-freebsd-x64/-/binding-freebsd-x64-0.8.7.tgz", + "integrity": "sha512-MpdpKXix9P+Y1rKgjvcNeNtGjXeL1CmttNhYINrWls8kRpm4xM/oBGTmn6w7to8lAlwj5jm8q03dQPl5mRv4Qw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@yuku-codegen/binding-linux-arm-gnu": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-codegen/binding-linux-arm-gnu/-/binding-linux-arm-gnu-0.8.7.tgz", + "integrity": "sha512-rr1srFLlPAmC1vtxfc9C1YLDe3iH09YjfSeeIidBqKhzx1MATjOAq4mjlRUOnhr/L27MotWIYOFKwVsd5JZFOg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@yuku-codegen/binding-linux-arm-musl": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-codegen/binding-linux-arm-musl/-/binding-linux-arm-musl-0.8.7.tgz", + "integrity": "sha512-eAufXh8qBRpiSO6ueaMDL+yyoXIGLhpUce72YbcACtZU2qhExwBIJyEtQf5kH2Ki0X2aqkSjSfog4OPtKXan3Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@yuku-codegen/binding-linux-arm64-gnu": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-codegen/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.8.7.tgz", + "integrity": "sha512-gw4w6wPoHObBrdIC4duVWLmJOvpdE25j5D7yrM5mACNlK4klRz/lv8hK+ssQk9EJHBgZjSaqZIJVFgqNYbfv7A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@yuku-codegen/binding-linux-arm64-musl": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-codegen/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.8.7.tgz", + "integrity": "sha512-L68N6Y4XkqcIaKo3Ra88JEvBEH4AHff44A4INcrxeVWZ8CZtu2tCpfVxe3hR8qQQMcvBSQlDn24KpkCKEhVvfA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@yuku-codegen/binding-linux-x64-gnu": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-codegen/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.8.7.tgz", + "integrity": "sha512-dzyAbltJmf3Cqlb8HcFuYIf5Yn0fl1vTr3XJ9HiVNNvOlhqPSArOqtw9vI1p6/VTXTjrMLXlU+s+/kNHiIy/Cw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@yuku-codegen/binding-linux-x64-musl": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-codegen/binding-linux-x64-musl/-/binding-linux-x64-musl-0.8.7.tgz", + "integrity": "sha512-Otw4MH3404q0Bbvl+YTdW9aoUV5vXmUw8260bWvt1XlaoIX/ceSgI4ygheRDMfBPoHt6FDayQaO9OLVUZAgkFA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@yuku-codegen/binding-win32-arm64": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-codegen/binding-win32-arm64/-/binding-win32-arm64-0.8.7.tgz", + "integrity": "sha512-qo/jyrzryiBuKEsFiuWaBCBe3tRMynQ0qFWFgOEjcCMQeZfBm+wKiVEUEFXXLc7bh8YezguAWp0Mtnhq4ARNyA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@yuku-codegen/binding-win32-x64": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-codegen/binding-win32-x64/-/binding-win32-x64-0.8.7.tgz", + "integrity": "sha512-D5lDsVDx6m00E6bWySlWdH72Ca4TPSaphDqB6QjU6MpuNLIJqoGoatYyq2rOmBE8Zv/kunot/o58KGL03P3eiA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@yuku-parser/binding-android-arm64": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-parser/binding-android-arm64/-/binding-android-arm64-0.8.7.tgz", + "integrity": "sha512-eGKYiUDX7Y0V7tDTmg+JTVnXnjMqfXXsorZ+EDf5kxwchQ3Or1HS14MzI2fw+jFhHR85fCWt+mtX33Yao73hIQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@yuku-parser/binding-darwin-arm64": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.8.7.tgz", + "integrity": "sha512-Re0RHelKLnjEURulY2/KxW+Ngb8zuNA4BRZuMwgGQNzVumT6u4U2N2hc01oeYVNVof0i7GrXE4UCNBgbpRRnjQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@yuku-parser/binding-darwin-x64": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-parser/binding-darwin-x64/-/binding-darwin-x64-0.8.7.tgz", + "integrity": "sha512-Hn8DROtQkjlA1ACbPgj4a7eP9IuVOI504oiTwpkWPbpaDWD9KdmnVYCqW+1LfenNK/g7O9NhWGpXEdaCNX7lIA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@yuku-parser/binding-freebsd-x64": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.8.7.tgz", + "integrity": "sha512-bAP2OV8wRuzplX/jYxv9+vvqQT8JxyNphI8fLfXGL054Xs+4/J5u33cIm3y4rxY8rdoLmmdiJs2Tq7r7lrDRfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@yuku-parser/binding-linux-arm-gnu": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-parser/binding-linux-arm-gnu/-/binding-linux-arm-gnu-0.8.7.tgz", + "integrity": "sha512-kTYwJQQgmZeAWdDIWabiReIZMpmfLueIj1tCmjStUtFGhR1Z0qwxonKVfUC4N7h/VhGGzLZ//7O1kgt1QKqgCg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@yuku-parser/binding-linux-arm-musl": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-parser/binding-linux-arm-musl/-/binding-linux-arm-musl-0.8.7.tgz", + "integrity": "sha512-uL4jE8HPT2BLlxAXyD10LqgPuXa9eDa0BKpCdSANmzIJghq/2eZo3/gQNtaxPZMupWoxjYzSad9IXrwu7aYPXQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@yuku-parser/binding-linux-arm64-gnu": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.8.7.tgz", + "integrity": "sha512-3gVN4pWSKZmXiNX7cU164dR9MPvesCHnlH6nPfpK+yQsCuYphjKKplcb4SnZBrhiqmXbgb2HR0c2TS0IZUPhgA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@yuku-parser/binding-linux-arm64-musl": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.8.7.tgz", + "integrity": "sha512-S0mwfEjoLpxzXeZw802Wa4RaELsQiPtWqG6INcy8j4GtvNFtl4LCX3eGO1XLn9pyLAISLzTRyU3zUCBUPin8lg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@yuku-parser/binding-linux-x64-gnu": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.8.7.tgz", + "integrity": "sha512-lnbWdPmerE5D1uH1G4IEZKnPzCrWCStRGrtgpSIe1RibAo5bZIjDbbbPYXmMHCEh4F+x/JaJpElh26a3r+BPbg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@yuku-parser/binding-linux-x64-musl": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.8.7.tgz", + "integrity": "sha512-769uwndMvMzUvATWbAcEvyLHKA+DzhHSCl/obBUrRdYfRo26yxui6S8y3z7uJ+Naup7UKrDxrpK7OnQkxkl9KQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@yuku-parser/binding-win32-arm64": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-parser/binding-win32-arm64/-/binding-win32-arm64-0.8.7.tgz", + "integrity": "sha512-mEB/9PlaAkisJ6KWGz0zvywXoU6+80dTlR2LwS7s/jcXXoU6fm2+sitBZXtqu3+Q4DcDgPxM45uWMCzPs0TSRw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@yuku-parser/binding-win32-x64": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-parser/binding-win32-x64/-/binding-win32-x64-0.8.7.tgz", + "integrity": "sha512-8vNB2DP0ou61nGb8tc/qfi41gfyDXz1MHr2zqL3nR+cJ6CEbiuWV/l/a/vv151gCgiZLLAyGkQGENpozdg716w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@yuku-toolchain/types": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@yuku-toolchain/types/-/types-0.8.7.tgz", + "integrity": "sha512-2Z53dNxAJL6UvFoIrDZvYf3zlO8s4VJK4O2hhaB4mXVwwpX/7ajtss3cmfqKvamlNLWyt9FSWs4eoYdlbxpnHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansis": { + "version": "4.3.1", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/ansis/-/ansis-4.3.1.tgz", + "integrity": "sha512-BJ8/l4R5LRE7hW9WdSuGYrLSHi2ynxeFpDFbH0K/CgNeY/tyhk+vO6TYxXC5r5CpUhNVX310xzPsN/H9lCdfOA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/aria-query": { + "version": "5.3.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/ast-v8-to-istanbul": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.31", + "estree-walker": "^3.0.3", + "js-tokens": "^10.0.0" + } + }, + "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { + "version": "10.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.27", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/cac": { + "version": "7.0.0", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/cac/-/cac-7.0.0.tgz", + "integrity": "sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001791", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/case-anything": { + "version": "2.1.13", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/chai": { + "version": "6.2.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/defu": { + "version": "6.1.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/defu/-/defu-6.1.7.tgz", + "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/dequal": { + "version": "2.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "dev": true, + "license": "MIT" + }, + "node_modules/dotenv": { + "version": "17.2.2", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dprint-node": { + "version": "1.0.8", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-libc": "^1.0.3" + } + }, + "node_modules/dprint-node/node_modules/detect-libc": { + "version": "1.0.3", + "dev": true, + "license": "Apache-2.0", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dts-resolver": { + "version": "3.0.0", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/dts-resolver/-/dts-resolver-3.0.0.tgz", + "integrity": "sha512-1T1f+z+4tl9XD+m+0HBgWoL/nm0bOIffyWaUuUSBlFg/86IWvfx+wjNaO/ybU0AJzG9/Mi5hBUgGV6zCmWEN7Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^22.18.0 || >=24.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "oxc-resolver": ">=11.0.0" + }, + "peerDependenciesMeta": { + "oxc-resolver": { + "optional": true + } + } + }, + "node_modules/empathic": { + "version": "2.0.1", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/empathic/-/empathic-2.0.1.tgz", + "integrity": "sha512-YGRs8knHhKHVShLkFET/rWAU8kmHbOV5LwN938RHI0pljAJ1Gf6SzXsSmRaEzcXTtOOmVqJ5+WtQPL5uigY50Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/entities": { + "version": "7.0.1", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-module-lexer": { + "version": "2.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/expect-type": { + "version": "1.3.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-tsconfig": { + "version": "5.0.0-beta.5", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/get-tsconfig/-/get-tsconfig-5.0.0-beta.5.tgz", + "integrity": "sha512-/6gFNr0N04nob252sTQxyFLi3eKFRqIg1I87YcqAMT1i6SQrSF6KujUEQrtrjMV0H/eejTCltLdDSTEMzHbnsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "engines": { + "node": ">=20.20.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/happy-dom": { + "version": "20.8.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": ">=20.0.0", + "@types/whatwg-mimetype": "^3.0.2", + "@types/ws": "^8.18.1", + "entities": "^7.0.1", + "whatwg-mimetype": "^3.0.0", + "ws": "^8.18.3" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/happy-dom/node_modules/@types/node": { + "version": "25.0.10", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/happy-dom/node_modules/undici-types": { + "version": "7.16.0", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hookable": { + "version": "6.1.1", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/hookable/-/hookable-6.1.1.tgz", + "integrity": "sha512-U9LYDy1CwhMCnprUfeAZWZGByVbhd54hwepegYTK7Pi5NvqEj63ifz5z+xukznehT7i6NIZRu89Ay1AZmRsLEQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/import-without-cache": { + "version": "0.4.0", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/import-without-cache/-/import-without-cache-0.4.0.tgz", + "integrity": "sha512-NkJQA7oZ4YHQhd2+H3BoRFKF3d/XNsiKpHZCQEMH9pDX27hQQLsTyOocyRgaIVtf8gHX3Nt3LPkR4e5EdtPAGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^22.18.0 || >=24.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "dev": true, + "license": "MIT", + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magicast": { + "version": "0.5.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.3", + "@babel/types": "^7.29.0", + "source-map-js": "^1.2.1" + } + }, + "node_modules/magicast/node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/magicast/node_modules/@babel/parser": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/magicast/node_modules/@babel/types": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.12", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/next": { + "version": "16.2.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@next/env": "16.2.12", + "@swc/helpers": "0.5.15", + "baseline-browser-mapping": "^2.9.19", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=20.9.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "16.2.12", + "@next/swc-darwin-x64": "16.2.12", + "@next/swc-linux-arm64-gnu": "16.2.12", + "@next/swc-linux-arm64-musl": "16.2.12", + "@next/swc-linux-x64-gnu": "16.2.12", + "@next/swc-linux-x64-musl": "16.2.12", + "@next/swc-win32-arm64-msvc": "16.2.12", + "@next/swc-win32-x64-msvc": "16.2.12", + "sharp": "^0.34.5" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/obug": { + "version": "2.1.4", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/obug/-/obug-2.1.4.tgz", + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.4.31", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/quansync": { + "version": "1.0.0", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/quansync/-/quansync-1.0.0.tgz", + "integrity": "sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT" + }, + "node_modules/react": { + "version": "19.2.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.3" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/rolldown": { + "version": "1.0.0-beta.38", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.89.0", + "@rolldown/pluginutils": "1.0.0-beta.38", + "ansis": "^4.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.0-beta.38", + "@rolldown/binding-darwin-arm64": "1.0.0-beta.38", + "@rolldown/binding-darwin-x64": "1.0.0-beta.38", + "@rolldown/binding-freebsd-x64": "1.0.0-beta.38", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.38", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.38", + "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.38", + "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.38", + "@rolldown/binding-linux-x64-musl": "1.0.0-beta.38", + "@rolldown/binding-openharmony-arm64": "1.0.0-beta.38", + "@rolldown/binding-wasm32-wasi": "1.0.0-beta.38", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.38", + "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.38", + "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.38" + } + }, + "node_modules/rolldown-plugin-dts": { + "version": "0.27.14", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/rolldown-plugin-dts/-/rolldown-plugin-dts-0.27.14.tgz", + "integrity": "sha512-ZvuDDwoIpRK9RPxDXratCpklFO9QZZWndf/sd0VBFb4LEj0jj07UcHK9OCh7V4XiFz2Z89ziyBC2K6tJiDjrbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dts-resolver": "^3.0.0", + "get-tsconfig": "5.0.0-beta.5", + "obug": "^2.1.4", + "yuku-ast": "^0.8.0", + "yuku-codegen": "^0.8.0", + "yuku-parser": "^0.8.0" + }, + "engines": { + "node": "^22.18.0 || >=24.11.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@typescript/native-preview": "*", + "@volar/typescript": "~2.4.0", + "rolldown": "^1.0.0", + "typescript": "^5.0.0 || ^6.0.0 || ~7.0.0", + "vue-tsc": "~3.2.0 || ~3.3.0" + }, + "peerDependenciesMeta": { + "@typescript/native-preview": { + "optional": true + }, + "@volar/typescript": { + "optional": true + }, + "typescript": { + "optional": true + }, + "vue-tsc": { + "optional": true + } + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-beta.38", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-beta.38.tgz", + "integrity": "sha512-AE3HFQrjWCKLFZD1Vpiy+qsqTRwwoil1oM5WsKPSmfQ5fif/A+ZtOZetF32erZdsR7qyvns6qHEteEsF6g6rsQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-beta.38", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-beta.38.tgz", + "integrity": "sha512-Ymojqc2U35iUc8NFU2XX1WQPfBRRHN6xHcrxAf9WS8BFFBn8pDrH5QPvH1tYs3lDkw6UGGbanr1RGzARqdUp1g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-beta.38", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-beta.38.tgz", + "integrity": "sha512-0ermTQ//WzSI0nOL3z/LUWMNiE9xeM5cLGxjewPFEexqxV/0uM8/lNp9QageQ8jfc/VO1OURsGw34HYO5PaL8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-beta.38", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-beta.38.tgz", + "integrity": "sha512-GADxzVUTCTp6EWI52831A29Tt7PukFe94nhg/SUsfkI33oTiNQtPxyLIT/3oRegizGuPSZSlrdBurkjDwxyEUQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-beta.38", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-beta.38.tgz", + "integrity": "sha512-SKO7Exl5Yem/OSNoA5uLHzyrptUQ8Hg70kHDxuwEaH0+GUg+SQe9/7PWmc4hFKBMrJGdQtii8WZ0uIz9Dofg5Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-beta.38", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-beta.38.tgz", + "integrity": "sha512-SOo6+WqhXPBaShLxLT0eCgH17d3Yu1lMAe4mFP0M9Bvr/kfMSOPQXuLxBcbBU9IFM9w3N6qP9xWOHO+oUJvi8Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-beta.38", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.38.tgz", + "integrity": "sha512-yvsQ3CyrodOX+lcoi+lejZGCOvJZa9xTsNB8OzpMDmHeZq3QzJfpYjXSAS6vie70fOkLVJb77UqYO193Cl8XBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-beta.38", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-beta.38.tgz", + "integrity": "sha512-84qzKMwUwikfYeOuJ4Kxm/3z15rt0nFGGQArHYIQQNSTiQdxGHxOkqXtzPFqrVfBJUdxBAf+jYzR1pttFJuWyg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-beta.38", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-beta.38.tgz", + "integrity": "sha512-QrNiWlce01DYH0rL8K3yUBu+lNzY+B0DyCbIc2Atan6/S6flxOL0ow5DLQvMamOI/oKhrJ4xG+9MkMb9dDHbLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-beta.38", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-beta.38.tgz", + "integrity": "sha512-19cTfnGedem+RY+znA9J6ARBOCEFD4YSjnx0p5jiTm9tR6pHafRfFIfKlTXhun+NL0WWM/M0eb2IfPPYUa8+wg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-beta.38", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-beta.38.tgz", + "integrity": "sha512-4Qx6cgEPXLb0XsCyLoQcUgYBpfL0sjugftob+zhUH0EOk/NVCAIT+h0NJhY+jn7pFpeKxhNMqhvTNx3AesxIAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "dev": true, + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.2", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp": { + "version": "0.34.5", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, + "node_modules/sharp/node_modules/semver": { + "version": "7.7.4", + "dev": true, + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "4.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "dev": true, + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.3.0", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/tinyexec/-/tinyexec-1.3.0.tgz", + "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyrainbow": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-poet": { + "version": "6.12.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "dprint-node": "^1.0.8" + } + }, + "node_modules/ts-proto": { + "version": "2.7.7", + "dev": true, + "license": "ISC", + "dependencies": { + "@bufbuild/protobuf": "^2.0.0", + "case-anything": "^2.1.13", + "ts-poet": "^6.12.0", + "ts-proto-descriptors": "2.0.0" + }, + "bin": { + "protoc-gen-ts_proto": "protoc-gen-ts_proto" + } + }, + "node_modules/ts-proto-descriptors": { + "version": "2.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "@bufbuild/protobuf": "^2.0.0" + } + }, + "node_modules/ts-proto-descriptors/node_modules/@bufbuild/protobuf": { + "version": "2.8.0", + "dev": true, + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/ts-proto/node_modules/@bufbuild/protobuf": { + "version": "2.8.0", + "dev": true, + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/tsdown": { + "version": "0.22.14", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/tsdown/-/tsdown-0.22.14.tgz", + "integrity": "sha512-ule7Y+fsAN2iZbLDoo7C4KYljFJNJJ+fLshyn+9gozeTspVersWHxwdGB+Dm2hzA38s6muFnUTl0jK3vJm9ifQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansis": "^4.3.1", + "cac": "^7.0.0", + "defu": "^6.1.7", + "empathic": "^2.0.1", + "hookable": "^6.1.1", + "import-without-cache": "^0.4.0", + "obug": "^2.1.4", + "picomatch": "^4.0.5", + "rolldown": "~1.2.0", + "rolldown-plugin-dts": "^0.27.13", + "tinyexec": "^1.2.4", + "tinyglobby": "^0.2.17", + "tree-kill": "^1.2.2", + "unconfig-core": "^7.5.0", + "verkit": "^0.3.0" + }, + "bin": { + "tsdown": "dist/run.mjs" + }, + "engines": { + "node": "^22.18.0 || >=24.11.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@arethetypeswrong/core": "^0.18.1", + "@tsdown/css": "0.22.14", + "@tsdown/exe": "0.22.14", + "@vitejs/devtools": "*", + "publint": "^0.3.8", + "tsx": "*", + "typescript": "^5.0.0 || ^6.0.0 || ^7.0.0", + "unplugin-unused": "^0.5.0", + "unrun": "*" + }, + "peerDependenciesMeta": { + "@arethetypeswrong/core": { + "optional": true + }, + "@tsdown/css": { + "optional": true + }, + "@tsdown/exe": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "publint": { + "optional": true + }, + "tsx": { + "optional": true + }, + "typescript": { + "optional": true + }, + "unplugin-unused": { + "optional": true + }, + "unrun": { + "optional": true + } + } + }, + "node_modules/tsdown/node_modules/@oxc-project/types": { + "version": "0.147.0", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@oxc-project/types/-/types-0.147.0.tgz", + "integrity": "sha512-IJ3s6ltHLp45S0bh7phkX+gJO7A1Wuz2EaqpAhb8WjqDwbzMiWKHhyyT42tskaWjEYXtHtVCPpnBJVT9+dcRLg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/tsdown/node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.2.6", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.6.tgz", + "integrity": "sha512-dgR56NYnvAszm7Ob1B2/Vn0e8bUQYZH2UjVaMMtMVOCKFSfjhfLmuA/9+O+F+ajUdG6B/bSssrKW6JJYASa8jA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/tsdown/node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tsdown/node_modules/rolldown": { + "version": "1.2.6", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/rolldown/-/rolldown-1.2.6.tgz", + "integrity": "sha512-vMM4q3aixf46GiF1Kok8jDPFsEpXgFWGjUHXNkNHNm+Y2adXAG2dbX91jkti3i0ZRsOlcmbuzAz1poObSHCmUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.147.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm-eabi": "1.2.6", + "@rolldown/binding-android-arm64": "1.2.6", + "@rolldown/binding-darwin-arm64": "1.2.6", + "@rolldown/binding-darwin-x64": "1.2.6", + "@rolldown/binding-freebsd-x64": "1.2.6", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.6", + "@rolldown/binding-linux-arm64-gnu": "1.2.6", + "@rolldown/binding-linux-arm64-musl": "1.2.6", + "@rolldown/binding-linux-ppc64-gnu": "1.2.6", + "@rolldown/binding-linux-s390x-gnu": "1.2.6", + "@rolldown/binding-linux-x64-gnu": "1.2.6", + "@rolldown/binding-linux-x64-musl": "1.2.6", + "@rolldown/binding-openharmony-arm64": "1.2.6", + "@rolldown/binding-win32-arm64-msvc": "1.2.6", + "@rolldown/binding-win32-x64-msvc": "1.2.6" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "dev": true, + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "5.9.3", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unconfig-core": { + "version": "7.5.0", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/unconfig-core/-/unconfig-core-7.5.0.tgz", + "integrity": "sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@quansync/fs": "^1.0.0", + "quansync": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/undici-types": { + "version": "7.12.0", + "dev": true, + "license": "MIT" + }, + "node_modules/verkit": { + "version": "0.3.2", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/verkit/-/verkit-0.3.2.tgz", + "integrity": "sha512-zj/ob3UsvJGN0whEAKFp53REA5X66hvffVqoCtVQAakJKnKlH+/PcOfMoFwIG/o4rElqLv/ycAFlx8ZlXUorCg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/vite": { + "version": "8.0.16", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.15", + "rolldown": "1.0.3", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.1.18", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/@oxc-project/types": { + "version": "0.133.0", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.3", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz", + "integrity": "sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.3", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.3", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.3.tgz", + "integrity": "sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.3", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.3.tgz", + "integrity": "sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.3", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.3.tgz", + "integrity": "sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.3", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.3.tgz", + "integrity": "sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.3", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.3.tgz", + "integrity": "sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.3", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.3.tgz", + "integrity": "sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.3", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.3.tgz", + "integrity": "sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.3", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.3.tgz", + "integrity": "sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.3", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz", + "integrity": "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.3", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.3.tgz", + "integrity": "sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.3", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.3.tgz", + "integrity": "sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.3", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.3.tgz", + "integrity": "sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.3", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.3.tgz", + "integrity": "sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/vite/node_modules/postcss": { + "version": "8.5.15", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/vite/node_modules/rolldown": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.133.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.3", + "@rolldown/binding-darwin-arm64": "1.0.3", + "@rolldown/binding-darwin-x64": "1.0.3", + "@rolldown/binding-freebsd-x64": "1.0.3", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.3", + "@rolldown/binding-linux-arm64-gnu": "1.0.3", + "@rolldown/binding-linux-arm64-musl": "1.0.3", + "@rolldown/binding-linux-ppc64-gnu": "1.0.3", + "@rolldown/binding-linux-s390x-gnu": "1.0.3", + "@rolldown/binding-linux-x64-gnu": "1.0.3", + "@rolldown/binding-linux-x64-musl": "1.0.3", + "@rolldown/binding-openharmony-arm64": "1.0.3", + "@rolldown/binding-wasm32-wasi": "1.0.3", + "@rolldown/binding-win32-arm64-msvc": "1.0.3", + "@rolldown/binding-win32-x64-msvc": "1.0.3" + } + }, + "node_modules/vitest": { + "version": "4.1.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.8", + "@vitest/mocker": "4.1.8", + "@vitest/pretty-format": "4.1.8", + "@vitest/runner": "4.1.8", + "@vitest/snapshot": "4.1.8", + "@vitest/spy": "4.1.8", + "@vitest/utils": "4.1.8", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.8", + "@vitest/browser-preview": "4.1.8", + "@vitest/browser-webdriverio": "4.1.8", + "@vitest/coverage-istanbul": "4.1.8", + "@vitest/coverage-v8": "4.1.8", + "@vitest/ui": "4.1.8", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ws": { + "version": "8.21.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yuku-ast": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/yuku-ast/-/yuku-ast-0.8.7.tgz", + "integrity": "sha512-h6+4bDfyootiMB9vckk5uKo5r5j0GHrkr17FQTDNfEsFT3DWlN9uu1HJwQwc64pgmLCI945fWM3lbTIqxjT3GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@yuku-toolchain/types": "^0.8.7" + } + }, + "node_modules/yuku-codegen": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/yuku-codegen/-/yuku-codegen-0.8.7.tgz", + "integrity": "sha512-adwDZSh8oVDzhE6Du9PwVWxcOxeV0e2EVhUuMKWfhSY4wkrDq9eqixlxFF3l/XGUV1E7UFzhpz9393MUumkyNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@yuku-toolchain/types": "^0.8.7" + }, + "optionalDependencies": { + "@yuku-codegen/binding-android-arm64": "0.8.7", + "@yuku-codegen/binding-darwin-arm64": "0.8.7", + "@yuku-codegen/binding-darwin-x64": "0.8.7", + "@yuku-codegen/binding-freebsd-x64": "0.8.7", + "@yuku-codegen/binding-linux-arm-gnu": "0.8.7", + "@yuku-codegen/binding-linux-arm-musl": "0.8.7", + "@yuku-codegen/binding-linux-arm64-gnu": "0.8.7", + "@yuku-codegen/binding-linux-arm64-musl": "0.8.7", + "@yuku-codegen/binding-linux-x64-gnu": "0.8.7", + "@yuku-codegen/binding-linux-x64-musl": "0.8.7", + "@yuku-codegen/binding-win32-arm64": "0.8.7", + "@yuku-codegen/binding-win32-x64": "0.8.7" + } + }, + "node_modules/yuku-parser": { + "version": "0.8.7", + "resolved": "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/yuku-parser/-/yuku-parser-0.8.7.tgz", + "integrity": "sha512-vRD9nwt4L3aYpxNqeSC4WqLv58xrXef0Ong1Mc45CTXTIpvLafx7JO05sczmQZwdLEZvywrLOGdNC5+Rp5N1BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@yuku-toolchain/types": "^0.8.7", + "yuku-ast": "^0.8.7" + }, + "optionalDependencies": { + "@yuku-parser/binding-android-arm64": "0.8.7", + "@yuku-parser/binding-darwin-arm64": "0.8.7", + "@yuku-parser/binding-darwin-x64": "0.8.7", + "@yuku-parser/binding-freebsd-x64": "0.8.7", + "@yuku-parser/binding-linux-arm-gnu": "0.8.7", + "@yuku-parser/binding-linux-arm-musl": "0.8.7", + "@yuku-parser/binding-linux-arm64-gnu": "0.8.7", + "@yuku-parser/binding-linux-arm64-musl": "0.8.7", + "@yuku-parser/binding-linux-x64-gnu": "0.8.7", + "@yuku-parser/binding-linux-x64-musl": "0.8.7", + "@yuku-parser/binding-win32-arm64": "0.8.7", + "@yuku-parser/binding-win32-x64": "0.8.7" + } + } + } +} diff --git a/openfeature-provider/python/src/confidence/proto/confidence/events/v1/api_pb2.py b/openfeature-provider/python/src/confidence/proto/confidence/events/v1/api_pb2.py index ffe93a137..6802f2d65 100644 --- a/openfeature-provider/python/src/confidence/proto/confidence/events/v1/api_pb2.py +++ b/openfeature-provider/python/src/confidence/proto/confidence/events/v1/api_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: confidence/events/v1/api.proto -# Protobuf Python Version: 6.31.1 +# Protobuf Python Version: 5.29.0 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -11,9 +11,9 @@ from google.protobuf.internal import builder as _builder _runtime_version.ValidateProtobufRuntimeVersion( _runtime_version.Domain.PUBLIC, - 6, - 31, - 1, + 5, + 29, + 0, '', 'confidence/events/v1/api.proto' ) @@ -23,7 +23,7 @@ from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 -from . import types_pb2 as confidence_dot_events_dot_v1_dot_types__pb2 +from confidence.events.v1 import types_pb2 as confidence_dot_events_dot_v1_dot_types__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1e\x63onfidence/events/v1/api.proto\x12\x14\x63onfidence.events.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a confidence/events/v1/types.proto\"\xb1\x01\n\x14PublishEventsRequest\x12\x15\n\rclient_secret\x18\x01 \x01(\t\x12+\n\x06\x65vents\x18\x02 \x03(\x0b\x32\x1b.confidence.events.v1.Event\x12-\n\tsend_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12&\n\x03sdk\x18\x04 \x01(\x0b\x32\x19.confidence.events.v1.Sdk\"I\n\x15PublishEventsResponse\x12\x30\n\x06\x65rrors\x18\x01 \x03(\x0b\x32 .confidence.events.v1.EventError2y\n\rEventsService\x12h\n\rPublishEvents\x12*.confidence.events.v1.PublishEventsRequest\x1a+.confidence.events.v1.PublishEventsResponseB\x93\x01\n$com.spotify.confidence.sdk.events.v1B\x08\x41piProtoP\x01Z_github.com/spotify/confidence-resolver/openfeature-provider/go/confidence/internal/proto/eventsb\x06proto3') diff --git a/openfeature-provider/python/src/confidence/proto/confidence/events/v1/api_pb2_grpc.py b/openfeature-provider/python/src/confidence/proto/confidence/events/v1/api_pb2_grpc.py index 046ab81e5..72231f94a 100644 --- a/openfeature-provider/python/src/confidence/proto/confidence/events/v1/api_pb2_grpc.py +++ b/openfeature-provider/python/src/confidence/proto/confidence/events/v1/api_pb2_grpc.py @@ -3,7 +3,7 @@ import grpc import warnings -from . import api_pb2 as confidence_dot_events_dot_v1_dot_api__pb2 +from confidence.events.v1 import api_pb2 as confidence_dot_events_dot_v1_dot_api__pb2 GRPC_GENERATED_VERSION = '1.70.0' GRPC_VERSION = grpc.__version__ @@ -18,7 +18,7 @@ if _version_not_supported: raise RuntimeError( f'The grpc package installed is at version {GRPC_VERSION},' - + ' but the generated code in confidence/events/v1/api_pb2_grpc.py depends on' + + f' but the generated code in confidence/events/v1/api_pb2_grpc.py depends on' + f' grpcio>={GRPC_GENERATED_VERSION}.' + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' diff --git a/openfeature-provider/python/src/confidence/proto/confidence/events/v1/types_pb2.py b/openfeature-provider/python/src/confidence/proto/confidence/events/v1/types_pb2.py index 8ff279925..75328d2e6 100644 --- a/openfeature-provider/python/src/confidence/proto/confidence/events/v1/types_pb2.py +++ b/openfeature-provider/python/src/confidence/proto/confidence/events/v1/types_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: confidence/events/v1/types.proto -# Protobuf Python Version: 6.31.1 +# Protobuf Python Version: 5.29.0 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -11,9 +11,9 @@ from google.protobuf.internal import builder as _builder _runtime_version.ValidateProtobufRuntimeVersion( _runtime_version.Domain.PUBLIC, - 6, - 31, - 1, + 5, + 29, + 0, '', 'confidence/events/v1/types.proto' ) diff --git a/openfeature-provider/python/src/confidence/proto/confidence/events/v1/types_pb2_grpc.py b/openfeature-provider/python/src/confidence/proto/confidence/events/v1/types_pb2_grpc.py index a314adab8..e5c206b55 100644 --- a/openfeature-provider/python/src/confidence/proto/confidence/events/v1/types_pb2_grpc.py +++ b/openfeature-provider/python/src/confidence/proto/confidence/events/v1/types_pb2_grpc.py @@ -4,7 +4,7 @@ import warnings -GRPC_GENERATED_VERSION = '1.78.0' +GRPC_GENERATED_VERSION = '1.70.0' GRPC_VERSION = grpc.__version__ _version_not_supported = False @@ -17,7 +17,7 @@ if _version_not_supported: raise RuntimeError( f'The grpc package installed is at version {GRPC_VERSION},' - + ' but the generated code in confidence/events/v1/types_pb2_grpc.py depends on' + + f' but the generated code in confidence/events/v1/types_pb2_grpc.py depends on' + f' grpcio>={GRPC_GENERATED_VERSION}.' + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' diff --git a/openfeature-provider/python/src/confidence/proto/confidence/events/wasm/v1/wasm_api_pb2.py b/openfeature-provider/python/src/confidence/proto/confidence/events/wasm/v1/wasm_api_pb2.py index 0ca4c4968..25c4e086e 100644 --- a/openfeature-provider/python/src/confidence/proto/confidence/events/wasm/v1/wasm_api_pb2.py +++ b/openfeature-provider/python/src/confidence/proto/confidence/events/wasm/v1/wasm_api_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: confidence/events/wasm/v1/wasm_api.proto -# Protobuf Python Version: 6.31.1 +# Protobuf Python Version: 5.29.0 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -11,9 +11,9 @@ from google.protobuf.internal import builder as _builder _runtime_version.ValidateProtobufRuntimeVersion( _runtime_version.Domain.PUBLIC, - 6, - 31, - 1, + 5, + 29, + 0, '', 'confidence/events/wasm/v1/wasm_api.proto' ) @@ -24,7 +24,7 @@ from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 -from ...v1 import types_pb2 as confidence_dot_events_dot_v1_dot_types__pb2 +from confidence.events.v1 import types_pb2 as confidence_dot_events_dot_v1_dot_types__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n(confidence/events/wasm/v1/wasm_api.proto\x12\x19\x63onfidence.events.wasm.v1\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a confidence/events/v1/types.proto\"\x06\n\x04Void\"\xc6\x01\n\x11TrackEventRequest\x12\x12\n\nevent_name\x18\x01 \x01(\t\x12.\n\nevent_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\x05value\x18\x03 \x01(\x01H\x00\x88\x01\x01\x12(\n\x07\x63ontext\x18\x04 \x01(\x0b\x32\x17.google.protobuf.Struct\x12%\n\x04\x64\x61ta\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructB\x08\n\x06_value\"B\n\x13\x46lushEventsResponse\x12+\n\x06\x65vents\x18\x01 \x03(\x0b\x32\x1b.confidence.events.v1.EventB\xa0\x01\n)com.spotify.confidence.sdk.events.wasm.v1B\x0cWasmApiProtoP\x01Zcgithub.com/spotify/confidence-resolver/openfeature-provider/go/confidence/internal/proto/eventswasmb\x06proto3') diff --git a/openfeature-provider/python/src/confidence/proto/confidence/events/wasm/v1/wasm_api_pb2_grpc.py b/openfeature-provider/python/src/confidence/proto/confidence/events/wasm/v1/wasm_api_pb2_grpc.py index 9fd4079a1..8f9f167c7 100644 --- a/openfeature-provider/python/src/confidence/proto/confidence/events/wasm/v1/wasm_api_pb2_grpc.py +++ b/openfeature-provider/python/src/confidence/proto/confidence/events/wasm/v1/wasm_api_pb2_grpc.py @@ -4,7 +4,7 @@ import warnings -GRPC_GENERATED_VERSION = '1.78.0' +GRPC_GENERATED_VERSION = '1.70.0' GRPC_VERSION = grpc.__version__ _version_not_supported = False @@ -17,7 +17,7 @@ if _version_not_supported: raise RuntimeError( f'The grpc package installed is at version {GRPC_VERSION},' - + ' but the generated code in confidence/events/wasm/v1/wasm_api_pb2_grpc.py depends on' + + f' but the generated code in confidence/events/wasm/v1/wasm_api_pb2_grpc.py depends on' + f' grpcio>={GRPC_GENERATED_VERSION}.' + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' diff --git a/openfeature-provider/python/src/confidence/proto/confidence/flags/admin/v1/resolver_pb2.py b/openfeature-provider/python/src/confidence/proto/confidence/flags/admin/v1/resolver_pb2.py index c08df5c76..9afdc52f4 100644 --- a/openfeature-provider/python/src/confidence/proto/confidence/flags/admin/v1/resolver_pb2.py +++ b/openfeature-provider/python/src/confidence/proto/confidence/flags/admin/v1/resolver_pb2.py @@ -23,8 +23,8 @@ from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 -from ...types.v1 import types_pb2 as confidence_dot_flags_dot_types_dot_v1_dot_types__pb2 -from ...types.v1 import target_pb2 as confidence_dot_flags_dot_types_dot_v1_dot_target__pb2 +from confidence.flags.types.v1 import types_pb2 as confidence_dot_flags_dot_types_dot_v1_dot_types__pb2 +from confidence.flags.types.v1 import target_pb2 as confidence_dot_flags_dot_types_dot_v1_dot_target__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n(confidence/flags/admin/v1/resolver.proto\x12\x19\x63onfidence.flags.admin.v1\x1a\x1cgoogle/protobuf/struct.proto\x1a%confidence/flags/types/v1/types.proto\x1a&confidence/flags/types/v1/target.proto\"z\n\x13\x43lientResolverState\x12\r\n\x05state\x18\x01 \x01(\x0c\x12\x0f\n\x07\x61\x63\x63ount\x18\x02 \x01(\t\x12\x43\n\x10log_destinations\x18\x04 \x03(\x0e\x32).confidence.flags.admin.v1.LogDestination\"\xa2\x04\n\rResolverState\x12.\n\x05\x66lags\x18\x01 \x03(\x0b\x32\x1f.confidence.flags.admin.v1.Flag\x12?\n\x13segments_no_bitsets\x18\x02 \x03(\x0b\x32\".confidence.flags.admin.v1.Segment\x12\x46\n\x07\x62itsets\x18\x05 \x03(\x0b\x32\x35.confidence.flags.admin.v1.ResolverState.PackedBitset\x12\x32\n\x07\x63lients\x18\x06 \x03(\x0b\x32!.confidence.flags.admin.v1.Client\x12G\n\x12\x63lient_credentials\x18\x07 \x03(\x0b\x32+.confidence.flags.admin.v1.ClientCredential\x12?\n\x06region\x18\x08 \x01(\x0e\x32/.confidence.flags.admin.v1.ResolverState.Region\x1aZ\n\x0cPackedBitset\x12\x0f\n\x07segment\x18\x01 \x01(\t\x12\x18\n\x0egzipped_bitset\x18\x02 \x01(\x0cH\x00\x12\x15\n\x0b\x66ull_bitset\x18\x03 \x01(\x08H\x00\x42\x08\n\x06\x62itset\">\n\x06Region\x12\x16\n\x12REGION_UNSPECIFIED\x10\x00\x12\r\n\tREGION_EU\x10\x01\x12\r\n\tREGION_US\x10\x02\"\xc9\x0c\n\x04\x46lag\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\r \x01(\t\x12\x46\n\x06schema\x18\x02 \x01(\x0b\x32\x36.confidence.flags.types.v1.FlagSchema.StructFlagSchema\x12\x39\n\x08variants\x18\x03 \x03(\x0b\x32\'.confidence.flags.admin.v1.Flag.Variant\x12\x34\n\x05state\x18\x04 \x01(\x0e\x32%.confidence.flags.admin.v1.Flag.State\x12\x33\n\x05rules\x18\x05 \x03(\x0b\x32$.confidence.flags.admin.v1.Flag.Rule\x12\x0f\n\x07\x63lients\x18\x0c \x03(\t\x1a?\n\x07Variant\x12\x0c\n\x04name\x18\x01 \x01(\t\x12&\n\x05value\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct\x1a\xa3\t\n\x04Rule\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07segment\x18\x02 \x01(\t\x12L\n\x0f\x61ssignment_spec\x18\x0c \x01(\x0b\x32\x33.confidence.flags.admin.v1.Flag.Rule.AssignmentSpec\x12\x1e\n\x16targeting_key_selector\x18\x05 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x0b \x01(\x08\x12V\n\x14materialization_spec\x18\r \x01(\x0b\x32\x38.confidence.flags.admin.v1.Flag.Rule.MaterializationSpec\x1a\x9b\x02\n\x13MaterializationSpec\x12\x1d\n\x15write_materialization\x18\x01 \x01(\t\x12\x1c\n\x14read_materialization\x18\x02 \x01(\t\x12^\n\x04mode\x18\x03 \x01(\x0b\x32P.confidence.flags.admin.v1.Flag.Rule.MaterializationSpec.MaterializationReadMode\x1ag\n\x17MaterializationReadMode\x12\"\n\x1amaterialization_must_match\x18\x01 \x01(\x08\x12(\n segment_targeting_can_be_ignored\x18\x02 \x01(\x08\x1al\n\x0e\x41ssignmentSpec\x12\x14\n\x0c\x62ucket_count\x18\x01 \x01(\x05\x12\x44\n\x0b\x61ssignments\x18\x02 \x03(\x0b\x32/.confidence.flags.admin.v1.Flag.Rule.Assignment\x1a\xeb\x03\n\nAssignment\x12\x15\n\rassignment_id\x18\x01 \x01(\t\x12T\n\x07variant\x18\x02 \x01(\x0b\x32\x41.confidence.flags.admin.v1.Flag.Rule.Assignment.VariantAssignmentH\x00\x12\\\n\x0b\x66\x61llthrough\x18\x03 \x01(\x0b\x32\x45.confidence.flags.admin.v1.Flag.Rule.Assignment.FallthroughAssignmentH\x00\x12\x61\n\x0e\x63lient_default\x18\x04 \x01(\x0b\x32G.confidence.flags.admin.v1.Flag.Rule.Assignment.ClientDefaultAssignmentH\x00\x12G\n\rbucket_ranges\x18\x05 \x03(\x0b\x32\x30.confidence.flags.admin.v1.Flag.Rule.BucketRange\x1a$\n\x11VariantAssignment\x12\x0f\n\x07variant\x18\x01 \x01(\t\x1a\x17\n\x15\x46\x61llthroughAssignment\x1a\x19\n\x17\x43lientDefaultAssignmentB\x0c\n\nassignment\x1a+\n\x0b\x42ucketRange\x12\r\n\x05lower\x18\x01 \x01(\x05\x12\r\n\x05upper\x18\x02 \x01(\x05\"8\n\x05State\x12\x15\n\x11STATE_UNSPECIFIED\x10\x00\x12\n\n\x06\x41\x43TIVE\x10\x01\x12\x0c\n\x08\x41RCHIVED\x10\x02\"\xef\x02\n\x07Segment\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x0c \x01(\t\x12\x37\n\ttargeting\x18\x02 \x01(\x0b\x32$.confidence.flags.types.v1.Targeting\x12\x41\n\nallocation\x18\x03 \x01(\x0b\x32-.confidence.flags.admin.v1.Segment.Allocation\x12N\n\x11\x62itset_allocation\x18\x06 \x01(\x0b\x32\x33.confidence.flags.admin.v1.Segment.BitsetAllocation\x1aP\n\nAllocation\x12\x12\n\nproportion\x18\x01 \x01(\t\x12\x18\n\x10\x65xclusivity_tags\x18\x03 \x03(\t\x12\x14\n\x0c\x65xclusive_to\x18\x04 \x03(\t\x1a\"\n\x10\x42itsetAllocation\x12\x0e\n\x06\x62itset\x18\x01 \x01(\x0c\"\x90\x0b\n\tCondition\x12\x43\n\x0etrue_condition\x18\x01 \x01(\x0b\x32).confidence.flags.admin.v1.Condition.TrueH\x00\x12\x45\n\x0f\x66\x61lse_condition\x18\x02 \x01(\x0b\x32*.confidence.flags.admin.v1.Condition.FalseH\x00\x12\x37\n\x03\x61nd\x18\x03 \x01(\x0b\x32(.confidence.flags.admin.v1.Condition.AndH\x00\x12\x35\n\x02or\x18\x04 \x01(\x0b\x32\'.confidence.flags.admin.v1.Condition.OrH\x00\x12\x37\n\x03not\x18\x05 \x01(\x0b\x32(.confidence.flags.admin.v1.Condition.NotH\x00\x12\x45\n\ncomparison\x18\x06 \x01(\x0b\x32/.confidence.flags.admin.v1.Condition.ComparisonH\x00\x12_\n\x18\x63ontext_field_comparison\x18\x07 \x01(\x0b\x32;.confidence.flags.admin.v1.Condition.ContextFieldComparisonH\x00\x1a\x06\n\x04True\x1a\x07\n\x05\x46\x61lse\x1a?\n\x03\x41nd\x12\x38\n\nconditions\x18\x01 \x03(\x0b\x32$.confidence.flags.admin.v1.Condition\x1a>\n\x02Or\x12\x38\n\nconditions\x18\x01 \x03(\x0b\x32$.confidence.flags.admin.v1.Condition\x1a>\n\x03Not\x12\x37\n\tcondition\x18\x01 \x01(\x0b\x32$.confidence.flags.admin.v1.Condition\x1a\x98\x03\n\nComparison\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12J\n\x08operator\x18\x02 \x01(\x0e\x32\x38.confidence.flags.admin.v1.Condition.Comparison.Operator\x12%\n\x05value\x18\x03 \x01(\x0b\x32\x16.google.protobuf.Value\"\x87\x02\n\x08Operator\x12\x18\n\x14OPERATOR_UNSPECIFIED\x10\x00\x12\n\n\x06\x45QUALS\x10\x01\x12\x0e\n\nNOT_EQUALS\x10\x02\x12\r\n\tLESS_THAN\x10\x03\x12\x16\n\x12LESS_THAN_OR_EQUAL\x10\x04\x12\x10\n\x0cGREATER_THAN\x10\x05\x12\x19\n\x15GREATER_THAN_OR_EQUAL\x10\x06\x12\x0c\n\x08\x43ONTAINS\x10\x07\x12\x0f\n\x0bSTARTS_WITH\x10\x08\x12\r\n\tENDS_WITH\x10\t\x12\x0b\n\x07MATCHES\x10\n\x12\x06\n\x02IN\x10\x0b\x12\n\n\x06NOT_IN\x10\x0c\x12\x10\n\x0c\x43ONTAINS_ANY\x10\r\x12\x10\n\x0c\x43ONTAINS_ALL\x10\x0e\x1a\xab\x02\n\x16\x43ontextFieldComparison\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12V\n\x08operator\x18\x02 \x01(\x0e\x32\x44.confidence.flags.admin.v1.Condition.ContextFieldComparison.Operator\x12\x13\n\x0bother_field\x18\x03 \x01(\t\"\x94\x01\n\x08Operator\x12\x18\n\x14OPERATOR_UNSPECIFIED\x10\x00\x12\n\n\x06\x45QUALS\x10\x01\x12\x0e\n\nNOT_EQUALS\x10\x02\x12\r\n\tLESS_THAN\x10\x03\x12\x16\n\x12LESS_THAN_OR_EQUAL\x10\x04\x12\x10\n\x0cGREATER_THAN\x10\x05\x12\x19\n\x15GREATER_THAN_OR_EQUAL\x10\x06\x42\x0b\n\tcondition\",\n\x06\x43lient\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x02 \x01(\t\"\xa1\x01\n\x10\x43lientCredential\x12\x0c\n\x04name\x18\x01 \x01(\t\x12Q\n\rclient_secret\x18\x03 \x01(\x0b\x32\x38.confidence.flags.admin.v1.ClientCredential.ClientSecretH\x00\x1a\x1e\n\x0c\x43lientSecret\x12\x0e\n\x06secret\x18\x01 \x01(\tB\x0c\n\ncredential*s\n\x0eLogDestination\x12\x1f\n\x1bLOG_DESTINATION_UNSPECIFIED\x10\x00\x12 \n\x1cLOG_DESTINATION_SPOTIFY_EDGE\x10\x01\x12\x1e\n\x1aLOG_DESTINATION_CLOUDFLARE\x10\x02\x42\x9c\x01\n)com.spotify.confidence.sdk.flags.admin.v1B\rResolverProtoP\x01Z^github.com/spotify/confidence-resolver/openfeature-provider/go/confidence/internal/proto/adminb\x06proto3') diff --git a/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/api_pb2.py b/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/api_pb2.py index 31c44efd2..3ebc26fd8 100644 --- a/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/api_pb2.py +++ b/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/api_pb2.py @@ -24,8 +24,8 @@ from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 -from . import types_pb2 as confidence_dot_flags_dot_resolver_dot_v1_dot_types__pb2 -from ...types.v1 import types_pb2 as confidence_dot_flags_dot_types_dot_v1_dot_types__pb2 +from confidence.flags.resolver.v1 import types_pb2 as confidence_dot_flags_dot_resolver_dot_v1_dot_types__pb2 +from confidence.flags.types.v1 import types_pb2 as confidence_dot_flags_dot_types_dot_v1_dot_types__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n&confidence/flags/resolver/v1/api.proto\x12\x1c\x63onfidence.flags.resolver.v1\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a(confidence/flags/resolver/v1/types.proto\x1a%confidence/flags/types/v1/types.proto\"\xaf\x01\n\x13ResolveFlagsRequest\x12\r\n\x05\x66lags\x18\x01 \x03(\t\x12\x33\n\x12\x65valuation_context\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct\x12\x15\n\rclient_secret\x18\x03 \x01(\t\x12\r\n\x05\x61pply\x18\x04 \x01(\x08\x12.\n\x03sdk\x18\x05 \x01(\x0b\x32!.confidence.flags.resolver.v1.Sdk\"\x85\x01\n\x14ResolveFlagsResponse\x12\x42\n\x0eresolved_flags\x18\x01 \x03(\x0b\x32*.confidence.flags.resolver.v1.ResolvedFlag\x12\x15\n\rresolve_token\x18\x02 \x01(\x0c\x12\x12\n\nresolve_id\x18\x03 \x01(\t\"\xda\x01\n\x11\x41pplyFlagsRequest\x12\x38\n\x05\x66lags\x18\x01 \x03(\x0b\x32).confidence.flags.resolver.v1.AppliedFlag\x12\x15\n\rclient_secret\x18\x02 \x01(\t\x12\x15\n\rresolve_token\x18\x03 \x01(\x0c\x12-\n\tsend_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\x03sdk\x18\x05 \x01(\x0b\x32!.confidence.flags.resolver.v1.Sdk\"\x14\n\x12\x41pplyFlagsResponse\"K\n\x0b\x41ppliedFlag\x12\x0c\n\x04\x66lag\x18\x01 \x01(\t\x12.\n\napply_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\x90\x02\n\x0cResolvedFlag\x12\x0c\n\x04\x66lag\x18\x01 \x01(\t\x12\x0f\n\x07variant\x18\x02 \x01(\t\x12&\n\x05value\x18\x03 \x01(\x0b\x32\x17.google.protobuf.Struct\x12K\n\x0b\x66lag_schema\x18\x04 \x01(\x0b\x32\x36.confidence.flags.types.v1.FlagSchema.StructFlagSchema\x12;\n\x06reason\x18\x05 \x01(\x0e\x32+.confidence.flags.resolver.v1.ResolveReason\x12\x14\n\x0cshould_apply\x18\x06 \x01(\x08\x12\x19\n\x11\x61ssignment_origin\x18\x07 \x01(\t2\x8e\x01\n\x13\x46lagResolverService\x12w\n\x0cResolveFlags\x12\x31.confidence.flags.resolver.v1.ResolveFlagsRequest\x1a\x32.confidence.flags.resolver.v1.ResolveFlagsResponse\"\x00\x42\x9d\x01\n,com.spotify.confidence.sdk.flags.resolver.v1B\x08\x41piProtoP\x01Zagithub.com/spotify/confidence-resolver/openfeature-provider/go/confidence/internal/proto/resolverb\x06proto3') diff --git a/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/api_pb2_grpc.py b/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/api_pb2_grpc.py index 6f4d114cd..1c1cfe7fd 100644 --- a/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/api_pb2_grpc.py +++ b/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/api_pb2_grpc.py @@ -3,7 +3,7 @@ import grpc import warnings -from . import api_pb2 as confidence_dot_flags_dot_resolver_dot_v1_dot_api__pb2 +from confidence.flags.resolver.v1 import api_pb2 as confidence_dot_flags_dot_resolver_dot_v1_dot_api__pb2 GRPC_GENERATED_VERSION = '1.70.0' GRPC_VERSION = grpc.__version__ diff --git a/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2_grpc.py b/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2_grpc.py index dce37bdce..ea5ec5c7a 100644 --- a/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2_grpc.py +++ b/openfeature-provider/python/src/confidence/proto/confidence/flags/resolver/v1/internal_api_pb2_grpc.py @@ -3,7 +3,7 @@ import grpc import warnings -from . import internal_api_pb2 as confidence_dot_flags_dot_resolver_dot_v1_dot_internal__api__pb2 +from confidence.flags.resolver.v1 import internal_api_pb2 as confidence_dot_flags_dot_resolver_dot_v1_dot_internal__api__pb2 GRPC_GENERATED_VERSION = '1.70.0' GRPC_VERSION = grpc.__version__ diff --git a/openfeature-provider/python/src/confidence/proto/confidence/wasm/messages_pb2.py b/openfeature-provider/python/src/confidence/proto/confidence/wasm/messages_pb2.py index 5c1c39a64..c84e3ec39 100644 --- a/openfeature-provider/python/src/confidence/proto/confidence/wasm/messages_pb2.py +++ b/openfeature-provider/python/src/confidence/proto/confidence/wasm/messages_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: confidence/wasm/messages.proto -# Protobuf Python Version: 6.31.1 +# Protobuf Python Version: 5.29.0 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -11,9 +11,9 @@ from google.protobuf.internal import builder as _builder _runtime_version.ValidateProtobufRuntimeVersion( _runtime_version.Domain.PUBLIC, - 6, - 31, - 1, + 5, + 29, + 0, '', 'confidence/wasm/messages.proto' ) @@ -22,10 +22,10 @@ _sym_db = _symbol_database.Default() -from ..flags.resolver.v1 import types_pb2 as confidence_dot_flags_dot_resolver_dot_v1_dot_types__pb2 +from confidence.flags.resolver.v1 import types_pb2 as confidence_dot_flags_dot_resolver_dot_v1_dot_types__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1econfidence/wasm/messages.proto\x12\x0fconfidence.wasm\x1a(confidence/flags/resolver/v1/types.proto"\x06\n\x04Void"\xad\x01\n\x17SetResolverStateRequest\x12\r\n\x05state\x18\x01 \x01(\x0c\x12\x12\n\naccount_id\x18\x02 \x01(\t\x12.\n\x03sdk\x18\x03 \x01(\x0b2!.confidence.flags.resolver.v1.Sdk\x12\x1a\n\x12enable_apply_dedup\x18\x04 \x01(\x08\x12#\n\x1bdisable_exposure_collection\x18\x05 \x01(\x08"\x17\n\x07Request\x12\x0c\n\x04data\x18\x01 \x01(\x0c"5\n\x08Response\x12\x0e\n\x04data\x18\x01 \x01(\x0cH\x00\x12\x0f\n\x05error\x18\x02 \x01(\tH\x00B\x08\n\x06result"^\n\x19PrometheusSnapshotRequest\x12\x10\n\x08instance\x18\x01 \x01(\t\x12\x1a\n\x12buckets_per_decade\x18\x02 \x01(\r\x12\x13\n\x0bopenmetrics\x18\x03 \x01(\x08"*\n\x1aPrometheusSnapshotResponse\x12\x0c\n\x04text\x18\x01 \x01(\tB\x8c\x01\n\x1fcom.spotify.confidence.sdk.wasmB\x08MessagesP\x00Z]github.com/spotify/confidence-resolver/openfeature-provider/go/confidence/internal/proto/wasmb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1e\x63onfidence/wasm/messages.proto\x12\x0f\x63onfidence.wasm\x1a(confidence/flags/resolver/v1/types.proto\"\x06\n\x04Void\"\xad\x01\n\x17SetResolverStateRequest\x12\r\n\x05state\x18\x01 \x01(\x0c\x12\x12\n\naccount_id\x18\x02 \x01(\t\x12.\n\x03sdk\x18\x03 \x01(\x0b\x32!.confidence.flags.resolver.v1.Sdk\x12\x1a\n\x12\x65nable_apply_dedup\x18\x04 \x01(\x08\x12#\n\x1b\x64isable_exposure_collection\x18\x05 \x01(\x08\"\x17\n\x07Request\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\"5\n\x08Response\x12\x0e\n\x04\x64\x61ta\x18\x01 \x01(\x0cH\x00\x12\x0f\n\x05\x65rror\x18\x02 \x01(\tH\x00\x42\x08\n\x06result\"^\n\x19PrometheusSnapshotRequest\x12\x10\n\x08instance\x18\x01 \x01(\t\x12\x1a\n\x12\x62uckets_per_decade\x18\x02 \x01(\r\x12\x13\n\x0bopenmetrics\x18\x03 \x01(\x08\"*\n\x1aPrometheusSnapshotResponse\x12\x0c\n\x04text\x18\x01 \x01(\tB\x8c\x01\n\x1f\x63om.spotify.confidence.sdk.wasmB\x08MessagesP\x00Z]github.com/spotify/confidence-resolver/openfeature-provider/go/confidence/internal/proto/wasmb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) diff --git a/openfeature-provider/python/src/confidence/proto/confidence/wasm/messages_pb2_grpc.py b/openfeature-provider/python/src/confidence/proto/confidence/wasm/messages_pb2_grpc.py index f38527c39..1c4e8c13d 100644 --- a/openfeature-provider/python/src/confidence/proto/confidence/wasm/messages_pb2_grpc.py +++ b/openfeature-provider/python/src/confidence/proto/confidence/wasm/messages_pb2_grpc.py @@ -4,7 +4,7 @@ import warnings -GRPC_GENERATED_VERSION = '1.78.0' +GRPC_GENERATED_VERSION = '1.70.0' GRPC_VERSION = grpc.__version__ _version_not_supported = False @@ -17,7 +17,7 @@ if _version_not_supported: raise RuntimeError( f'The grpc package installed is at version {GRPC_VERSION},' - + ' but the generated code in confidence/wasm/messages_pb2_grpc.py depends on' + + f' but the generated code in confidence/wasm/messages_pb2_grpc.py depends on' + f' grpcio>={GRPC_GENERATED_VERSION}.' + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' diff --git a/openfeature-provider/python/src/confidence/proto/confidence/wasm/wasm_api_pb2.py b/openfeature-provider/python/src/confidence/proto/confidence/wasm/wasm_api_pb2.py index ed651bfdd..b410ae531 100644 --- a/openfeature-provider/python/src/confidence/proto/confidence/wasm/wasm_api_pb2.py +++ b/openfeature-provider/python/src/confidence/proto/confidence/wasm/wasm_api_pb2.py @@ -22,8 +22,8 @@ _sym_db = _symbol_database.Default() -from ..flags.resolver.v1 import api_pb2 as confidence_dot_flags_dot_resolver_dot_v1_dot_api__pb2 -from ..flags.resolver.v1 import types_pb2 as confidence_dot_flags_dot_resolver_dot_v1_dot_types__pb2 +from confidence.flags.resolver.v1 import api_pb2 as confidence_dot_flags_dot_resolver_dot_v1_dot_api__pb2 +from confidence.flags.resolver.v1 import types_pb2 as confidence_dot_flags_dot_resolver_dot_v1_dot_types__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1e\x63onfidence/wasm/wasm_api.proto\x12\x1c\x63onfidence.flags.resolver.v1\x1a&confidence/flags/resolver/v1/api.proto\x1a(confidence/flags/resolver/v1/types.proto\"\xac\x05\n\x15ResolveProcessRequest\x12V\n\x19\x64\x65\x66\x65rred_materializations\x18\x01 \x01(\x0b\x32\x31.confidence.flags.resolver.v1.ResolveFlagsRequestH\x00\x12m\n\x17static_materializations\x18\x02 \x01(\x0b\x32J.confidence.flags.resolver.v1.ResolveProcessRequest.StaticMaterializationsH\x00\x12U\n\x18without_materializations\x18\x03 \x01(\x0b\x32\x31.confidence.flags.resolver.v1.ResolveFlagsRequestH\x00\x12L\n\x06resume\x18\x04 \x01(\x0b\x32:.confidence.flags.resolver.v1.ResolveProcessRequest.ResumeH\x00\x1a\xb3\x01\n\x16StaticMaterializations\x12J\n\x0fresolve_request\x18\x01 \x01(\x0b\x32\x31.confidence.flags.resolver.v1.ResolveFlagsRequest\x12M\n\x10materializations\x18\x02 \x03(\x0b\x32\x33.confidence.flags.resolver.v1.MaterializationRecord\x1a\x66\n\x06Resume\x12M\n\x10materializations\x18\x01 \x03(\x0b\x32\x33.confidence.flags.resolver.v1.MaterializationRecord\x12\r\n\x05state\x18\x02 \x01(\x0c\x42\t\n\x07resolve\"\xe8\x03\n\x16ResolveProcessResponse\x12Q\n\x08resolved\x18\x01 \x01(\x0b\x32=.confidence.flags.resolver.v1.ResolveProcessResponse.ResolvedH\x00\x12S\n\tsuspended\x18\x02 \x01(\x0b\x32>.confidence.flags.resolver.v1.ResolveProcessResponse.SuspendedH\x00\x1a\xa8\x01\n\x08Resolved\x12\x44\n\x08response\x18\x01 \x01(\x0b\x32\x32.confidence.flags.resolver.v1.ResolveFlagsResponse\x12V\n\x19materializations_to_write\x18\x02 \x03(\x0b\x32\x33.confidence.flags.resolver.v1.MaterializationRecord\x1aq\n\tSuspended\x12U\n\x18materializations_to_read\x18\x01 \x03(\x0b\x32\x33.confidence.flags.resolver.v1.MaterializationRecord\x12\r\n\x05state\x18\x02 \x01(\x0c\x42\x08\n\x06result\"]\n\x15MaterializationRecord\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\x17\n\x0fmaterialization\x18\x02 \x01(\t\x12\x0c\n\x04rule\x18\x03 \x01(\t\x12\x0f\n\x07variant\x18\x04 \x01(\t\"\x1d\n\nLogMessage\x12\x0f\n\x07message\x18\x01 \x01(\t\"i\n\x16RegisterResolveRequest\x12;\n\x06reason\x18\x01 \x01(\x0e\x32+.confidence.flags.resolver.v1.ResolveReason\x12\x12\n\nlatency_us\x18\x02 \x01(\rB\x9d\x01\n,com.spotify.confidence.sdk.flags.resolver.v1B\x0cWasmApiProtoP\x01Z]github.com/spotify/confidence-resolver/openfeature-provider/go/confidence/internal/proto/wasmb\x06proto3')

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 JsiM~OI5gTGhaiqAywC&G70CxZa6 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 GWB&(zL7xZ! diff --git a/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go b/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go index 47af3fe39..a70cfba65 100644 --- a/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go +++ b/openfeature-provider/go/confidence/internal/proto/resolverinternal/internal_api.pb.go @@ -246,12 +246,14 @@ type TelemetryData struct { Sdk *resolver.Sdk `protobuf:"bytes,2,opt,name=sdk,proto3" json:"sdk,omitempty"` // Version of the embedded resolver (e.g. "0.14.0"). // This must be preserved when providers decode and re-encode telemetry. - ResolverVersion string `protobuf:"bytes,8,opt,name=resolver_version,json=resolverVersion,proto3" json:"resolver_version,omitempty"` - ProviderInitRate []*TelemetryData_ProviderInitRate `protobuf:"bytes,9,rep,name=provider_init_rate,json=providerInitRate,proto3" json:"provider_init_rate,omitempty"` + ResolverVersion string `protobuf:"bytes,8,opt,name=resolver_version,json=resolverVersion,proto3" json:"resolver_version,omitempty"` + ProviderInitRate []*TelemetryData_ProviderInitRate `protobuf:"bytes,9,rep,name=provider_init_rate,json=providerInitRate,proto3" json:"provider_init_rate,omitempty"` + ApplyDedup *TelemetryData_ApplyDedupTelemetry `protobuf:"bytes,10,opt,name=apply_dedup,json=applyDedup,proto3" json:"apply_dedup,omitempty"` // Delta counters: WriteFlagLogs batch delivery outcomes since last flush. // Populated by the host SDK after each delivery attempt. - FlushSucceeded uint32 `protobuf:"varint,11,opt,name=flush_succeeded,json=flushSucceeded,proto3" json:"flush_succeeded,omitempty"` - FlushFailed uint32 `protobuf:"varint,12,opt,name=flush_failed,json=flushFailed,proto3" json:"flush_failed,omitempty"` + FlushSucceeded uint32 `protobuf:"varint,11,opt,name=flush_succeeded,json=flushSucceeded,proto3" json:"flush_succeeded,omitempty"` + FlushFailed uint32 `protobuf:"varint,12,opt,name=flush_failed,json=flushFailed,proto3" json:"flush_failed,omitempty"` + // Delta counters: event delivery stats since last flush. EventsPublished uint32 `protobuf:"varint,13,opt,name=events_published,json=eventsPublished,proto3" json:"events_published,omitempty"` EventBatchesSucceeded uint32 `protobuf:"varint,14,opt,name=event_batches_succeeded,json=eventBatchesSucceeded,proto3" json:"event_batches_succeeded,omitempty"` EventBatchesFailed uint32 `protobuf:"varint,15,opt,name=event_batches_failed,json=eventBatchesFailed,proto3" json:"event_batches_failed,omitempty"` @@ -310,6 +312,13 @@ func (x *TelemetryData) GetProviderInitRate() []*TelemetryData_ProviderInitRate return nil } +func (x *TelemetryData) GetApplyDedup() *TelemetryData_ApplyDedupTelemetry { + if x != nil { + return x.ApplyDedup + } + return nil +} + func (x *TelemetryData) GetFlushSucceeded() uint32 { if x != nil { return x.FlushSucceeded @@ -1223,6 +1232,90 @@ func (x *ReadOperationsResult) GetResults() []*ReadResult { return nil } +type TelemetryData_ApplyDedupTelemetry struct { + state protoimpl.MessageState `protogen:"open.v1"` + AppliesTotal uint32 `protobuf:"varint,1,opt,name=applies_total,json=appliesTotal,proto3" json:"applies_total,omitempty"` + AppliesDeduped uint32 `protobuf:"varint,2,opt,name=applies_deduped,json=appliesDeduped,proto3" json:"applies_deduped,omitempty"` + AppliesNotCached uint32 `protobuf:"varint,3,opt,name=applies_not_cached,json=appliesNotCached,proto3" json:"applies_not_cached,omitempty"` + Sweeps uint32 `protobuf:"varint,4,opt,name=sweeps,proto3" json:"sweeps,omitempty"` + MapSize uint32 `protobuf:"varint,5,opt,name=map_size,json=mapSize,proto3" json:"map_size,omitempty"` + MapCapacity uint32 `protobuf:"varint,6,opt,name=map_capacity,json=mapCapacity,proto3" json:"map_capacity,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TelemetryData_ApplyDedupTelemetry) Reset() { + *x = TelemetryData_ApplyDedupTelemetry{} + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TelemetryData_ApplyDedupTelemetry) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TelemetryData_ApplyDedupTelemetry) ProtoMessage() {} + +func (x *TelemetryData_ApplyDedupTelemetry) ProtoReflect() protoreflect.Message { + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TelemetryData_ApplyDedupTelemetry.ProtoReflect.Descriptor instead. +func (*TelemetryData_ApplyDedupTelemetry) Descriptor() ([]byte, []int) { + return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 0} +} + +func (x *TelemetryData_ApplyDedupTelemetry) GetAppliesTotal() uint32 { + if x != nil { + return x.AppliesTotal + } + return 0 +} + +func (x *TelemetryData_ApplyDedupTelemetry) GetAppliesDeduped() uint32 { + if x != nil { + return x.AppliesDeduped + } + return 0 +} + +func (x *TelemetryData_ApplyDedupTelemetry) GetAppliesNotCached() uint32 { + if x != nil { + return x.AppliesNotCached + } + return 0 +} + +func (x *TelemetryData_ApplyDedupTelemetry) GetSweeps() uint32 { + if x != nil { + return x.Sweeps + } + return 0 +} + +func (x *TelemetryData_ApplyDedupTelemetry) GetMapSize() uint32 { + if x != nil { + return x.MapSize + } + return 0 +} + +func (x *TelemetryData_ApplyDedupTelemetry) GetMapCapacity() uint32 { + if x != nil { + return x.MapCapacity + } + return 0 +} + type TelemetryData_ProviderInitRate struct { state protoimpl.MessageState `protogen:"open.v1"` Count uint32 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` @@ -1233,7 +1326,7 @@ type TelemetryData_ProviderInitRate struct { func (x *TelemetryData_ProviderInitRate) Reset() { *x = TelemetryData_ProviderInitRate{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[19] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1245,7 +1338,7 @@ func (x *TelemetryData_ProviderInitRate) String() string { func (*TelemetryData_ProviderInitRate) ProtoMessage() {} func (x *TelemetryData_ProviderInitRate) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[19] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1258,7 +1351,7 @@ func (x *TelemetryData_ProviderInitRate) ProtoReflect() protoreflect.Message { // Deprecated: Use TelemetryData_ProviderInitRate.ProtoReflect.Descriptor instead. func (*TelemetryData_ProviderInitRate) Descriptor() ([]byte, []int) { - return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 0} + return file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP(), []int{3, 1} } func (x *TelemetryData_ProviderInitRate) GetCount() uint32 { @@ -1295,7 +1388,7 @@ type FlagAssigned_AppliedFlag struct { func (x *FlagAssigned_AppliedFlag) Reset() { *x = FlagAssigned_AppliedFlag{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[21] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1307,7 +1400,7 @@ func (x *FlagAssigned_AppliedFlag) String() string { func (*FlagAssigned_AppliedFlag) ProtoMessage() {} func (x *FlagAssigned_AppliedFlag) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[21] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1423,7 +1516,7 @@ type FlagAssigned_AssignmentInfo struct { func (x *FlagAssigned_AssignmentInfo) Reset() { *x = FlagAssigned_AssignmentInfo{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[22] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1435,7 +1528,7 @@ func (x *FlagAssigned_AssignmentInfo) String() string { func (*FlagAssigned_AssignmentInfo) ProtoMessage() {} func (x *FlagAssigned_AssignmentInfo) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[22] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1474,7 +1567,7 @@ type FlagAssigned_DefaultAssignment struct { func (x *FlagAssigned_DefaultAssignment) Reset() { *x = FlagAssigned_DefaultAssignment{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[23] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1486,7 +1579,7 @@ func (x *FlagAssigned_DefaultAssignment) String() string { func (*FlagAssigned_DefaultAssignment) ProtoMessage() {} func (x *FlagAssigned_DefaultAssignment) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[23] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1520,7 +1613,7 @@ type ClientResolveInfo_EvaluationContextSchemaInstance struct { func (x *ClientResolveInfo_EvaluationContextSchemaInstance) Reset() { *x = ClientResolveInfo_EvaluationContextSchemaInstance{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[24] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1532,7 +1625,7 @@ func (x *ClientResolveInfo_EvaluationContextSchemaInstance) String() string { func (*ClientResolveInfo_EvaluationContextSchemaInstance) ProtoMessage() {} func (x *ClientResolveInfo_EvaluationContextSchemaInstance) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[24] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1568,7 +1661,7 @@ type FlagResolveInfo_VariantResolveInfo struct { func (x *FlagResolveInfo_VariantResolveInfo) Reset() { *x = FlagResolveInfo_VariantResolveInfo{} - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[26] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1580,7 +1673,7 @@ func (x *FlagResolveInfo_VariantResolveInfo) String() string { func (*FlagResolveInfo_VariantResolveInfo) ProtoMessage() {} func (x *FlagResolveInfo_VariantResolveInfo) ProtoReflect() protoreflect.Message { - mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[26] + mi := &file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1624,13 +1717,26 @@ const file_confidence_flags_resolver_v1_internal_api_proto_rawDesc = "" + "\x15IngestFlagLogsRequest\x12\x1d\n" + "\n" + "account_id\x18\x01 \x01(\tR\taccountId\x12H\n" + - "\x05batch\x18\x02 \x01(\v22.confidence.flags.resolver.v1.WriteFlagLogsRequestR\x05batch\"\xf5\x03\n" + + "\x05batch\x18\x02 \x01(\v22.confidence.flags.resolver.v1.WriteFlagLogsRequestR\x05batch\"\xd6\a\n" + "\rTelemetryData\x123\n" + "\x03sdk\x18\x02 \x01(\v2!.confidence.flags.resolver.v1.SdkR\x03sdk\x12)\n" + "\x10resolver_version\x18\b \x01(\tR\x0fresolverVersion\x12j\n" + - "\x12provider_init_rate\x18\t \x03(\v2<.confidence.flags.resolver.v1.TelemetryData.ProviderInitRateR\x10providerInitRate\x12'\n" + + "\x12provider_init_rate\x18\t \x03(\v2<.confidence.flags.resolver.v1.TelemetryData.ProviderInitRateR\x10providerInitRate\x12`\n" + + "\vapply_dedup\x18\n" + + " \x01(\v2?.confidence.flags.resolver.v1.TelemetryData.ApplyDedupTelemetryR\n" + + "applyDedup\x12'\n" + "\x0fflush_succeeded\x18\v \x01(\rR\x0eflushSucceeded\x12!\n" + - "\fflush_failed\x18\f \x01(\rR\vflushFailed\x1a\xcb\x01\n" + + "\fflush_failed\x18\f \x01(\rR\vflushFailed\x12)\n" + + "\x10events_published\x18\r \x01(\rR\x0feventsPublished\x126\n" + + "\x17event_batches_succeeded\x18\x0e \x01(\rR\x15eventBatchesSucceeded\x120\n" + + "\x14event_batches_failed\x18\x0f \x01(\rR\x12eventBatchesFailed\x1a\xe7\x01\n" + + "\x13ApplyDedupTelemetry\x12#\n" + + "\rapplies_total\x18\x01 \x01(\rR\fappliesTotal\x12'\n" + + "\x0fapplies_deduped\x18\x02 \x01(\rR\x0eappliesDeduped\x12,\n" + + "\x12applies_not_cached\x18\x03 \x01(\rR\x10appliesNotCached\x12\x16\n" + + "\x06sweeps\x18\x04 \x01(\rR\x06sweeps\x12\x19\n" + + "\bmap_size\x18\x05 \x01(\rR\amapSize\x12!\n" + + "\fmap_capacity\x18\x06 \x01(\rR\vmapCapacity\x1a\xcb\x01\n" + "\x10ProviderInitRate\x12\x14\n" + "\x05count\x18\x01 \x01(\rR\x05count\x12`\n" + "\x06labels\x18\x03 \x03(\v2H.confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntryR\x06labels\x1a9\n" + @@ -1744,7 +1850,7 @@ func file_confidence_flags_resolver_v1_internal_api_proto_rawDescGZIP() []byte { } var file_confidence_flags_resolver_v1_internal_api_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_confidence_flags_resolver_v1_internal_api_proto_msgTypes = make([]protoimpl.MessageInfo, 27) +var file_confidence_flags_resolver_v1_internal_api_proto_msgTypes = make([]protoimpl.MessageInfo, 28) var file_confidence_flags_resolver_v1_internal_api_proto_goTypes = []any{ (FlagAssigned_DefaultAssignment_DefaultAssignmentReason)(0), // 0: confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.DefaultAssignmentReason (*WriteFlagLogsRequest)(nil), // 1: confidence.flags.resolver.v1.WriteFlagLogsRequest @@ -1766,16 +1872,17 @@ var file_confidence_flags_resolver_v1_internal_api_proto_goTypes = []any{ (*InclusionData)(nil), // 17: confidence.flags.resolver.v1.InclusionData (*ReadResult)(nil), // 18: confidence.flags.resolver.v1.ReadResult (*ReadOperationsResult)(nil), // 19: confidence.flags.resolver.v1.ReadOperationsResult - (*TelemetryData_ProviderInitRate)(nil), // 20: confidence.flags.resolver.v1.TelemetryData.ProviderInitRate - nil, // 21: confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry - (*FlagAssigned_AppliedFlag)(nil), // 22: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag - (*FlagAssigned_AssignmentInfo)(nil), // 23: confidence.flags.resolver.v1.FlagAssigned.AssignmentInfo - (*FlagAssigned_DefaultAssignment)(nil), // 24: confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment - (*ClientResolveInfo_EvaluationContextSchemaInstance)(nil), // 25: confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance - nil, // 26: confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry - (*FlagResolveInfo_VariantResolveInfo)(nil), // 27: confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo - (*resolver.Sdk)(nil), // 28: confidence.flags.resolver.v1.Sdk - (*timestamppb.Timestamp)(nil), // 29: google.protobuf.Timestamp + (*TelemetryData_ApplyDedupTelemetry)(nil), // 20: confidence.flags.resolver.v1.TelemetryData.ApplyDedupTelemetry + (*TelemetryData_ProviderInitRate)(nil), // 21: confidence.flags.resolver.v1.TelemetryData.ProviderInitRate + nil, // 22: confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry + (*FlagAssigned_AppliedFlag)(nil), // 23: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag + (*FlagAssigned_AssignmentInfo)(nil), // 24: confidence.flags.resolver.v1.FlagAssigned.AssignmentInfo + (*FlagAssigned_DefaultAssignment)(nil), // 25: confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment + (*ClientResolveInfo_EvaluationContextSchemaInstance)(nil), // 26: confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance + nil, // 27: confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry + (*FlagResolveInfo_VariantResolveInfo)(nil), // 28: confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo + (*resolver.Sdk)(nil), // 29: confidence.flags.resolver.v1.Sdk + (*timestamppb.Timestamp)(nil), // 30: google.protobuf.Timestamp } var file_confidence_flags_resolver_v1_internal_api_proto_depIdxs = []int32{ 6, // 0: confidence.flags.resolver.v1.WriteFlagLogsRequest.flag_assigned:type_name -> confidence.flags.resolver.v1.FlagAssigned @@ -1783,38 +1890,39 @@ var file_confidence_flags_resolver_v1_internal_api_proto_depIdxs = []int32{ 8, // 2: confidence.flags.resolver.v1.WriteFlagLogsRequest.client_resolve_info:type_name -> confidence.flags.resolver.v1.ClientResolveInfo 9, // 3: confidence.flags.resolver.v1.WriteFlagLogsRequest.flag_resolve_info:type_name -> confidence.flags.resolver.v1.FlagResolveInfo 1, // 4: confidence.flags.resolver.v1.IngestFlagLogsRequest.batch:type_name -> confidence.flags.resolver.v1.WriteFlagLogsRequest - 28, // 5: confidence.flags.resolver.v1.TelemetryData.sdk:type_name -> confidence.flags.resolver.v1.Sdk - 20, // 6: confidence.flags.resolver.v1.TelemetryData.provider_init_rate:type_name -> confidence.flags.resolver.v1.TelemetryData.ProviderInitRate - 28, // 7: confidence.flags.resolver.v1.ClientInfo.sdk:type_name -> confidence.flags.resolver.v1.Sdk - 5, // 8: confidence.flags.resolver.v1.FlagAssigned.client_info:type_name -> confidence.flags.resolver.v1.ClientInfo - 22, // 9: confidence.flags.resolver.v1.FlagAssigned.flags:type_name -> confidence.flags.resolver.v1.FlagAssigned.AppliedFlag - 25, // 10: confidence.flags.resolver.v1.ClientResolveInfo.schema:type_name -> confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance - 27, // 11: confidence.flags.resolver.v1.FlagResolveInfo.variant_resolve_info:type_name -> confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo - 16, // 12: confidence.flags.resolver.v1.WriteOperationsRequest.store_variant_op:type_name -> confidence.flags.resolver.v1.VariantData - 12, // 13: confidence.flags.resolver.v1.ReadOp.variant_read_op:type_name -> confidence.flags.resolver.v1.VariantReadOp - 13, // 14: confidence.flags.resolver.v1.ReadOp.inclusion_read_op:type_name -> confidence.flags.resolver.v1.InclusionReadOp - 14, // 15: confidence.flags.resolver.v1.ReadOperationsRequest.ops:type_name -> confidence.flags.resolver.v1.ReadOp - 16, // 16: confidence.flags.resolver.v1.ReadResult.variant_result:type_name -> confidence.flags.resolver.v1.VariantData - 17, // 17: confidence.flags.resolver.v1.ReadResult.inclusion_result:type_name -> confidence.flags.resolver.v1.InclusionData - 18, // 18: confidence.flags.resolver.v1.ReadOperationsResult.results:type_name -> confidence.flags.resolver.v1.ReadResult - 21, // 19: confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.labels:type_name -> confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry - 23, // 20: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.assignment_info:type_name -> confidence.flags.resolver.v1.FlagAssigned.AssignmentInfo - 24, // 21: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.default_assignment:type_name -> confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment - 7, // 22: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.fallthrough_assignments:type_name -> confidence.flags.resolver.v1.FallthroughAssignment - 29, // 23: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.apply_time:type_name -> google.protobuf.Timestamp - 0, // 24: confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.reason:type_name -> confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.DefaultAssignmentReason - 26, // 25: confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.schema:type_name -> confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry - 1, // 26: confidence.flags.resolver.v1.InternalFlagLoggerService.ClientWriteFlagLogs:input_type -> confidence.flags.resolver.v1.WriteFlagLogsRequest - 10, // 27: confidence.flags.resolver.v1.InternalFlagLoggerService.WriteMaterializedOperations:input_type -> confidence.flags.resolver.v1.WriteOperationsRequest - 15, // 28: confidence.flags.resolver.v1.InternalFlagLoggerService.ReadMaterializedOperations:input_type -> confidence.flags.resolver.v1.ReadOperationsRequest - 2, // 29: confidence.flags.resolver.v1.InternalFlagLoggerService.ClientWriteFlagLogs:output_type -> confidence.flags.resolver.v1.WriteFlagLogsResponse - 11, // 30: confidence.flags.resolver.v1.InternalFlagLoggerService.WriteMaterializedOperations:output_type -> confidence.flags.resolver.v1.WriteOperationsResult - 19, // 31: confidence.flags.resolver.v1.InternalFlagLoggerService.ReadMaterializedOperations:output_type -> confidence.flags.resolver.v1.ReadOperationsResult - 29, // [29:32] is the sub-list for method output_type - 26, // [26:29] is the sub-list for method input_type - 26, // [26:26] is the sub-list for extension type_name - 26, // [26:26] is the sub-list for extension extendee - 0, // [0:26] is the sub-list for field type_name + 29, // 5: confidence.flags.resolver.v1.TelemetryData.sdk:type_name -> confidence.flags.resolver.v1.Sdk + 21, // 6: confidence.flags.resolver.v1.TelemetryData.provider_init_rate:type_name -> confidence.flags.resolver.v1.TelemetryData.ProviderInitRate + 20, // 7: confidence.flags.resolver.v1.TelemetryData.apply_dedup:type_name -> confidence.flags.resolver.v1.TelemetryData.ApplyDedupTelemetry + 29, // 8: confidence.flags.resolver.v1.ClientInfo.sdk:type_name -> confidence.flags.resolver.v1.Sdk + 5, // 9: confidence.flags.resolver.v1.FlagAssigned.client_info:type_name -> confidence.flags.resolver.v1.ClientInfo + 23, // 10: confidence.flags.resolver.v1.FlagAssigned.flags:type_name -> confidence.flags.resolver.v1.FlagAssigned.AppliedFlag + 26, // 11: confidence.flags.resolver.v1.ClientResolveInfo.schema:type_name -> confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance + 28, // 12: confidence.flags.resolver.v1.FlagResolveInfo.variant_resolve_info:type_name -> confidence.flags.resolver.v1.FlagResolveInfo.VariantResolveInfo + 16, // 13: confidence.flags.resolver.v1.WriteOperationsRequest.store_variant_op:type_name -> confidence.flags.resolver.v1.VariantData + 12, // 14: confidence.flags.resolver.v1.ReadOp.variant_read_op:type_name -> confidence.flags.resolver.v1.VariantReadOp + 13, // 15: confidence.flags.resolver.v1.ReadOp.inclusion_read_op:type_name -> confidence.flags.resolver.v1.InclusionReadOp + 14, // 16: confidence.flags.resolver.v1.ReadOperationsRequest.ops:type_name -> confidence.flags.resolver.v1.ReadOp + 16, // 17: confidence.flags.resolver.v1.ReadResult.variant_result:type_name -> confidence.flags.resolver.v1.VariantData + 17, // 18: confidence.flags.resolver.v1.ReadResult.inclusion_result:type_name -> confidence.flags.resolver.v1.InclusionData + 18, // 19: confidence.flags.resolver.v1.ReadOperationsResult.results:type_name -> confidence.flags.resolver.v1.ReadResult + 22, // 20: confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.labels:type_name -> confidence.flags.resolver.v1.TelemetryData.ProviderInitRate.LabelsEntry + 24, // 21: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.assignment_info:type_name -> confidence.flags.resolver.v1.FlagAssigned.AssignmentInfo + 25, // 22: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.default_assignment:type_name -> confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment + 7, // 23: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.fallthrough_assignments:type_name -> confidence.flags.resolver.v1.FallthroughAssignment + 30, // 24: confidence.flags.resolver.v1.FlagAssigned.AppliedFlag.apply_time:type_name -> google.protobuf.Timestamp + 0, // 25: confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.reason:type_name -> confidence.flags.resolver.v1.FlagAssigned.DefaultAssignment.DefaultAssignmentReason + 27, // 26: confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.schema:type_name -> confidence.flags.resolver.v1.ClientResolveInfo.EvaluationContextSchemaInstance.SchemaEntry + 1, // 27: confidence.flags.resolver.v1.InternalFlagLoggerService.ClientWriteFlagLogs:input_type -> confidence.flags.resolver.v1.WriteFlagLogsRequest + 10, // 28: confidence.flags.resolver.v1.InternalFlagLoggerService.WriteMaterializedOperations:input_type -> confidence.flags.resolver.v1.WriteOperationsRequest + 15, // 29: confidence.flags.resolver.v1.InternalFlagLoggerService.ReadMaterializedOperations:input_type -> confidence.flags.resolver.v1.ReadOperationsRequest + 2, // 30: confidence.flags.resolver.v1.InternalFlagLoggerService.ClientWriteFlagLogs:output_type -> confidence.flags.resolver.v1.WriteFlagLogsResponse + 11, // 31: confidence.flags.resolver.v1.InternalFlagLoggerService.WriteMaterializedOperations:output_type -> confidence.flags.resolver.v1.WriteOperationsResult + 19, // 32: confidence.flags.resolver.v1.InternalFlagLoggerService.ReadMaterializedOperations:output_type -> confidence.flags.resolver.v1.ReadOperationsResult + 30, // [30:33] is the sub-list for method output_type + 27, // [27:30] is the sub-list for method input_type + 27, // [27:27] is the sub-list for extension type_name + 27, // [27:27] is the sub-list for extension extendee + 0, // [0:27] is the sub-list for field type_name } func init() { file_confidence_flags_resolver_v1_internal_api_proto_init() } @@ -1830,7 +1938,7 @@ func file_confidence_flags_resolver_v1_internal_api_proto_init() { (*ReadResult_VariantResult)(nil), (*ReadResult_InclusionResult)(nil), } - file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[21].OneofWrappers = []any{ + file_confidence_flags_resolver_v1_internal_api_proto_msgTypes[22].OneofWrappers = []any{ (*FlagAssigned_AppliedFlag_AssignmentInfo)(nil), (*FlagAssigned_AppliedFlag_DefaultAssignment)(nil), } @@ -1840,7 +1948,7 @@ func file_confidence_flags_resolver_v1_internal_api_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_confidence_flags_resolver_v1_internal_api_proto_rawDesc), len(file_confidence_flags_resolver_v1_internal_api_proto_rawDesc)), NumEnums: 1, - NumMessages: 27, + NumMessages: 28, NumExtensions: 0, NumServices: 1, }, diff --git a/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto b/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto index c5a43c13c..c51d1f3e2 100644 --- a/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto +++ b/openfeature-provider/proto/confidence/flags/resolver/v1/internal_api.proto @@ -57,7 +57,7 @@ message TelemetryData { repeated ProviderInitRate provider_init_rate = 9; - // apply_dedup = 10; — set by WASM guest, passes through as unknown fields + ApplyDedupTelemetry apply_dedup = 10; // Delta counters: WriteFlagLogs batch delivery outcomes since last flush. // Populated by the host SDK after each delivery attempt. @@ -69,6 +69,15 @@ message TelemetryData { uint32 event_batches_succeeded = 14; uint32 event_batches_failed = 15; + message ApplyDedupTelemetry { + uint32 applies_total = 1; + uint32 applies_deduped = 2; + uint32 applies_not_cached = 3; + uint32 sweeps = 4; + uint32 map_size = 5; + uint32 map_capacity = 6; + } + message ProviderInitRate { uint32 count = 1; reserved 2; // status — tbd From 7ae8ccf614bf5ac94252b4f1f4554955b2c0150c Mon Sep 17 00:00:00 2001 From: vahidlazio Date: Wed, 2 Sep 2026 14:42:45 +0200 Subject: [PATCH 07/25] =?UTF-8?q?fix(ci):=20revert=20locally-built=20WASM?= =?UTF-8?q?=20=E2=80=94=20CI=20builds=20in=20Docker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- .../assets/confidence_resolver.wasm | Bin 510659 -> 500838 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/openfeature-provider/go/confidence/internal/local_resolver/assets/confidence_resolver.wasm b/openfeature-provider/go/confidence/internal/local_resolver/assets/confidence_resolver.wasm index 19a75352aae0d50876a95d0393f6a8a0c24cea18..4b70bf1928ee1e9119b593593c0c5e851c256070 100755 GIT binary patch delta 109105 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
SCTO_!~__ z-JAYK^)LU6y6x~7n{ptJW>AnLsq%}pXJq;vG!%pO$Q^V$&6HJlP*+eu{+)CeJtL>z zNp(reHFsh}qzv3eHzMayEQgGMGJRf79|38&O0FM4^|K?AO4!q7C!0ku+}LyT#xr-* zkcg*#GxtLI+U5OsQ?n8k5y@^i;&o_Pwbc$sJi9O@zy${xRJ%5vfECKb_Nn?eleP1l z7k9(U0jna7utyO+jIJumOG>&IbisAW()&b8n~2wvef%n&%QK2lL8b+Z9_{>OSgi7U zP(D3U-i7oi7@N!DyWDl;)_bTYCfErh=_V?d_l!iBzm`)*(zW!8yg9>@N}tKIBdKnj z6=s8}GAhvy$|m$*SlxbX%@o-s;hJATk!3g4+@Ir&~1m~w=Hwze8Tu5s7V!^85o zd!cU*%bEAlN;+K8^?vXGeJ5Xkfc{43WY#E}O=o4rC~7ax9GAb0q7Z#A)Bldy&JXhC zztf^fOgf*IF;3q6Ajtd!x&1+^q$lL#|DZ46{k-!bWPhsSw}&vN0oA5IO!WfC85j_n z%Wv$NCVM_iUFd|I{xBv>C*>~>Q?HD02DNn=Qx7M$w!l>IYp3MkM`$DcDC<0m$aa5&21Wf0XX3YlV+MX@fm8`A4_biY-=2gRk*^?X>*(QR+)S%lv=Q<@AfZ z>0k7yb!j2v9|Pl_mIEH6rt+~8*fjDnSczxk_Q$BBocI_e$g~o;0e+VqORy^Pvn(m0 zR^s$%`K24{f4fWQU*P(lr4+>U;GRtk^pidZo#cX*|1h+0jTD z7Uqnasqok_K9MS~98b*!uKyfQ4ZKIWtoE&3G9KpcDH%I~`T+$uPoSs0=hUkm@}~*Z zi1X_cDMvheNE#C9O!iqMYW0DECJuU`Qr6+?`es$q_Y0 zRuT+9F8IIJPNn*EKvrS5Oxn*D!82;n6YY2V(Iux%qm=q=+OgD%{JY7>1UGiT6Y=cGR?rDrCc0O|cQlg`9^$EHt6(~ihrpP>mzeN0kr<~qg|FPlPN z!Gk)Se|7%J)7Hz4l3q-)%Ec@SCEOQ^9nKMuaQ7UM56z+{QHg6d7FK_d|C~)@ASchw zrdR0``N|v^(G~MxRgS5sng??-q^2XFKKS?kU@{Fdg+l!0fiTfN`R|bZydp_>{Zom~`wZBrvE~2!O(%r}mtJ&4ksmd8}z_)a& zI(5Rd#%ed-@9-C)38U;OMDyjtvwj8(Cs^X_go}=JtnBb>`0_3h%~Z*;O+NoAL7u2l zA+B0>TtIQ*jTy540`SF$QsPpAMP81z06(P#-F!(3Iz^FD>SxJowSsgL?9E$ z!kn>aAr#8OwQ}e}tVaD-=DZQs&vo;i4{19Y*IffH_ETUrW|#bYzBB)(ZfDtF1DFE~S~DiLl# z5F7TZqDNK(a?T6RW`XSt6vouqg7bg!g0odH(gatsmEYr_rI1&r9sz{+Ayh{;Ti|Rj z4o#BxEpT3YmvY8Kc>Qnw`2WRs9|pK!p);#Q0b~KJ5UTTu8KOvMy~kb~%W>-P-wd
0W0GNNA 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