Skip to content

Commit

Permalink
feat(telemetry): register metrics via callback (#1062)
Browse files Browse the repository at this point in the history
## Summary
Register metrics for a service through a callback on the telemetry
builder.

## Background
`astria_telemetry::Config` should be the central entry point to
configure telemetry and metrics. Before this patch the metrics provider,
buckets, and global labels were set through config, but actual metrics
specific outside of it. With this patch this is done in one step.

## Changes
- add `Config::register_metrics` on telemetry builder
- change all services to pass their initialization function to it. 

## Testing
Must be observed in a dev cluster.
  • Loading branch information
SuperFluffy authored May 14, 2024
1 parent 19a70cf commit 6ceb3f9
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 8 deletions.
5 changes: 2 additions & 3 deletions crates/astria-composer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,10 @@ async fn main() -> ExitCode {
if !cfg.no_metrics {
telemetry_conf = telemetry_conf
.metrics_addr(&cfg.metrics_http_listener_addr)
.service_name(env!("CARGO_PKG_NAME"));
.service_name(env!("CARGO_PKG_NAME"))
.register_metrics(metrics_init::register);
}

metrics_init::register();

if let Err(e) = telemetry_conf
.try_init()
.wrap_err("failed to setup telemetry")
Expand Down
3 changes: 2 additions & 1 deletion crates/astria-conductor/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ async fn main() -> ExitCode {
if !cfg.no_metrics {
telemetry_conf = telemetry_conf
.metrics_addr(&cfg.metrics_http_listener_addr)
.service_name(env!("CARGO_PKG_NAME"));
.service_name(env!("CARGO_PKG_NAME"))
.register_metrics(|| {}); // conductor currently has no metrics
}

if let Err(e) = telemetry_conf
Expand Down
4 changes: 2 additions & 2 deletions crates/astria-sequencer-relayer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ async fn main() -> ExitCode {
if !cfg.no_metrics {
telemetry_conf = telemetry_conf
.metrics_addr(&cfg.metrics_http_listener_addr)
.service_name(env!("CARGO_PKG_NAME"));
.service_name(env!("CARGO_PKG_NAME"))
.register_metrics(metrics_init::register);
}
metrics_init::register();

if let Err(e) = telemetry_conf
.try_init()
Expand Down
4 changes: 2 additions & 2 deletions crates/astria-sequencer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ async fn main() -> ExitCode {
if !cfg.no_metrics {
telemetry_conf = telemetry_conf
.metrics_addr(&cfg.metrics_http_listener_addr)
.service_name(env!("CARGO_PKG_NAME"));
.service_name(env!("CARGO_PKG_NAME"))
.register_metrics(metrics_init::register);
}
metrics_init::register();

if let Err(e) = telemetry_conf
.try_init()
Expand Down
25 changes: 25 additions & 0 deletions crates/astria-telemetry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ impl Error {
fn exporter_install(source: BuildError) -> Self {
Self(ErrorKind::ExporterInstall(source))
}

fn no_metric_register_func() -> Self {
Self(ErrorKind::NoMetricRegisterFunc)
}
}

#[derive(Debug, thiserror::Error)]
Expand All @@ -90,6 +94,11 @@ enum ErrorKind {
BucketError(#[source] BuildError),
#[error("failed installing prometheus metrics exporter")]
ExporterInstall(#[source] BuildError),
#[error(
"telemetry was configured to run with metrics, but no function/closure to register \
metrics was provided"
)]
NoMetricRegisterFunc,
}

#[must_use = "the otel config must be initialized to be useful"]
Expand Down Expand Up @@ -136,6 +145,7 @@ pub struct Config {
metrics_addr: Option<String>,
service_name: String,
metric_buckets: Option<Vec<f64>>,
register_metrics: Option<Box<dyn Fn()>>,
}

impl Config {
Expand All @@ -150,6 +160,7 @@ impl Config {
metrics_addr: None,
service_name: String::new(),
metric_buckets: None,
register_metrics: None,
}
}
}
Expand Down Expand Up @@ -237,6 +248,14 @@ impl Config {
}
}

#[must_use = "telemetry must be initialized to be useful"]
pub fn register_metrics<F: Fn() + 'static>(self, f: F) -> Self {
Self {
register_metrics: Some(Box::new(f)),
..self
}
}

/// Initialize telemetry, consuming the config.
///
/// # Errors
Expand All @@ -252,6 +271,7 @@ impl Config {
metrics_addr,
service_name,
metric_buckets,
register_metrics,
} = self;

let env_filter = {
Expand Down Expand Up @@ -322,6 +342,11 @@ impl Config {
.map_err(Error::bucket_error)?;
}

let Some(register_metrics) = register_metrics else {
return Err(Error::no_metric_register_func());
};
register_metrics();

metrics_builder.install().map_err(Error::exporter_install)?;
}

Expand Down

0 comments on commit 6ceb3f9

Please sign in to comment.