cat_gateway/metrics/
memory.rs

1//! Metrics related to memory analytics.
2
3use std::alloc::System;
4
5use memory_stats::{memory_stats, MemoryStats};
6use stats_alloc::{Region, StatsAlloc, INSTRUMENTED_SYSTEM};
7
8use crate::settings::Settings;
9
10/// Use the instrumented allocator for gathering allocation statistics.
11/// Note: This wraps the global allocator.
12/// All structs that use the global allocator can be tracked.
13#[global_allocator]
14static GLOBAL: &StatsAlloc<System> = &INSTRUMENTED_SYSTEM;
15
16/// Updates memory metrics to current values.
17pub(crate) fn update() {
18    let stats = Region::new(GLOBAL);
19    let api_host_names = Settings::api_host_names().join(",");
20    let service_id = Settings::service_id();
21
22    let allocator_stats = stats.change();
23    let mem_stats = memory_stats().unwrap_or({
24        MemoryStats {
25            physical_mem: 0,
26            virtual_mem: 0,
27        }
28    });
29
30    reporter::MEMORY_PHYSICAL_USAGE
31        .with_label_values(&[&api_host_names, service_id])
32        .set(i64::try_from(mem_stats.physical_mem).unwrap_or(-1));
33    reporter::MEMORY_VIRTUAL_USAGE
34        .with_label_values(&[&api_host_names, service_id])
35        .set(i64::try_from(mem_stats.virtual_mem).unwrap_or(-1));
36    reporter::MEMORY_ALLOCATION_COUNT
37        .with_label_values(&[&api_host_names, service_id])
38        .set(i64::try_from(allocator_stats.allocations).unwrap_or(-1));
39    reporter::MEMORY_DEALLOCATION_COUNT
40        .with_label_values(&[&api_host_names, service_id])
41        .set(i64::try_from(allocator_stats.deallocations).unwrap_or(-1));
42    reporter::MEMORY_REALLOCATION_COUNT
43        .with_label_values(&[&api_host_names, service_id])
44        .set(i64::try_from(allocator_stats.reallocations).unwrap_or(-1));
45    reporter::MEMORY_BYTES_ALLOCATED
46        .with_label_values(&[&api_host_names, service_id])
47        .set(i64::try_from(allocator_stats.bytes_allocated).unwrap_or(-1));
48    reporter::MEMORY_BYTES_DEALLOCATED
49        .with_label_values(&[&api_host_names, service_id])
50        .set(i64::try_from(allocator_stats.bytes_deallocated).unwrap_or(-1));
51    reporter::MEMORY_BYTES_REALLOCATED
52        .with_label_values(&[&api_host_names, service_id])
53        .set(i64::try_from(allocator_stats.bytes_reallocated).unwrap_or(-1));
54}
55
56/// All the related memory reporting metrics to the Prometheus service are inside this
57/// module.
58mod reporter {
59    #![allow(clippy::unwrap_used)]
60
61    use std::sync::LazyLock;
62
63    use prometheus::{register_int_gauge_vec, IntGaugeVec};
64
65    /// Labels for the memory metrics
66    const MEMORY_METRIC_LABELS: [&str; 2] = ["api_host_names", "service_id"];
67
68    /// The "physical" memory used by this process, in bytes.
69    pub(super) static MEMORY_PHYSICAL_USAGE: LazyLock<IntGaugeVec> = LazyLock::new(|| {
70        register_int_gauge_vec!(
71            "memory_physical_usage",
72            "Amount of physical memory usage in bytes",
73            &MEMORY_METRIC_LABELS
74        )
75        .unwrap()
76    });
77
78    /// The "virtual" memory used by this process, in bytes.
79    pub(super) static MEMORY_VIRTUAL_USAGE: LazyLock<IntGaugeVec> = LazyLock::new(|| {
80        register_int_gauge_vec!(
81            "memory_virtual_usage",
82            "Amount of physical virtual usage in bytes",
83            &MEMORY_METRIC_LABELS
84        )
85        .unwrap()
86    });
87
88    /// The number of allocation count in the heap.
89    pub(super) static MEMORY_ALLOCATION_COUNT: LazyLock<IntGaugeVec> = LazyLock::new(|| {
90        register_int_gauge_vec!(
91            "memory_allocation_count",
92            "Number of allocation count in the heap",
93            &MEMORY_METRIC_LABELS
94        )
95        .unwrap()
96    });
97
98    /// The number of deallocation count in the heap.
99    pub(super) static MEMORY_DEALLOCATION_COUNT: LazyLock<IntGaugeVec> = LazyLock::new(|| {
100        register_int_gauge_vec!(
101            "memory_deallocation_count",
102            "Number of deallocation count in the heap",
103            &MEMORY_METRIC_LABELS
104        )
105        .unwrap()
106    });
107
108    /// The number of reallocation count in the heap.
109    pub(super) static MEMORY_REALLOCATION_COUNT: LazyLock<IntGaugeVec> = LazyLock::new(|| {
110        register_int_gauge_vec!(
111            "memory_reallocation_count",
112            "Number of reallocation count in the heap",
113            &MEMORY_METRIC_LABELS
114        )
115        .unwrap()
116    });
117
118    /// The amount of accumulative allocated bytes in the heap.
119    pub(super) static MEMORY_BYTES_ALLOCATED: LazyLock<IntGaugeVec> = LazyLock::new(|| {
120        register_int_gauge_vec!(
121            "memory_bytes_allocated",
122            "Amount of accumulative allocated bytes in the heap",
123            &MEMORY_METRIC_LABELS
124        )
125        .unwrap()
126    });
127
128    /// The amount of accumulative deallocated bytes in the heap.
129    pub(super) static MEMORY_BYTES_DEALLOCATED: LazyLock<IntGaugeVec> = LazyLock::new(|| {
130        register_int_gauge_vec!(
131            "memory_bytes_deallocated",
132            "Amount of accumulative deallocated bytes in the heap",
133            &MEMORY_METRIC_LABELS
134        )
135        .unwrap()
136    });
137
138    /// The amount of accumulative reallocated bytes in the heap.
139    pub(super) static MEMORY_BYTES_REALLOCATED: LazyLock<IntGaugeVec> = LazyLock::new(|| {
140        register_int_gauge_vec!(
141            "memory_bytes_reallocated",
142            "Amount of accumulative reallocated bytes in the heap",
143            &MEMORY_METRIC_LABELS
144        )
145        .unwrap()
146    });
147}