wowlab_analytics/analytics/merge/
histogram.rs1use hdrhistogram::{
2 Histogram,
3 serialization::{Deserializer, Serializer, V2Serializer},
4};
5use wowlab_types::proto;
6
7pub(super) fn merge_histogram(
8 state: &mut proto::RunningAggregateStateV1,
9 chunk: &proto::ChunkTelemetry,
10) {
11 let Some(chunk_hist) = &chunk.histogram else {
12 return;
13 };
14 let Some(chunk_hdr) = decode_hdr_v2(chunk_hist) else {
15 return;
16 };
17
18 if state.histogram.is_none() {
19 state.histogram = Some(proto::HistogramData {
20 hdr_v2: serialize_hdr_v2(&chunk_hdr).unwrap_or_default(),
21 });
22
23 return;
24 }
25
26 let Some(state_hist) = state.histogram.as_mut() else {
27 return;
28 };
29 let Some(mut state_hdr) = decode_hdr_v2(state_hist) else {
30 return;
31 };
32
33 if state_hdr.add(&chunk_hdr).is_err() {
34 return;
35 }
36
37 state_hist.hdr_v2 = serialize_hdr_v2(&state_hdr).unwrap_or_default();
38}
39
40pub(super) fn decode_hdr_v2(hist: &proto::HistogramData) -> Option<Histogram<u64>> {
41 if !hist.hdr_v2.is_empty() {
42 let mut d = Deserializer::new();
43 let mut bytes = hist.hdr_v2.as_slice();
44 let decoded: Result<Histogram<u64>, _> = d.deserialize(&mut bytes);
45
46 if let Ok(hdr) = decoded {
47 return Some(hdr);
48 }
49 }
50
51 None
52}
53
54pub(super) fn serialize_hdr_v2(hdr: &Histogram<u64>) -> Option<Vec<u8>> {
55 let mut out = Vec::new();
56 let mut s = V2Serializer::new();
57
58 s.serialize(hdr, &mut out).ok()?;
59
60 Some(out)
61}
62
63#[inline]
64pub(super) fn sat_add_u128(a: u64, b: u64) -> u64 {
65 let sum = u128::from(a) + u128::from(b);
66
67 u64::try_from(sum).unwrap_or(u64::MAX)
68}