diff --git a/oximeter/db/src/lib.rs b/oximeter/db/src/lib.rs index d57fcdc525..4fa241af74 100644 --- a/oximeter/db/src/lib.rs +++ b/oximeter/db/src/lib.rs @@ -328,17 +328,20 @@ pub struct TimeseriesPageSelector { pub(crate) type TimeseriesKey = u64; pub(crate) fn timeseries_key(sample: &Sample) -> TimeseriesKey { - timeseries_key_for(sample.target_fields(), sample.metric_fields()) + timeseries_key_for( + sample.sorted_target_fields(), + sample.sorted_metric_fields(), + ) } -pub(crate) fn timeseries_key_for<'a>( - target_fields: impl Iterator, - metric_fields: impl Iterator, +fn timeseries_key_for<'a>( + target_fields: &BTreeMap, + metric_fields: &BTreeMap, ) -> TimeseriesKey { use highway::HighwayHasher; use std::hash::{Hash, Hasher}; let mut hasher = HighwayHasher::default(); - for field in target_fields.chain(metric_fields) { + for field in target_fields.values().chain(metric_fields.values()) { bcs::to_bytes(&field) .expect("Failed to serialized field to bytes") .hash(&mut hasher); @@ -460,10 +463,12 @@ mod tests { let mut output = vec![]; for (name, value) in values { - let key = timeseries_key_for( - [&Field { name: name.to_string(), value }].into_iter(), - [].into_iter(), - ); + let target_fields = BTreeMap::from([( + "field".to_string(), + Field { name: name.to_string(), value }, + )]); + let metric_fields = BTreeMap::new(); + let key = timeseries_key_for(&target_fields, &metric_fields); output.push(format!("{name} -> {key}")); } diff --git a/oximeter/oximeter/src/types.rs b/oximeter/oximeter/src/types.rs index 1c8af6f83e..d3f1b9e746 100644 --- a/oximeter/oximeter/src/types.rs +++ b/oximeter/oximeter/src/types.rs @@ -769,6 +769,11 @@ impl Sample { self.target.fields.values() } + /// Return the sorted fields of this sample's target. + pub fn sorted_target_fields(&self) -> &BTreeMap { + &self.target.fields + } + /// Return the name of this sample's metric. pub fn metric_name(&self) -> &str { &self.metric.name @@ -779,6 +784,11 @@ impl Sample { self.metric.fields.values() } + /// Return the sorted fields of this sample's metric + pub fn sorted_metric_fields(&self) -> &BTreeMap { + &self.metric.fields + } + // Check validity of field names for the target and metric. Currently this // just verifies there are no duplicate names between them. fn verify_field_names(