1use super::{CounterMap, GaugeMap, HistogramWithSum, Key, Registry, StatMap};
2use indexmap::IndexMap;
3use std::sync::atomic::Ordering;
4use std::sync::{Arc, Mutex};
5
6type ReportCounterMap = IndexMap<Key, usize>;
7type ReportGaugeMap = IndexMap<Key, usize>;
8type ReportStatMap = IndexMap<Key, HistogramWithSum>;
9
10pub fn new(registry: Arc<Mutex<Registry>>) -> Reporter {
11 Reporter(registry)
12}
13
14#[derive(Clone)]
15pub struct Reporter(Arc<Mutex<Registry>>);
16
17impl Reporter {
18 pub fn peek(&self) -> Report {
20 let registry = self.0.lock().unwrap();
21 Report {
22 counters: snap_counters(®istry.counters),
23 gauges: snap_gauges(®istry.gauges),
24 stats: snap_stats(®istry.stats, false),
25 }
26 }
27
28 pub fn take(&mut self) -> Report {
30 let mut registry = self.0.lock().unwrap();
31
32 let report = Report {
33 counters: snap_counters(®istry.counters),
34 gauges: snap_gauges(®istry.gauges),
35 stats: snap_stats(®istry.stats, true),
36 };
37
38 registry.counters.retain(|_, v| Arc::weak_count(v) > 0);
40 registry.gauges.retain(|_, v| Arc::weak_count(v) > 0);
41 registry.stats.retain(|_, v| Arc::weak_count(v) > 0);
42
43 report
44 }
45}
46
47fn snap_counters(counters: &CounterMap) -> ReportCounterMap {
48 let mut snap = ReportCounterMap::with_capacity(counters.len());
49 for (k, v) in &*counters {
50 let v = v.load(Ordering::Acquire);
51 snap.insert(k.clone(), v);
52 }
53 snap
54}
55
56fn snap_gauges(gauges: &GaugeMap) -> ReportGaugeMap {
57 let mut snap = ReportGaugeMap::with_capacity(gauges.len());
58 for (k, v) in &*gauges {
59 let v = v.load(Ordering::Acquire);
60 snap.insert(k.clone(), v);
61 }
62 snap
63}
64
65fn snap_stats(stats: &StatMap, clear: bool) -> ReportStatMap {
66 let mut snap = ReportStatMap::with_capacity(stats.len());
67 for (k, ptr) in &*stats {
68 let mut orig = ptr.lock().unwrap();
69 snap.insert(k.clone(), orig.clone());
70 if clear {
71 orig.clear();
72 }
73 }
74 snap
75}
76
77pub struct Report {
78 counters: ReportCounterMap,
79 gauges: ReportGaugeMap,
80 stats: ReportStatMap,
81}
82impl Report {
83 pub fn counters(&self) -> &ReportCounterMap {
84 &self.counters
85 }
86 pub fn gauges(&self) -> &ReportGaugeMap {
87 &self.gauges
88 }
89 pub fn stats(&self) -> &ReportStatMap {
90 &self.stats
91 }
92 pub fn is_empty(&self) -> bool {
93 self.counters.is_empty() && self.gauges.is_empty() && self.stats.is_empty()
94 }
95 pub fn len(&self) -> usize {
96 self.counters.len() + self.gauges.len() + self.stats.len()
97 }
98}