servers/metrics/
jemalloc.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use common_telemetry::error;
16use lazy_static::lazy_static;
17use once_cell::sync::Lazy;
18use prometheus::*;
19use snafu::ResultExt;
20use tikv_jemalloc_ctl::stats::{allocated_mib, resident_mib};
21use tikv_jemalloc_ctl::{epoch, epoch_mib, stats};
22
23use crate::error::UpdateJemallocMetricsSnafu;
24
25lazy_static! {
26    pub static ref SYS_JEMALLOC_RESIDEN: IntGauge = register_int_gauge!(
27        "sys_jemalloc_resident",
28        "Total number of bytes allocated by the application."
29    )
30    .unwrap();
31    pub static ref SYS_JEMALLOC_ALLOCATED: IntGauge = register_int_gauge!(
32        "sys_jemalloc_allocated",
33        "Total number of bytes in physically resident data pages mapped by the allocator."
34    )
35    .unwrap();
36}
37
38pub(crate) static JEMALLOC_COLLECTOR: Lazy<Option<JemallocCollector>> = Lazy::new(|| {
39    let collector = JemallocCollector::try_new()
40        .map_err(|e| {
41            error!(e; "Failed to retrieve jemalloc metrics");
42            e
43        })
44        .ok();
45    collector.inspect(|c| {
46        if let Err(e) = c.update() {
47            error!(e; "Failed to update jemalloc metrics");
48        };
49    })
50});
51
52pub(crate) struct JemallocCollector {
53    epoch: epoch_mib,
54    allocated: allocated_mib,
55    resident: resident_mib,
56}
57
58impl JemallocCollector {
59    pub(crate) fn try_new() -> crate::error::Result<Self> {
60        let e = epoch::mib().context(UpdateJemallocMetricsSnafu)?;
61        let allocated = stats::allocated::mib().context(UpdateJemallocMetricsSnafu)?;
62        let resident = stats::resident::mib().context(UpdateJemallocMetricsSnafu)?;
63        Ok(Self {
64            epoch: e,
65            allocated,
66            resident,
67        })
68    }
69
70    pub(crate) fn update(&self) -> crate::error::Result<()> {
71        let _ = self.epoch.advance().context(UpdateJemallocMetricsSnafu)?;
72        let allocated = self.allocated.read().context(UpdateJemallocMetricsSnafu)?;
73        let resident = self.resident.read().context(UpdateJemallocMetricsSnafu)?;
74        SYS_JEMALLOC_RESIDEN.set(allocated as i64);
75        SYS_JEMALLOC_ALLOCATED.set(resident as i64);
76        Ok(())
77    }
78}