Skip to content

Commit

Permalink
Re-export reth-metrics-derive crate from dojo-metrics (starkware…
Browse files Browse the repository at this point in the history
…-libs#1719)

ref starkware-libs#1369

- re-export [reth-metrics-derive](https://github.com/paradigmxyz/reth/tree/v0.2.0-beta.4/crates/metrics/metrics-derive) crate from dojo-metrics
- rename metrics -> dojo-metrics crate
- re-export core metrics stuff from dojo-metrics

---

this PR relies on starkware-libs#1720 bcs reth's MSRV is 1.76.0, otherwise can't build reth-metrics-derive.
  • Loading branch information
kariy committed Mar 29, 2024
1 parent 3de11db commit 48e7261
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 191 deletions.
247 changes: 108 additions & 139 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ lto = "fat"
common = { path = "crates/common" }

# metrics
metrics = { path = "crates/metrics" }
dojo-metrics = { path = "crates/metrics" }

# dojo-lang
dojo-bindgen = { path = "crates/dojo-bindgen" }
Expand Down Expand Up @@ -139,12 +139,13 @@ indoc = "1.0.7"
itertools = "0.10.3"
jsonrpsee = { version = "0.16.2", default-features = false }
lazy_static = "1.4.0"
metrics-process = "1.0.9"
metrics = "0.21.1"
num-traits = { version = "0.2", default-features = false }
once_cell = "1.0"
parking_lot = "0.12.1"
pretty_assertions = "1.2.1"
rayon = "1.8.0"
regex = "1.10.3"
salsa = "0.16.1"
scarb = { git = "https://github.com/software-mansion/scarb", tag = "v2.5.4" }
scarb-ui = { git = "https://github.com/software-mansion/scarb", tag = "v2.5.4" }
Expand All @@ -166,7 +167,6 @@ tokio = { version = "1.32.0", features = [ "full" ] }
toml = "0.7.4"
tracing = "0.1.34"
tracing-subscriber = { version = "0.3.16", features = [ "env-filter", "json" ] }
regex = "1.10.3"
url = { version = "2.4.0", features = [ "serde" ] }

rstest = "0.18.2"
Expand Down
5 changes: 2 additions & 3 deletions bin/katana/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@ clap.workspace = true
clap_complete.workspace = true
common.workspace = true
console.workspace = true
dojo-metrics.workspace = true
katana-core.workspace = true
katana-executor.workspace = true
katana-primitives.workspace = true
katana-rpc-api.workspace = true
katana-rpc.workspace = true
metrics-process.workspace = true
metrics.workspace = true
serde_json.workspace = true
shellexpand = "3.1.0"
starknet_api.workspace = true
Expand All @@ -37,6 +36,6 @@ default = [ "blockifier", "jemalloc", "messaging" ]
blockifier = [ "katana-executor/blockifier" ]
sir = [ "katana-executor/sir" ]

jemalloc = [ "metrics/jemalloc" ]
jemalloc = [ "dojo-metrics/jemalloc" ]
messaging = [ "katana-core/messaging" ]
starknet-messaging = [ "katana-core/starknet-messaging", "messaging" ]
2 changes: 1 addition & 1 deletion bin/katana/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::sync::Arc;
use clap::{CommandFactory, Parser};
use clap_complete::{generate, Shell};
use console::Style;
use dojo_metrics::{metrics_process, prometheus_exporter};
use katana_core::constants::MAX_RECURSION_DEPTH;
use katana_core::env::get_default_vm_resource_fee_cost;
use katana_core::sequencer::KatanaSequencer;
Expand All @@ -15,7 +16,6 @@ use katana_primitives::env::{CfgEnv, FeeTokenAddressses};
use katana_primitives::genesis::allocation::GenesisAccountAlloc;
use katana_primitives::genesis::Genesis;
use katana_rpc::{spawn, NodeHandle};
use metrics::prometheus_exporter;
use tokio::signal::ctrl_c;
use tracing::info;

Expand Down
7 changes: 3 additions & 4 deletions bin/torii/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ chrono.workspace = true
clap.workspace = true
common.workspace = true
ctrlc = { version = "3.4", features = [ "termination" ] }
dojo-metrics.workspace = true
dojo-types.workspace = true
dojo-world.workspace = true
either = "1.9.0"
Expand All @@ -24,8 +25,6 @@ hyper-reverse-proxy = { git = "https://github.com/tarrencev/hyper-reverse-proxy"
hyper.workspace = true
indexmap = "1.9.3"
lazy_static.workspace = true
metrics-process.workspace = true
metrics.workspace = true
scarb.workspace = true
serde.workspace = true
serde_json.workspace = true
Expand All @@ -38,19 +37,19 @@ tokio.workspace = true
torii-core.workspace = true
torii-graphql.workspace = true
torii-grpc = { workspace = true, features = [ "server" ] }
torii-relay.workspace = true
torii-server.workspace = true
tower = "0.4.13"
tower-http = "0.4.4"
tracing-subscriber.workspace = true
tracing.workspace = true
url.workspace = true
torii-relay.workspace = true
webbrowser = "0.8"

[dev-dependencies]
camino.workspace = true

[features]
default = [ "jemalloc", "sqlite" ]
jemalloc = [ "metrics/jemalloc" ]
jemalloc = [ "dojo-metrics/jemalloc" ]
sqlite = [ "sqlx/sqlite" ]
2 changes: 1 addition & 1 deletion bin/torii/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ use std::sync::Arc;

use clap::Parser;
use common::parse::{parse_socket_address, parse_url};
use dojo_metrics::{metrics_process, prometheus_exporter};
use dojo_world::contracts::world::WorldContractReader;
use metrics::prometheus_exporter;
use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions};
use sqlx::SqlitePool;
use starknet::core::types::FieldElement;
Expand Down
9 changes: 5 additions & 4 deletions crates/metrics/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
[package]
edition.workspace = true
name = "metrics"
name = "dojo-metrics"
version.workspace = true

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
anyhow.workspace = true
hyper.workspace = true
hyper = { workspace = true, features = [ "http1", "http2", "server", "tcp" ] }
thiserror.workspace = true
tokio.workspace = true
tracing.workspace = true

# Metrics
metrics = "0.21.1"
metrics-exporter-prometheus = "0.12.1"
metrics-process.workspace = true
metrics-process = "=1.0.14"
metrics-util = "0.15.0"
metrics.workspace = true
reth-metrics-derive = { git = "https://github.com/paradigmxyz/reth.git", tag = "v0.2.0-beta.4" }

[target.'cfg(not(windows))'.dependencies]
jemalloc-ctl = { version = "0.5.0", optional = true }
Expand Down
6 changes: 6 additions & 0 deletions crates/metrics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ pub mod prometheus_exporter;

#[cfg(all(feature = "jemalloc", unix))]
use jemallocator as _;
/// Re-export the metrics crate
pub use metrics;
/// Re-export the metrics-process crate
pub use metrics_process;
/// Re-export the metrics derive macro
pub use reth_metrics_derive::Metrics;

// We use jemalloc for performance reasons
#[cfg(all(feature = "jemalloc", unix))]
Expand Down
71 changes: 38 additions & 33 deletions crates/metrics/src/prometheus_exporter.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
//! Prometheus exporter
//! Adapted from Paradigm's [`reth`](https://github.com/paradigmxyz/reth/blob/c1d7d2bde398bcf410c7e2df13fd7151fc2a58b9/bin/reth/src/prometheus_exporter.rs)

use std::convert::Infallible;
use std::net::SocketAddr;
use std::sync::Arc;

use anyhow::{Context, Result};
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Request, Response, Server};
use metrics::{describe_gauge, gauge};
Expand All @@ -14,34 +16,55 @@ pub(crate) trait Hook: Fn() + Send + Sync {}
impl<T: Fn() + Send + Sync> Hook for T {}

/// Installs Prometheus as the metrics recorder.
pub fn install_recorder(prefix: &str) -> anyhow::Result<PrometheusHandle> {
///
/// ## Arguments
/// * `prefix` - Apply a prefix to all metrics keys.
pub fn install_recorder(prefix: &str) -> Result<PrometheusHandle> {
let recorder = PrometheusBuilder::new().build_recorder();
let handle = recorder.handle();

// Build metrics stack
// Build metrics stack and install the recorder
Stack::new(recorder)
.push(PrefixLayer::new(prefix))
.install()
.map_err(|e| anyhow::anyhow!("Couldn't set metrics recorder: {}", e))?;
.context("Couldn't set metrics recorder")?;

Ok(handle)
}

/// Serves Prometheus metrics over HTTP with database and process metrics.
pub async fn serve(
listen_addr: SocketAddr,
handle: PrometheusHandle,
process: metrics_process::Collector,
) -> Result<()> {
// Clone `process` to move it into the hook and use the original `process` for describe below.
let cloned_process = process.clone();
let hooks: Vec<Box<dyn Hook<Output = ()>>> =
vec![Box::new(move || cloned_process.collect()), Box::new(collect_memory_stats)];
serve_with_hooks(listen_addr, handle, hooks).await?;

process.describe();
describe_memory_stats();

Ok(())
}

/// Serves Prometheus metrics over HTTP with hooks.
///
/// The hooks are called every time the metrics are requested at the given endpoint, and can be used
/// to record values for pull-style metrics, i.e. metrics that are not automatically updated.
pub(crate) async fn serve_with_hooks<F: Hook + 'static>(
async fn serve_with_hooks<F: Hook + 'static>(
listen_addr: SocketAddr,
handle: PrometheusHandle,
hooks: impl IntoIterator<Item = F>,
) -> anyhow::Result<()> {
) -> Result<()> {
let hooks: Vec<_> = hooks.into_iter().collect();

// Start endpoint
start_endpoint(listen_addr, handle, Arc::new(move || hooks.iter().for_each(|hook| hook())))
.await
.map_err(|e| anyhow::anyhow!("Could not start Prometheus endpoint: {}", e))?;
.context("Could not start Prometheus endpoint")?;

Ok(())
}
Expand All @@ -51,7 +74,7 @@ async fn start_endpoint<F: Hook + 'static>(
listen_addr: SocketAddr,
handle: PrometheusHandle,
hook: Arc<F>,
) -> anyhow::Result<()> {
) -> Result<()> {
let make_svc = make_service_fn(move |_| {
let handle = handle.clone();
let hook = Arc::clone(&hook);
Expand All @@ -64,75 +87,57 @@ async fn start_endpoint<F: Hook + 'static>(
}
});
let server = Server::try_bind(&listen_addr)
.map_err(|e| anyhow::anyhow!("Could not bind to address: {}", e))?
.context(format!("Could not bind to address: {listen_addr}"))?
.serve(make_svc);

tokio::spawn(async move { server.await.expect("Metrics endpoint crashed") });

Ok(())
}

/// Serves Prometheus metrics over HTTP with database and process metrics.
pub async fn serve(
listen_addr: SocketAddr,
handle: PrometheusHandle,
process: metrics_process::Collector,
) -> anyhow::Result<()> {
// Clone `process` to move it into the hook and use the original `process` for describe below.
let cloned_process = process.clone();
let hooks: Vec<Box<dyn Hook<Output = ()>>> =
vec![Box::new(move || cloned_process.collect()), Box::new(collect_memory_stats)];
serve_with_hooks(listen_addr, handle, hooks).await?;

process.describe();
describe_memory_stats();

Ok(())
}

#[cfg(all(feature = "jemalloc", unix))]
fn collect_memory_stats() {
use jemalloc_ctl::{epoch, stats};

if epoch::advance()
.map_err(|error| tracing::error!(?error, "Failed to advance jemalloc epoch"))
.map_err(|error| tracing::error!(%error, "Failed to advance jemalloc epoch"))
.is_err()
{
return;
}

if let Ok(value) = stats::active::read()
.map_err(|error| tracing::error!(?error, "Failed to read jemalloc.stats.active"))
.map_err(|error| tracing::error!(%error, "Failed to read jemalloc.stats.active"))
{
gauge!("jemalloc.active", value as f64);
}

if let Ok(value) = stats::allocated::read()
.map_err(|error| tracing::error!(?error, "Failed to read jemalloc.stats.allocated"))
.map_err(|error| tracing::error!(%error, "Failed to read jemalloc.stats.allocated"))
{
gauge!("jemalloc.allocated", value as f64);
}

if let Ok(value) = stats::mapped::read()
.map_err(|error| tracing::error!(?error, "Failed to read jemalloc.stats.mapped"))
.map_err(|error| tracing::error!(%error, "Failed to read jemalloc.stats.mapped"))
{
gauge!("jemalloc.mapped", value as f64);
}

if let Ok(value) = stats::metadata::read()
.map_err(|error| tracing::error!(?error, "Failed to read jemalloc.stats.metadata"))
.map_err(|error| tracing::error!(%error, "Failed to read jemalloc.stats.metadata"))
{
gauge!("jemalloc.metadata", value as f64);
}

if let Ok(value) = stats::resident::read()
.map_err(|error| tracing::error!(?error, "Failed to read jemalloc.stats.resident"))
.map_err(|error| tracing::error!(%error, "Failed to read jemalloc.stats.resident"))
{
gauge!("jemalloc.resident", value as f64);
}

if let Ok(value) = stats::retained::read()
.map_err(|error| tracing::error!(?error, "Failed to read jemalloc.stats.retained"))
.map_err(|error| tracing::error!(%error, "Failed to read jemalloc.stats.retained"))
{
gauge!("jemalloc.retained", value as f64);
}
Expand Down
5 changes: 2 additions & 3 deletions crates/torii/server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ camino.workspace = true
chrono.workspace = true
clap.workspace = true
ctrlc = { version = "3.4", features = [ "termination" ] }
dojo-metrics.workspace = true
dojo-types = { path = "../../dojo-types" }
dojo-world = { path = "../../dojo-world" }
either = "1.9.0"
Expand All @@ -23,8 +24,6 @@ hyper-reverse-proxy = { git = "https://github.com/tarrencev/hyper-reverse-proxy"
hyper.workspace = true
indexmap = "1.9.3"
lazy_static.workspace = true
metrics = { path = "../../metrics" }
metrics-process.workspace = true
scarb.workspace = true
serde.workspace = true
serde_json.workspace = true
Expand All @@ -48,5 +47,5 @@ camino.workspace = true

[features]
default = [ "jemalloc", "sqlite" ]
jemalloc = [ "metrics/jemalloc" ]
jemalloc = [ "dojo-metrics/jemalloc" ]
sqlite = [ "sqlx/sqlite" ]

0 comments on commit 48e7261

Please sign in to comment.