kmp_observability/
quality_telemetry_observation.rs1use std::time::{SystemTime, UNIX_EPOCH};
2
3use kmp_domain::{BundleQualityMetrics, QualityObservationContext};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8pub struct QualityTelemetryObservation {
9 observed_at_millis: u64,
10 rpc: String,
11 root_node_id: String,
12 role: String,
13 #[serde(default)]
14 revision: Option<u64>,
15 raw_equivalent_tokens: u32,
16 compression_ratio: f64,
17 causal_density: f64,
18 noise_ratio: f64,
19 detail_coverage: f64,
20}
21
22impl QualityTelemetryObservation {
23 pub fn capture(metrics: &BundleQualityMetrics, context: &QualityObservationContext) -> Self {
24 Self {
25 observed_at_millis: SystemTime::now()
26 .duration_since(UNIX_EPOCH)
27 .map(|elapsed| u64::try_from(elapsed.as_millis()).unwrap_or(u64::MAX))
28 .unwrap_or(0),
29 rpc: context.rpc.clone(),
30 root_node_id: context.root_node_id.clone(),
31 role: context.role.clone(),
32 revision: context.revision,
33 raw_equivalent_tokens: metrics.raw_equivalent_tokens(),
34 compression_ratio: metrics.compression_ratio(),
35 causal_density: metrics.causal_density(),
36 noise_ratio: metrics.noise_ratio(),
37 detail_coverage: metrics.detail_coverage(),
38 }
39 }
40
41 pub fn observed_at_millis(&self) -> u64 {
42 self.observed_at_millis
43 }
44
45 pub fn rpc(&self) -> &str {
46 &self.rpc
47 }
48
49 pub fn root_node_id(&self) -> &str {
50 &self.root_node_id
51 }
52
53 pub fn role(&self) -> &str {
54 &self.role
55 }
56
57 pub fn revision(&self) -> Option<u64> {
58 self.revision
59 }
60
61 pub fn raw_equivalent_tokens(&self) -> u32 {
62 self.raw_equivalent_tokens
63 }
64
65 pub fn compression_ratio(&self) -> f64 {
66 self.compression_ratio
67 }
68
69 pub fn causal_density(&self) -> f64 {
70 self.causal_density
71 }
72
73 pub fn noise_ratio(&self) -> f64 {
74 self.noise_ratio
75 }
76
77 pub fn detail_coverage(&self) -> f64 {
78 self.detail_coverage
79 }
80}