Skip to main content

wowlab_analytics/analytics/merge/
histogram.rs

1use 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}