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