solana_metrics/
lib.rs

1#![cfg_attr(
2    not(feature = "agave-unstable-api"),
3    deprecated(
4        since = "3.1.0",
5        note = "This crate has been marked for formal inclusion in the Agave Unstable API. From \
6                v4.0.0 onward, the `agave-unstable-api` crate feature must be specified to \
7                acknowledge use of an interface that may break without warning."
8    )
9)]
10#![allow(clippy::arithmetic_side_effects)]
11pub mod counter;
12pub mod datapoint;
13pub mod metrics;
14pub use crate::metrics::{flush, query, set_host_id, set_panic_hook, submit};
15use std::sync::{
16    atomic::{AtomicU64, Ordering},
17    Arc,
18};
19
20// To track an external counter which cannot be reset and is always increasing
21#[derive(Default)]
22pub struct MovingStat {
23    value: AtomicU64,
24}
25
26impl MovingStat {
27    pub fn update_stat(&self, old_value: &MovingStat, new_value: u64) {
28        let old = old_value.value.swap(new_value, Ordering::Acquire);
29        self.value
30            .fetch_add(new_value.saturating_sub(old), Ordering::Release);
31    }
32
33    pub fn load_and_reset(&self) -> u64 {
34        self.value.swap(0, Ordering::Acquire)
35    }
36}
37
38/// A helper that sends the count of created tokens as a datapoint.
39#[allow(clippy::redundant_allocation)]
40pub struct TokenCounter(Arc<&'static str>);
41
42impl TokenCounter {
43    /// Creates a new counter with the specified metrics `name`.
44    pub fn new(name: &'static str) -> Self {
45        Self(Arc::new(name))
46    }
47
48    /// Creates a new token for this counter. The metric's value will be equal
49    /// to the number of `CounterToken`s.
50    pub fn create_token(&self) -> CounterToken {
51        // new_count = strong_count
52        //    - 1 (in TokenCounter)
53        //    + 1 (token that's being created)
54        datapoint_info!(*self.0, ("count", Arc::strong_count(&self.0), i64));
55        CounterToken(self.0.clone())
56    }
57}
58
59/// A token for `TokenCounter`.
60#[allow(clippy::redundant_allocation)]
61pub struct CounterToken(Arc<&'static str>);
62
63impl Clone for CounterToken {
64    fn clone(&self) -> Self {
65        // new_count = strong_count
66        //    - 1 (in TokenCounter)
67        //    + 1 (token that's being created)
68        datapoint_info!(*self.0, ("count", Arc::strong_count(&self.0), i64));
69        CounterToken(self.0.clone())
70    }
71}
72
73impl Drop for CounterToken {
74    fn drop(&mut self) {
75        // new_count = strong_count
76        //    - 1 (in TokenCounter, if it still exists)
77        //    - 1 (token that's being dropped)
78        datapoint_info!(
79            *self.0,
80            ("count", Arc::strong_count(&self.0).saturating_sub(2), i64)
81        );
82    }
83}
84
85impl Drop for TokenCounter {
86    fn drop(&mut self) {
87        datapoint_info!(
88            *self.0,
89            ("count", Arc::strong_count(&self.0).saturating_sub(2), i64)
90        );
91    }
92}