Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more metrics #2310

Merged
merged 62 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
eb5525c
Add `gas_per_block` metric
rafal-ch Oct 7, 2024
260b745
Add `transactions_per_block` metric
rafal-ch Oct 7, 2024
c84204b
Add `fee_per_block` metric
rafal-ch Oct 7, 2024
8c5a979
Correct bucket names
rafal-ch Oct 7, 2024
ddb424e
Producer metrics - gas price
acerone85 Oct 7, 2024
27fb0fd
Update bucket values for new metrics
rafal-ch Oct 7, 2024
09357db
chore: add libp2p bandwidth metrics
rymnc Oct 7, 2024
088b918
fix: use dns
rymnc Oct 7, 2024
76b1084
chore: more p2p metrics
rymnc Oct 7, 2024
090ada8
Rework histogram bucket initialization
rafal-ch Oct 8, 2024
bd8b64b
Bucket access function returns iterator
rafal-ch Oct 8, 2024
f205434
Extract the `buckets` module
rafal-ch Oct 8, 2024
de98ec5
Update changelog
rafal-ch Oct 8, 2024
58cf08b
Merge remote-tracking branch 'upstream/master' into 807_add_more_metrics
rafal-ch Oct 8, 2024
c897f8a
Fix `tokio` dependencies
rafal-ch Oct 8, 2024
f184a61
Add test for the presence of all required buckets
rafal-ch Oct 8, 2024
b86efce
Additional length assert in bucket tests
rafal-ch Oct 8, 2024
b8241a0
Remove the `GasPrice` metric
rafal-ch Oct 8, 2024
94f3d42
Fix `strum` dependency definition
rafal-ch Oct 8, 2024
4166809
Update the metric bucket values
rafal-ch Oct 8, 2024
3b128b5
Use explicit `_gwei` suffix for "fee_per_block" metric
rafal-ch Oct 8, 2024
8817d1a
Update changelog
rafal-ch Oct 8, 2024
9bc707c
Merge branch 'master' into 807_add_more_metrics
rafal-ch Oct 8, 2024
3badebd
Reformat `Buckets::Timing` for clarity
rafal-ch Oct 8, 2024
aadc59f
Merge remote-tracking branch 'upstream/807_add_more_metrics' into 807…
rafal-ch Oct 8, 2024
87eed6d
Calculate `total_gas_used` and `total_fee` in a single pass over tran…
rafal-ch Oct 8, 2024
fa60c9e
Move metrics to executor
rafal-ch Oct 8, 2024
10e3407
Add the `executor_size_per_block_bytes` metric
rafal-ch Oct 8, 2024
0978160
Remove no longer used metrics from the importer
rafal-ch Oct 8, 2024
3920e74
Remove the no longer needed `total_fee()` function
rafal-ch Oct 8, 2024
703a89d
Update executor metrics after processing all transactions from a block
rafal-ch Oct 8, 2024
b10178e
Fix comment
rafal-ch Oct 8, 2024
b41331b
Update bucket sized for 'Fee' metric
rafal-ch Oct 9, 2024
ef13002
Update bucket sized for 'TransactionsCount' metric
rafal-ch Oct 9, 2024
5387bc9
Update bucket sized for 'SizeUsed' metric
rafal-ch Oct 9, 2024
853100d
Move the execution metrics to importer
rafal-ch Oct 9, 2024
37d4cdc
Block importer respects the `--metrics` command line parameter
rafal-ch Oct 9, 2024
2297804
Merge remote-tracking branch 'upstream/master' into 807_add_more_metrics
rafal-ch Oct 11, 2024
11a6cfe
Merge remote-tracking branch 'upstream/master' into 807_add_more_metrics
rafal-ch Oct 14, 2024
c921a09
Add support for comma separated metric configuration
rafal-ch Oct 14, 2024
0785b2d
Update changelog
rafal-ch Oct 14, 2024
aa751cd
Detailed help message string for `disable-metrics`
rafal-ch Oct 14, 2024
0f85f04
Sort dependencies
rafal-ch Oct 14, 2024
21ebbc9
Make the `disable-metrics` cli arg optional
rafal-ch Oct 14, 2024
523932d
Simplify implementation of `HELP_STRING`
rafal-ch Oct 14, 2024
1b5c428
Add additional tests for metrics config
rafal-ch Oct 14, 2024
2fba5d2
Figure out dependencies to be able to run tests locally
rafal-ch Oct 14, 2024
f23b469
Merge remote-tracking branch 'upstream/master' into 807_add_more_metrics
rafal-ch Oct 14, 2024
e67ae19
Fix compilation issues in `metrics` crate
rafal-ch Oct 14, 2024
c043ed7
Change some metrics from histogram to a gauge
rafal-ch Oct 14, 2024
7d17f99
Add `importer_gas_price_for_block` metric
rafal-ch Oct 14, 2024
e0124b6
Simplify metric config handling
rafal-ch Oct 14, 2024
f12185f
Make metric config tests more robust
rafal-ch Oct 14, 2024
be71c4b
Merge branch 'master' into 807_add_more_metrics
xgreenx Oct 14, 2024
a128622
Metric config creation may now return an error
rafal-ch Oct 14, 2024
395f491
Merge remote-tracking branch 'upstream/807_add_more_metrics' into 807…
rafal-ch Oct 14, 2024
eb3872f
Log metrics config at startup
rafal-ch Oct 14, 2024
bee9c6f
Allow creating metrics config from empty string, it's equal to `all`
rafal-ch Oct 14, 2024
8da222a
Merge remote-tracking branch 'upstream/master' into 807_add_more_metrics
rafal-ch Oct 14, 2024
8c0cccc
Reworked parsing of the command for disabled metrics
xgreenx Oct 14, 2024
aa6120a
Merge branch 'master' into 807_add_more_metrics
xgreenx Oct 14, 2024
5aea57a
Show nice log
xgreenx Oct 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Changed
- [2334](https://github.com/FuelLabs/fuel-core/pull/2334): Prepare the GraphQL service for the switching to `async` methods.
- [2310](https://github.com/FuelLabs/fuel-core/pull/2310): New metrics: "The gas prices used in a block" (`importer_gas_price_for_block`), "The total gas used in a block" (`importer_gas_per_block`), "The total fee (gwei) paid by transactions in a block" (`importer_fee_per_block_gwei`), "The total number of transactions in a block" (`importer_transactions_per_block`), P2P metrics for swarm and protocol.

#### Breaking
- [2310](https://github.com/FuelLabs/fuel-core/pull/2310): The `metrics` command-line parameter has been replaced with `disable-metrics`. Metrics are now enabled by default, with the option to disable them entirely or on a per-module basis.
- [2341](https://github.com/FuelLabs/fuel-core/pull/2341): Updated all pagination queries to work with the async stream instead of the sync iterator.
- [2340](https://github.com/FuelLabs/fuel-core/pull/2340): Avoid long heavy tasks in the GraphQL service by splitting work into batches.
- [2350](https://github.com/FuelLabs/fuel-core/pull/2350): Limited the number of threads used by the GraphQL service.
Expand Down
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions bin/fuel-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ dotenvy = { version = "0.15", optional = true }
fuel-core = { workspace = true, features = ["wasm-executor"] }
fuel-core-chain-config = { workspace = true }
fuel-core-compression = { workspace = true }
fuel-core-metrics = { workspace = true }
fuel-core-poa = { workspace = true }
fuel-core-types = { workspace = true, features = ["std"] }
hex = { workspace = true }
Expand All @@ -53,6 +54,7 @@ itertools = { workspace = true }
pretty_assertions = { workspace = true }
rand = { workspace = true }
serde = { workspace = true }
strum = { workspace = true }
tempfile = { workspace = true }
test-case = { workspace = true }

Expand Down
112 changes: 105 additions & 7 deletions bin/fuel-core/src/cli/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ use fuel_core_chain_config::{
SnapshotMetadata,
SnapshotReader,
};
use fuel_core_metrics::config::{
DisableConfig,
Module,
};
use fuel_core_poa::signer::SignMode;
use fuel_core_types::blockchain::header::StateTransitionBytecodeVersion;
use pyroscope::{
Expand Down Expand Up @@ -236,8 +240,8 @@ pub struct Command {
#[cfg(feature = "p2p")]
pub sync_args: p2p::SyncArgs,

#[arg(long = "metrics", env)]
pub metrics: bool,
#[arg(long = "disable-metrics", value_delimiter = ',', help = fuel_core_metrics::config::help_string(), env)]
pub disabled_metrics: Vec<Module>,

#[clap(long = "verify-max-da-lag", default_value = "10", env)]
pub max_da_lag: u64,
Expand Down Expand Up @@ -294,7 +298,7 @@ impl Command {
p2p_args,
#[cfg(feature = "p2p")]
sync_args,
metrics,
disabled_metrics: metrics,
max_da_lag,
max_wait_time,
tx_pool,
Expand All @@ -305,6 +309,14 @@ impl Command {
profiling: _,
} = self;

let enabled_metrics = metrics.list_of_enabled();

if !enabled_metrics.is_empty() {
info!("`{:?}` metrics are enabled", enabled_metrics);
} else {
info!("All metrics are disabled");
}

let addr = net::SocketAddr::new(graphql.ip, graphql.port);

let snapshot_reader = match snapshot.as_ref() {
Expand All @@ -320,7 +332,10 @@ impl Command {
let relayer_cfg = relayer_args.into_config();

#[cfg(feature = "p2p")]
let p2p_cfg = p2p_args.into_config(chain_config.chain_name.clone(), metrics)?;
let p2p_cfg = p2p_args.into_config(
chain_config.chain_name.clone(),
metrics.is_enabled(Module::P2P),
)?;

let trigger: Trigger = poa_trigger.into();

Expand Down Expand Up @@ -428,8 +443,9 @@ impl Command {
state_rewind_policy,
};

let block_importer =
fuel_core::service::config::fuel_core_importer::Config::new();
let block_importer = fuel_core::service::config::fuel_core_importer::Config::new(
metrics.is_enabled(Module::Importer),
);

let da_compression = match da_compression {
Some(retention) => {
Expand Down Expand Up @@ -549,7 +565,7 @@ impl Command {
},
block_producer: ProducerConfig {
coinbase_recipient,
metrics,
metrics: metrics.is_enabled(Module::Producer),
},
starting_gas_price,
gas_price_change_percent,
Expand Down Expand Up @@ -659,3 +675,85 @@ fn start_pyroscope_agent(
})
.transpose()
}

#[cfg(test)]
#[allow(non_snake_case)]
#[allow(clippy::bool_assert_comparison)]
mod tests {
use super::*;
use strum::IntoEnumIterator;

fn parse_command(args: &[&str]) -> anyhow::Result<Command> {
Ok(Command::try_parse_from([""].iter().chain(args))?)
}

#[test]
fn parse_disabled_metrics__no_value_enables_everything() {
// Given
let args = [];

// When
let command = parse_command(&args).unwrap();

// Then
let config = command.disabled_metrics;
Module::iter().for_each(|module| {
assert_eq!(config.is_enabled(module), true);
});
}

#[test]
fn parse_disabled_metrics__all() {
// Given
let args = ["--disable-metrics", "all"];

// When
let command = parse_command(&args).unwrap();

// Then
let config = command.disabled_metrics;
Module::iter().for_each(|module| {
assert_eq!(config.is_enabled(module), false);
});
}

#[test]
fn parse_disabled_metrics__mixed_args() {
// Given
let args = [
"--disable-metrics",
"txpool,importer",
"--disable-metrics",
"graphql",
];

// When
let command = parse_command(&args).unwrap();

// Then
let config = command.disabled_metrics;
assert_eq!(config.is_enabled(Module::TxPool), false);
assert_eq!(config.is_enabled(Module::Importer), false);
assert_eq!(config.is_enabled(Module::GraphQL), false);
assert_eq!(config.is_enabled(Module::P2P), true);
assert_eq!(config.is_enabled(Module::Producer), true);
}

#[test]
fn parse_disabled_metrics__bad_values() {
// Given
let args = ["--disable-metrics", "txpool,alpha,bravo"];

// When
let command = parse_command(&args);

// Then
let err = command.expect_err("should fail to parse");
assert_eq!(
err.to_string(),
"error: invalid value 'alpha' for \
'--disable-metrics <DISABLED_METRICS>': Matching variant not found\
\n\nFor more information, try '--help'.\n"
);
}
}
5 changes: 4 additions & 1 deletion crates/fuel-core/src/service/adapters/block_importer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,11 @@ impl BlockImporterAdapter {
executor: ExecutorAdapter,
verifier: VerifierAdapter,
) -> Self {
let metrics = config.metrics;
let importer = Importer::new(chain_id, config, database, executor, verifier);
importer.init_metrics();
if metrics {
importer.init_metrics();
}
Self {
block_importer: Arc::new(importer),
}
Expand Down
2 changes: 1 addition & 1 deletion crates/fuel-core/src/service/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl Config {

#[cfg(feature = "test-helpers")]
pub fn local_node_with_reader(snapshot_reader: SnapshotReader) -> Self {
let block_importer = fuel_core_importer::Config::new();
let block_importer = fuel_core_importer::Config::new(false);
let latest_block = snapshot_reader.last_block_config();
// In tests, we always want to use the native executor as a default configuration.
let native_executor_version = latest_block
Expand Down
3 changes: 3 additions & 0 deletions crates/metrics/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ repository = { workspace = true }
description = "Fuel metrics"

[dependencies]
once_cell = { workspace = true }
parking_lot = { workspace = true }
pin-project-lite = { workspace = true }
prometheus-client = { workspace = true }
regex = "1"
strum = { workspace = true }
strum_macros = { workspace = true }
tracing = { workspace = true }

[dev-dependencies]
Expand Down
65 changes: 65 additions & 0 deletions crates/metrics/src/buckets.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use std::{
collections::HashMap,
sync::OnceLock,
};
#[cfg(test)]
use strum_macros::EnumIter;

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(test, derive(EnumIter))]
pub(crate) enum Buckets {
Timing,
}
static BUCKETS: OnceLock<HashMap<Buckets, Vec<f64>>> = OnceLock::new();
pub(crate) fn buckets(b: Buckets) -> impl Iterator<Item = f64> {
BUCKETS.get_or_init(initialize_buckets)[&b].iter().copied()
}

#[rustfmt::skip]
fn initialize_buckets() -> HashMap<Buckets, Vec<f64>> {
xgreenx marked this conversation as resolved.
Show resolved Hide resolved
[
(
Buckets::Timing,
vec![
0.005,
0.010,
0.025,
0.050,
0.100,
0.250,
0.500,
1.000,
2.500,
5.000,
10.000,
],
),
]
.into_iter()
.collect()
}

#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;

use crate::buckets::Buckets;

use super::initialize_buckets;

#[test]
fn buckets_are_defined_for_every_variant() {
let actual_buckets = initialize_buckets();
let actual_buckets = actual_buckets.keys().collect::<Vec<_>>();

let required_buckets: Vec<_> = Buckets::iter().collect();

assert_eq!(required_buckets.len(), actual_buckets.len());

let all_buckets_defined = required_buckets
.iter()
.all(|required_bucket| actual_buckets.contains(&required_bucket));

assert!(all_buckets_defined)
}
}
51 changes: 51 additions & 0 deletions crates/metrics/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use once_cell::sync::Lazy;
use strum::IntoEnumIterator;
use strum_macros::{
Display,
EnumIter,
EnumString,
};

#[derive(Debug, Display, Clone, Copy, PartialEq, EnumString, EnumIter)]
#[strum(serialize_all = "lowercase")]
pub enum Module {
All,
Importer,
P2P,
Producer,
TxPool, /* TODO[RC]: Not used. Add support in https://github.com/FuelLabs/fuel-core/pull/2321 */
GraphQL, // TODO[RC]: Not used... yet.
}

/// Configuration for disabling metrics.
pub trait DisableConfig {
/// Returns `true` if the given module is enabled.
fn is_enabled(&self, module: Module) -> bool;

/// Returns the list of enabled modules.
fn list_of_enabled(&self) -> Vec<Module>;
}

impl DisableConfig for Vec<Module> {
fn is_enabled(&self, module: Module) -> bool {
!self.contains(&module) && !self.contains(&Module::All)
}

fn list_of_enabled(&self) -> Vec<Module> {
Module::iter()
.filter(|module| self.is_enabled(*module) && *module != Module::All)
.collect()
}
}

static HELP_STRING: Lazy<String> = Lazy::new(|| {
let all_modules: Vec<_> = Module::iter().map(|module| module.to_string()).collect();
format!(
"Comma-separated list of modules or 'all' to disable all metrics. Available options: {}, all",
all_modules.join(", ")
)
});

pub fn help_string() -> &'static str {
&HELP_STRING
}
4 changes: 3 additions & 1 deletion crates/metrics/src/futures/future_tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,9 @@ impl<T: Future> Future for FutureTracker<T> {

#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;

use crate::futures::future_tracker::FutureTracker;

#[tokio::test]
async fn empty_future() {
Expand Down
7 changes: 5 additions & 2 deletions crates/metrics/src/graphql_metrics.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::{
buckets::{
buckets,
Buckets,
},
global_registry,
timing_buckets,
};
use prometheus_client::{
encoding::EncodeLabelSet,
Expand Down Expand Up @@ -30,7 +33,7 @@ impl GraphqlMetrics {
let tx_count_gauge = Gauge::default();
let queries_complexity = Histogram::new(buckets_complexity());
let requests = Family::<Label, Histogram>::new_with_constructor(|| {
Histogram::new(timing_buckets().iter().cloned())
Histogram::new(buckets(Buckets::Timing))
});
let mut registry = global_registry().registry.lock();
registry.register("graphql_request_duration_seconds", "", requests.clone());
Expand Down
Loading
Loading