-
Notifications
You must be signed in to change notification settings - Fork 176
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(metrics): separate metrics recorder impl from the server (#2561
- Loading branch information
Showing
10 changed files
with
325 additions
and
256 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
pub mod prometheus; | ||
|
||
/// Trait for metrics recorder whose metrics can be exported. | ||
pub trait Exporter: Clone + Send + Sync { | ||
/// Export the metrics that have been recorded by the metrics thus far. | ||
fn export(&self) -> String; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
//! Prometheus exporter | ||
|
||
use std::sync::OnceLock; | ||
|
||
use metrics_exporter_prometheus::PrometheusBuilder; | ||
pub use metrics_exporter_prometheus::PrometheusHandle as Prometheus; | ||
use metrics_util::layers::{PrefixLayer, Stack}; | ||
use tracing::info; | ||
|
||
use crate::exporters::Exporter; | ||
use crate::Error; | ||
|
||
static PROMETHEUS_HANDLE: OnceLock<Prometheus> = OnceLock::new(); | ||
|
||
/// Prometheus exporter recorder. | ||
#[derive(Debug)] | ||
pub struct PrometheusRecorder; | ||
|
||
impl PrometheusRecorder { | ||
/// Installs Prometheus as the metrics recorder. | ||
/// | ||
/// ## Arguments | ||
/// | ||
/// * `prefix` - Apply a prefix to all metrics keys. | ||
pub fn install(prefix: &str) -> Result<Prometheus, Error> { | ||
let recorder = PrometheusBuilder::new().build_recorder(); | ||
let handle = recorder.handle(); | ||
|
||
// Build metrics stack and install the recorder | ||
Stack::new(recorder) | ||
.push(PrefixLayer::new(prefix)) | ||
.install() | ||
.map_err(|_| Error::GlobalRecorderAlreadyInstalled)?; | ||
|
||
info!(target: "metrics", %prefix, "Prometheus recorder installed."); | ||
|
||
let _ = PROMETHEUS_HANDLE.set(handle.clone()); | ||
|
||
Ok(handle) | ||
} | ||
|
||
/// Get the handle to the installed Prometheus recorder (if any). | ||
pub fn current() -> Option<Prometheus> { | ||
PROMETHEUS_HANDLE.get().cloned() | ||
} | ||
} | ||
|
||
impl Exporter for Prometheus { | ||
fn export(&self) -> String { | ||
self.render() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
use metrics::{describe_gauge, gauge}; | ||
|
||
const LOG_TARGET: &str = "metrics"; | ||
|
||
#[cfg(all(feature = "jemalloc", unix))] | ||
pub fn collect_memory_stats() { | ||
use jemalloc_ctl::{epoch, stats}; | ||
|
||
if epoch::advance() | ||
.map_err(|error| { | ||
tracing::error!( | ||
target: LOG_TARGET, | ||
error = %error, | ||
"Advance jemalloc epoch." | ||
) | ||
}) | ||
.is_err() | ||
{ | ||
return; | ||
} | ||
|
||
if let Ok(value) = stats::active::read().map_err(|error| { | ||
tracing::error!( | ||
target: LOG_TARGET, | ||
error = %error, | ||
"Read jemalloc.stats.active." | ||
) | ||
}) { | ||
gauge!("jemalloc.active").increment(value as f64); | ||
} | ||
|
||
if let Ok(value) = stats::allocated::read().map_err(|error| { | ||
tracing::error!( | ||
target: LOG_TARGET, | ||
error = %error, | ||
"Read jemalloc.stats.allocated." | ||
) | ||
}) { | ||
gauge!("jemalloc.allocated").increment(value as f64); | ||
} | ||
|
||
if let Ok(value) = stats::mapped::read().map_err(|error| { | ||
tracing::error!( | ||
target: LOG_TARGET, | ||
error = %error, | ||
"Read jemalloc.stats.mapped." | ||
) | ||
}) { | ||
gauge!("jemalloc.mapped").increment(value as f64); | ||
} | ||
|
||
if let Ok(value) = stats::metadata::read().map_err(|error| { | ||
tracing::error!( | ||
target: LOG_TARGET, | ||
error = %error, | ||
"Read jemalloc.stats.metadata." | ||
) | ||
}) { | ||
gauge!("jemalloc.metadata").increment(value as f64); | ||
} | ||
|
||
if let Ok(value) = stats::resident::read().map_err(|error| { | ||
tracing::error!( | ||
target: LOG_TARGET, | ||
error = %error, | ||
"Read jemalloc.stats.resident." | ||
) | ||
}) { | ||
gauge!("jemalloc.resident").increment(value as f64); | ||
} | ||
|
||
if let Ok(value) = stats::retained::read().map_err(|error| { | ||
tracing::error!( | ||
target: LOG_TARGET, | ||
error = %error, | ||
"Read jemalloc.stats.retained." | ||
) | ||
}) { | ||
gauge!("jemalloc.retained").increment(value as f64); | ||
} | ||
} | ||
|
||
#[cfg(all(feature = "jemalloc", unix))] | ||
pub fn describe_memory_stats() { | ||
describe_gauge!( | ||
"jemalloc.active", | ||
metrics::Unit::Bytes, | ||
"Total number of bytes in active pages allocated by the application" | ||
); | ||
describe_gauge!( | ||
"jemalloc.allocated", | ||
metrics::Unit::Bytes, | ||
"Total number of bytes allocated by the application" | ||
); | ||
describe_gauge!( | ||
"jemalloc.mapped", | ||
metrics::Unit::Bytes, | ||
"Total number of bytes in active extents mapped by the allocator" | ||
); | ||
describe_gauge!( | ||
"jemalloc.metadata", | ||
metrics::Unit::Bytes, | ||
"Total number of bytes dedicated to jemalloc metadata" | ||
); | ||
describe_gauge!( | ||
"jemalloc.resident", | ||
metrics::Unit::Bytes, | ||
"Total number of bytes in physically resident data pages mapped by the allocator" | ||
); | ||
describe_gauge!( | ||
"jemalloc.retained", | ||
metrics::Unit::Bytes, | ||
"Total number of bytes in virtual memory mappings that were retained rather than being \ | ||
returned to the operating system via e.g. munmap(2)" | ||
); | ||
} | ||
|
||
#[cfg(not(all(feature = "jemalloc", unix)))] | ||
pub fn collect_memory_stats() {} | ||
|
||
#[cfg(not(all(feature = "jemalloc", unix)))] | ||
pub fn describe_memory_stats() {} |
Oops, something went wrong.