From fb1d7b86a3bbd98793b294894f1c65c81c1c414e Mon Sep 17 00:00:00 2001 From: Richard Janis Goldschmidt Date: Tue, 4 Jun 2024 14:28:56 +0200 Subject: [PATCH] feat: use macro to declare metric constants (#1129) ## Summary Introduce a macro `declare_metric_const!` to avoid repetition and common typos when declaring string consts used as metric names. ## Background Noticed some common errors in reviews and when writing metrics: mismatch between the const's name and the actual value. Missing underscores. Annoying repetiton of `env!("CARGO_CRATE_NAME")`; ## Changes - Declare a macro `declare_metric_const!` and define all consts in terms of it. - Add unit tests for all macros to ensure they don't accidentally break. ## Testing - Unit tests for all const declaration - Simple unit test for the macro ## Metrics - `astria_composer_transactions_per_submission` replaces `astria_composer_transaction_per_submission` --- Cargo.lock | 1 + Cargo.toml | 1 + .../src/metrics_init.rs | 50 +++++-- crates/astria-composer/src/metrics_init.rs | 80 +++++++---- crates/astria-conductor/src/metrics_init.rs | 85 ++++++++---- crates/astria-sequencer-relayer/Cargo.toml | 4 +- .../src/metrics_init.rs | 113 ++++++++++------ crates/astria-sequencer/src/metrics_init.rs | 128 +++++++++++------- crates/astria-telemetry/Cargo.toml | 1 + crates/astria-telemetry/src/lib.rs | 3 + crates/astria-telemetry/src/macros.rs | 58 ++++++++ 11 files changed, 366 insertions(+), 158 deletions(-) create mode 100644 crates/astria-telemetry/src/macros.rs diff --git a/Cargo.lock b/Cargo.lock index 05aeb5635..bd7bb35d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -914,6 +914,7 @@ version = "0.1.0" dependencies = [ "base64 0.21.7", "base64-serde", + "const_format", "metrics-exporter-prometheus", "opentelemetry", "opentelemetry-otlp", diff --git a/Cargo.toml b/Cargo.toml index 851bb6824..1e46cc79c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,6 +57,7 @@ bytes = "1" celestia-tendermint = "0.32.1" celestia-types = "0.1.1" clap = "4.5.4" +const_format = "0.2.32" ethers = "2.0.11" futures = "0.3" hex = "0.4" diff --git a/crates/astria-bridge-withdrawer/src/metrics_init.rs b/crates/astria-bridge-withdrawer/src/metrics_init.rs index 44b039e72..bc9f455da 100644 --- a/crates/astria-bridge-withdrawer/src/metrics_init.rs +++ b/crates/astria-bridge-withdrawer/src/metrics_init.rs @@ -8,6 +8,7 @@ use metrics::{ describe_histogram, Unit, }; +use telemetry::metric_name; /// Registers all metrics used by this crate. pub fn register() { @@ -39,19 +40,42 @@ pub fn register() { ); } -pub const NONCE_FETCH_COUNT: &str = concat!(env!("CARGO_CRATE_NAME"), "_nonce_fetch_count"); +metric_name!(pub const CURRENT_NONCE); +metric_name!(pub const NONCE_FETCH_COUNT); +metric_name!(pub const NONCE_FETCH_FAILURE_COUNT); +metric_name!(pub const NONCE_FETCH_LATENCY); +metric_name!(pub const SEQUENCER_SUBMISSION_FAILURE_COUNT); +metric_name!(pub const SEQUENCER_SUBMISSION_LATENCY); -pub const NONCE_FETCH_FAILURE_COUNT: &str = - concat!(env!("CARGO_CRATE_NAME"), "_nonce_fetch_failure_count"); - -pub const NONCE_FETCH_LATENCY: &str = concat!(env!("CARGO_CRATE_NAME"), "_nonce_fetch_latency"); - -pub const CURRENT_NONCE: &str = concat!(env!("CARGO_CRATE_NAME"), "_current_nonce"); +#[cfg(test)] +mod tests { + use super::{ + CURRENT_NONCE, + NONCE_FETCH_COUNT, + NONCE_FETCH_FAILURE_COUNT, + NONCE_FETCH_LATENCY, + SEQUENCER_SUBMISSION_FAILURE_COUNT, + SEQUENCER_SUBMISSION_LATENCY, + }; -pub const SEQUENCER_SUBMISSION_FAILURE_COUNT: &str = concat!( - env!("CARGO_CRATE_NAME"), - "_sequencer_submission_failure_count" -); + #[track_caller] + fn assert_const(actual: &'static str, suffix: &str) { + // XXX: hard-code this so the crate name isn't accidentally changed. + const CRATE_NAME: &str = "astria_bridge_withdrawer"; + let expected = format!("{CRATE_NAME}_{suffix}"); + assert_eq!(expected, actual); + } -pub const SEQUENCER_SUBMISSION_LATENCY: &str = - concat!(env!("CARGO_CRATE_NAME"), "_sequencer_submission_latency"); + #[test] + fn metrics_are_as_expected() { + assert_const(CURRENT_NONCE, "current_nonce"); + assert_const(NONCE_FETCH_COUNT, "nonce_fetch_count"); + assert_const(NONCE_FETCH_FAILURE_COUNT, "nonce_fetch_failure_count"); + assert_const(NONCE_FETCH_LATENCY, "nonce_fetch_latency"); + assert_const( + SEQUENCER_SUBMISSION_FAILURE_COUNT, + "sequencer_submission_failure_count", + ); + assert_const(SEQUENCER_SUBMISSION_LATENCY, "sequencer_submission_latency"); + } +} diff --git a/crates/astria-composer/src/metrics_init.rs b/crates/astria-composer/src/metrics_init.rs index 71d9ac57f..a71028b72 100644 --- a/crates/astria-composer/src/metrics_init.rs +++ b/crates/astria-composer/src/metrics_init.rs @@ -8,6 +8,7 @@ use metrics::{ describe_histogram, Unit, }; +use telemetry::metric_name; /// Labels pub(crate) const ROLLUP_ID_LABEL: &str = "rollup_id"; @@ -73,31 +74,60 @@ pub fn register() { ); } -pub const TRANSACTIONS_RECEIVED: &str = concat!(env!("CARGO_CRATE_NAME"), "_transactions_received"); +metric_name!(pub const TRANSACTIONS_RECEIVED); +metric_name!(pub const TRANSACTIONS_DROPPED); +metric_name!(pub const TRANSACTIONS_DROPPED_TOO_LARGE); +metric_name!(pub const NONCE_FETCH_COUNT); +metric_name!(pub const NONCE_FETCH_FAILURE_COUNT); +metric_name!(pub const NONCE_FETCH_LATENCY); +metric_name!(pub const CURRENT_NONCE); +metric_name!(pub const SEQUENCER_SUBMISSION_LATENCY); +metric_name!(pub const SEQUENCER_SUBMISSION_FAILURE_COUNT); +metric_name!(pub const TRANSACTIONS_PER_SUBMISSION); +metric_name!(pub const BYTES_PER_SUBMISSION); -pub const TRANSACTIONS_DROPPED: &str = concat!(env!("CARGO_CRATE_NAME"), "_transactions_dropped"); - -pub const TRANSACTIONS_DROPPED_TOO_LARGE: &str = - concat!(env!("CARGO_CRATE_NAME"), "_transactions_dropped_too_large"); - -pub const NONCE_FETCH_COUNT: &str = concat!(env!("CARGO_CRATE_NAME"), "_nonce_fetch_count"); - -pub const NONCE_FETCH_FAILURE_COUNT: &str = - concat!(env!("CARGO_CRATE_NAME"), "_nonce_fetch_failure_count"); - -pub const NONCE_FETCH_LATENCY: &str = concat!(env!("CARGO_CRATE_NAME"), "_nonce_fetch_latency"); - -pub const CURRENT_NONCE: &str = concat!(env!("CARGO_CRATE_NAME"), "_current_nonce"); - -pub const SEQUENCER_SUBMISSION_LATENCY: &str = - concat!(env!("CARGO_CRATE_NAME"), "_sequencer_submission_latency"); - -pub const SEQUENCER_SUBMISSION_FAILURE_COUNT: &str = concat!( - env!("CARGO_CRATE_NAME"), - "_sequencer_submission_failure_count" -); +#[cfg(test)] +mod tests { + use super::{ + BYTES_PER_SUBMISSION, + CURRENT_NONCE, + NONCE_FETCH_COUNT, + NONCE_FETCH_FAILURE_COUNT, + NONCE_FETCH_LATENCY, + SEQUENCER_SUBMISSION_FAILURE_COUNT, + SEQUENCER_SUBMISSION_LATENCY, + TRANSACTIONS_DROPPED, + TRANSACTIONS_DROPPED_TOO_LARGE, + TRANSACTIONS_PER_SUBMISSION, + TRANSACTIONS_RECEIVED, + }; -pub const TRANSACTIONS_PER_SUBMISSION: &str = - concat!(env!("CARGO_CRATE_NAME"), "_transaction_per_submission"); + #[track_caller] + fn assert_const(actual: &'static str, suffix: &str) { + // XXX: hard-code this so the crate name isn't accidentally changed. + const CRATE_NAME: &str = "astria_composer"; + let expected = format!("{CRATE_NAME}_{suffix}"); + assert_eq!(expected, actual); + } -pub const BYTES_PER_SUBMISSION: &str = concat!(env!("CARGO_CRATE_NAME"), "_bytes_per_submission"); + #[test] + fn metrics_are_as_expected() { + assert_const(TRANSACTIONS_RECEIVED, "transactions_received"); + assert_const(TRANSACTIONS_DROPPED, "transactions_dropped"); + assert_const( + TRANSACTIONS_DROPPED_TOO_LARGE, + "transactions_dropped_too_large", + ); + assert_const(NONCE_FETCH_COUNT, "nonce_fetch_count"); + assert_const(NONCE_FETCH_FAILURE_COUNT, "nonce_fetch_failure_count"); + assert_const(NONCE_FETCH_LATENCY, "nonce_fetch_latency"); + assert_const(CURRENT_NONCE, "current_nonce"); + assert_const(SEQUENCER_SUBMISSION_LATENCY, "sequencer_submission_latency"); + assert_const( + SEQUENCER_SUBMISSION_FAILURE_COUNT, + "sequencer_submission_failure_count", + ); + assert_const(TRANSACTIONS_PER_SUBMISSION, "transactions_per_submission"); + assert_const(BYTES_PER_SUBMISSION, "bytes_per_submission"); + } +} diff --git a/crates/astria-conductor/src/metrics_init.rs b/crates/astria-conductor/src/metrics_init.rs index d5da23a23..f0801c84a 100644 --- a/crates/astria-conductor/src/metrics_init.rs +++ b/crates/astria-conductor/src/metrics_init.rs @@ -7,6 +7,7 @@ use metrics::{ describe_histogram, Unit, }; +use telemetry::metric_name; pub(crate) const NAMESPACE_TYPE_LABEL: &str = "namespace_type"; pub(crate) const NAMESPACE_TYPE_METADATA: &str = "metadata"; @@ -58,31 +59,63 @@ pub fn register() { ); } -pub const BLOBS_PER_CELESTIA_FETCH: &str = - concat!(env!("CARGO_CRATE_NAME"), "_blobs_per_celestia_fetch",); +metric_name!(pub const BLOBS_PER_CELESTIA_FETCH); +metric_name!(pub const CELESTIA_BLOB_FETCH_ERROR_COUNT); +metric_name!(pub const DECODED_ITEMS_PER_CELESTIA_FETCH); +metric_name!(pub const SEQUENCER_BLOCKS_METADATA_VERIFIED_PER_CELESTIA_FETCH); +metric_name!(pub const SEQUENCER_BLOCK_INFORMATION_RECONSTRUCTED_PER_CELESTIA_FETCH); -pub const CELESTIA_BLOB_FETCH_ERROR_COUNT: &str = - concat!(env!("CARGO_CRATE_NAME"), "_celestia_blob_fetch_error_count"); +metric_name!(pub const EXECUTED_FIRM_BLOCK_NUMBER); +metric_name!(pub const EXECUTED_SOFT_BLOCK_NUMBER); +metric_name!(pub const TRANSACTIONS_PER_EXECUTED_BLOCK); -pub const DECODED_ITEMS_PER_CELESTIA_FETCH: &str = concat!( - env!("CARGO_CRATE_NAME"), - "_decoded_items_per_celestia_fetch", -); - -pub const SEQUENCER_BLOCKS_METADATA_VERIFIED_PER_CELESTIA_FETCH: &str = concat!( - env!("CARGO_CRATE_NAME"), - "_sequencer_blocks_metadata_verified_per_celestia_fetch", -); - -pub const SEQUENCER_BLOCK_INFORMATION_RECONSTRUCTED_PER_CELESTIA_FETCH: &str = concat!( - env!("CARGO_CRATE_NAME"), - "_sequencer_block_information_reconstructed_per_celestia_fetch", -); - -pub const EXECUTED_FIRM_BLOCK_NUMBER: &str = - concat!(env!("CARGO_CRATE_NAME"), "_executed_firm_block_number"); -pub const EXECUTED_SOFT_BLOCK_NUMBER: &str = - concat!(env!("CARGO_CRATE_NAME"), "_executed_soft_block_number"); - -pub const TRANSACTIONS_PER_EXECUTED_BLOCK: &str = - concat!(env!("CARGO_CRATE_NAME"), "_transactions_per_executed_block",); +#[cfg(test)] +mod tests { + use super::TRANSACTIONS_PER_EXECUTED_BLOCK; + use crate::metrics_init::{ + BLOBS_PER_CELESTIA_FETCH, + CELESTIA_BLOB_FETCH_ERROR_COUNT, + DECODED_ITEMS_PER_CELESTIA_FETCH, + EXECUTED_FIRM_BLOCK_NUMBER, + EXECUTED_SOFT_BLOCK_NUMBER, + SEQUENCER_BLOCKS_METADATA_VERIFIED_PER_CELESTIA_FETCH, + SEQUENCER_BLOCK_INFORMATION_RECONSTRUCTED_PER_CELESTIA_FETCH, + }; + + #[track_caller] + fn assert_const(actual: &'static str, suffix: &str) { + // XXX: hard-code this so the crate name isn't accidentally changed. + const CRATE_NAME: &str = "astria_conductor"; + let expected = format!("{CRATE_NAME}_{suffix}"); + assert_eq!(expected, actual); + } + + #[test] + fn metrics_are_as_expected() { + assert_const(BLOBS_PER_CELESTIA_FETCH, "blobs_per_celestia_fetch"); + assert_const( + CELESTIA_BLOB_FETCH_ERROR_COUNT, + "celestia_blob_fetch_error_count", + ); + assert_const( + DECODED_ITEMS_PER_CELESTIA_FETCH, + "decoded_items_per_celestia_fetch", + ); + + assert_const( + SEQUENCER_BLOCKS_METADATA_VERIFIED_PER_CELESTIA_FETCH, + "sequencer_blocks_metadata_verified_per_celestia_fetch", + ); + + assert_const( + SEQUENCER_BLOCK_INFORMATION_RECONSTRUCTED_PER_CELESTIA_FETCH, + "sequencer_block_information_reconstructed_per_celestia_fetch", + ); + assert_const(EXECUTED_FIRM_BLOCK_NUMBER, "executed_firm_block_number"); + assert_const(EXECUTED_SOFT_BLOCK_NUMBER, "executed_soft_block_number"); + assert_const( + TRANSACTIONS_PER_EXECUTED_BLOCK, + "transactions_per_executed_block", + ); + } +} diff --git a/crates/astria-sequencer-relayer/Cargo.toml b/crates/astria-sequencer-relayer/Cargo.toml index d74f75a0b..ee7a25ded 100644 --- a/crates/astria-sequencer-relayer/Cargo.toml +++ b/crates/astria-sequencer-relayer/Cargo.toml @@ -24,6 +24,7 @@ axum = { workspace = true } base64 = { workspace = true } base64-serde = { workspace = true } celestia-types = { workspace = true } +const_format = { workspace = true } futures = { workspace = true } hex = { workspace = true, features = ["serde"] } humantime = { workspace = true } @@ -43,6 +44,7 @@ thiserror = { workspace = true } tracing = { workspace = true } tryhard = { workspace = true } tokio = { workspace = true, features = ["macros", "rt-multi-thread", "signal"] } +tokio-stream = { workspace = true } tokio-util = { workspace = true } tonic = { workspace = true } @@ -61,8 +63,6 @@ sequencer-client = { package = "astria-sequencer-client", path = "../astria-sequ telemetry = { package = "astria-telemetry", path = "../astria-telemetry", features = [ "display", ] } -tokio-stream = { workspace = true } -const_format = "0.2.32" [dev-dependencies] astria-grpc-mock = { path = "../astria-grpc-mock" } diff --git a/crates/astria-sequencer-relayer/src/metrics_init.rs b/crates/astria-sequencer-relayer/src/metrics_init.rs index 52616b3b0..ab6ac9940 100644 --- a/crates/astria-sequencer-relayer/src/metrics_init.rs +++ b/crates/astria-sequencer-relayer/src/metrics_init.rs @@ -8,6 +8,7 @@ use metrics::{ describe_histogram, Unit, }; +use telemetry::metric_name; /// Registers all metrics used by this crate. pub fn register() { @@ -92,46 +93,72 @@ pub fn register() { // output, and may need to be updated over time. pub const HISTOGRAM_BUCKETS: &[f64; 5] = &[0.00001, 0.0001, 0.001, 0.01, 0.1]; -pub const CELESTIA_SUBMISSION_HEIGHT: &str = - concat!(env!("CARGO_CRATE_NAME"), "_celestia_submission_height"); - -pub const CELESTIA_SUBMISSION_COUNT: &str = - concat!(env!("CARGO_CRATE_NAME"), "_celestia_submission_count"); - -pub const CELESTIA_SUBMISSION_FAILURE_COUNT: &str = concat!( - env!("CARGO_CRATE_NAME"), - "_celestia_submission_failure_count" -); - -pub const BLOCKS_PER_CELESTIA_TX: &str = - concat!(env!("CARGO_CRATE_NAME"), "_blocks_per_celestia_tx"); - -pub const BLOBS_PER_CELESTIA_TX: &str = concat!(env!("CARGO_CRATE_NAME"), "_blobs_per_celestia_tx"); - -pub const BYTES_PER_CELESTIA_TX: &str = concat!(env!("CARGO_CRATE_NAME"), "_bytes_per_celestia_tx"); - -pub const CELESTIA_PAYLOAD_CREATION_LATENCY: &str = concat!( - env!("CARGO_CRATE_NAME"), - "_celestia_payload_creation_latency" -); - -pub const CELESTIA_SUBMISSION_LATENCY: &str = - concat!(env!("CARGO_CRATE_NAME"), "_celestia_submission_latency"); - -pub const SEQUENCER_BLOCK_FETCH_FAILURE_COUNT: &str = concat!( - env!("CARGO_CRATE_NAME"), - "_sequencer_block_fetch_failure_count", -); - -pub const SEQUENCER_HEIGHT_FETCH_FAILURE_COUNT: &str = concat!( - env!("CARGO_CRATE_NAME"), - "_sequencer_height_fetch_failure_count", -); - -pub const SEQUENCER_SUBMISSION_HEIGHT: &str = - concat!(env!("CARGO_CRATE_NAME"), "_sequencer_submission_height"); - -pub const COMPRESSION_RATIO_FOR_ASTRIA_BLOCK: &str = concat!( - env!("CARGO_CRATE_NAME"), - "_compression_ratio_for_astria_block" -); +metric_name!(pub const CELESTIA_SUBMISSION_HEIGHT); +metric_name!(pub const CELESTIA_SUBMISSION_COUNT); +metric_name!(pub const CELESTIA_SUBMISSION_FAILURE_COUNT); +metric_name!(pub const BLOCKS_PER_CELESTIA_TX); +metric_name!(pub const BLOBS_PER_CELESTIA_TX); +metric_name!(pub const BYTES_PER_CELESTIA_TX); +metric_name!(pub const CELESTIA_PAYLOAD_CREATION_LATENCY); +metric_name!(pub const CELESTIA_SUBMISSION_LATENCY); +metric_name!(pub const SEQUENCER_BLOCK_FETCH_FAILURE_COUNT); +metric_name!(pub const SEQUENCER_HEIGHT_FETCH_FAILURE_COUNT); +metric_name!(pub const SEQUENCER_SUBMISSION_HEIGHT); +metric_name!(pub const COMPRESSION_RATIO_FOR_ASTRIA_BLOCK); + +#[cfg(test)] +mod tests { + use super::{ + BLOBS_PER_CELESTIA_TX, + BLOCKS_PER_CELESTIA_TX, + BYTES_PER_CELESTIA_TX, + CELESTIA_PAYLOAD_CREATION_LATENCY, + CELESTIA_SUBMISSION_COUNT, + CELESTIA_SUBMISSION_FAILURE_COUNT, + CELESTIA_SUBMISSION_HEIGHT, + CELESTIA_SUBMISSION_LATENCY, + COMPRESSION_RATIO_FOR_ASTRIA_BLOCK, + SEQUENCER_BLOCK_FETCH_FAILURE_COUNT, + SEQUENCER_HEIGHT_FETCH_FAILURE_COUNT, + SEQUENCER_SUBMISSION_HEIGHT, + }; + + #[track_caller] + fn assert_const(actual: &'static str, suffix: &str) { + // XXX: hard-code this so the crate name isn't accidentally changed. + const CRATE_NAME: &str = "astria_sequencer_relayer"; + let expected = format!("{CRATE_NAME}_{suffix}"); + assert_eq!(expected, actual); + } + + #[test] + fn metrics_are_as_expected() { + assert_const(CELESTIA_SUBMISSION_HEIGHT, "celestia_submission_height"); + assert_const(CELESTIA_SUBMISSION_COUNT, "celestia_submission_count"); + assert_const( + CELESTIA_SUBMISSION_FAILURE_COUNT, + "celestia_submission_failure_count", + ); + assert_const(BLOCKS_PER_CELESTIA_TX, "blocks_per_celestia_tx"); + assert_const(BLOBS_PER_CELESTIA_TX, "blobs_per_celestia_tx"); + assert_const(BYTES_PER_CELESTIA_TX, "bytes_per_celestia_tx"); + assert_const( + CELESTIA_PAYLOAD_CREATION_LATENCY, + "celestia_payload_creation_latency", + ); + assert_const(CELESTIA_SUBMISSION_LATENCY, "celestia_submission_latency"); + assert_const( + SEQUENCER_BLOCK_FETCH_FAILURE_COUNT, + "sequencer_block_fetch_failure_count", + ); + assert_const( + SEQUENCER_HEIGHT_FETCH_FAILURE_COUNT, + "sequencer_height_fetch_failure_count", + ); + assert_const(SEQUENCER_SUBMISSION_HEIGHT, "sequencer_submission_height"); + assert_const( + COMPRESSION_RATIO_FOR_ASTRIA_BLOCK, + "compression_ratio_for_astria_block", + ); + } +} diff --git a/crates/astria-sequencer/src/metrics_init.rs b/crates/astria-sequencer/src/metrics_init.rs index b2c369cba..777ce1833 100644 --- a/crates/astria-sequencer/src/metrics_init.rs +++ b/crates/astria-sequencer/src/metrics_init.rs @@ -8,6 +8,7 @@ use metrics::{ describe_histogram, Unit, }; +use telemetry::metric_name; /// Registers all metrics used by this crate. pub fn register() { @@ -89,52 +90,81 @@ pub fn register() { ); } -pub const PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS_DECODE_FAILURE: &str = concat!( - env!("CARGO_CRATE_NAME"), - "_prepare_proposal_excluded_transactions_decode_failure" -); - -pub const PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS_COMETBFT_SPACE: &str = concat!( - env!("CARGO_CRATE_NAME"), - "_prepare_proposal_excluded_transactions_cometbft_space" -); - -pub const PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS_SEQUENCER_SPACE: &str = concat!( - env!("CARGO_CRATE_NAME"), - "_prepare_proposal_excluded_transactions_sequencer_space" -); - -pub const PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS_FAILED_EXECUTION: &str = concat!( - env!("CARGO_CRATE_NAME"), - "_prepare_proposal_excluded_transactions_failed_execution" -); - -pub const PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS: &str = concat!( - env!("CARGO_CRATE_NAME"), - "_prepare_proposal_excluded_transactions" -); - -pub const PROPOSAL_DEPOSITS: &str = concat!(env!("CARGO_CRATE_NAME"), "_proposal_deposits"); - -pub const PROPOSAL_TRANSACTIONS: &str = concat!(env!("CARGO_CRATE_NAME"), "_proposal_transactions"); - -pub const PROCESS_PROPOSAL_SKIPPED_PROPOSAL: &str = concat!( - env!("CARGO_CRATE_NAME"), - "_process_proposal_skipped_proposal" -); - -pub const CHECK_TX_REMOVED_TOO_LARGE: &str = - concat!(env!("CARGO_CRATE_NAME"), "_check_tx_removed_too_large"); - -pub const CHECK_TX_REMOVED_FAILED_STATELESS: &str = concat!( - env!("CARGO_CRATE_NAME"), - "_check_tx_removed_failed_stateless" -); - -pub const CHECK_TX_REMOVED_STALE_NONCE: &str = - concat!(env!("CARGO_CRATE_NAME"), "_check_tx_removed_stale_nonce"); - -pub const CHECK_TX_REMOVED_ACCOUNT_BALANCE: &str = concat!( - env!("CARGO_CRATE_NAME"), - "_check_tx_removed_account_balance" -); +metric_name!(pub const PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS_DECODE_FAILURE); +metric_name!(pub const PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS_COMETBFT_SPACE); +metric_name!(pub const PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS_SEQUENCER_SPACE); +metric_name!(pub const PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS_FAILED_EXECUTION); +metric_name!(pub const PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS); +metric_name!(pub const PROPOSAL_DEPOSITS); +metric_name!(pub const PROPOSAL_TRANSACTIONS); +metric_name!(pub const PROCESS_PROPOSAL_SKIPPED_PROPOSAL); +metric_name!(pub const CHECK_TX_REMOVED_TOO_LARGE); +metric_name!(pub const CHECK_TX_REMOVED_FAILED_STATELESS); +metric_name!(pub const CHECK_TX_REMOVED_STALE_NONCE); +metric_name!(pub const CHECK_TX_REMOVED_ACCOUNT_BALANCE); + +#[cfg(test)] +mod tests { + use super::{ + CHECK_TX_REMOVED_ACCOUNT_BALANCE, + CHECK_TX_REMOVED_FAILED_STATELESS, + CHECK_TX_REMOVED_STALE_NONCE, + CHECK_TX_REMOVED_TOO_LARGE, + PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS, + PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS_COMETBFT_SPACE, + PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS_DECODE_FAILURE, + PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS_FAILED_EXECUTION, + PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS_SEQUENCER_SPACE, + PROCESS_PROPOSAL_SKIPPED_PROPOSAL, + PROPOSAL_DEPOSITS, + PROPOSAL_TRANSACTIONS, + }; + + #[track_caller] + fn assert_const(actual: &'static str, suffix: &str) { + // XXX: hard-code this so the crate name isn't accidentally changed. + const CRATE_NAME: &str = "astria_sequencer"; + let expected = format!("{CRATE_NAME}_{suffix}"); + assert_eq!(expected, actual); + } + + #[test] + fn metrics_are_as_expected() { + assert_const( + PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS_DECODE_FAILURE, + "prepare_proposal_excluded_transactions_decode_failure", + ); + assert_const( + PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS_COMETBFT_SPACE, + "prepare_proposal_excluded_transactions_cometbft_space", + ); + assert_const( + PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS_SEQUENCER_SPACE, + "prepare_proposal_excluded_transactions_sequencer_space", + ); + assert_const( + PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS_FAILED_EXECUTION, + "prepare_proposal_excluded_transactions_failed_execution", + ); + assert_const( + PREPARE_PROPOSAL_EXCLUDED_TRANSACTIONS, + "prepare_proposal_excluded_transactions", + ); + assert_const(PROPOSAL_DEPOSITS, "proposal_deposits"); + assert_const(PROPOSAL_TRANSACTIONS, "proposal_transactions"); + assert_const( + PROCESS_PROPOSAL_SKIPPED_PROPOSAL, + "process_proposal_skipped_proposal", + ); + assert_const(CHECK_TX_REMOVED_TOO_LARGE, "check_tx_removed_too_large"); + assert_const( + CHECK_TX_REMOVED_FAILED_STATELESS, + "check_tx_removed_failed_stateless", + ); + assert_const(CHECK_TX_REMOVED_STALE_NONCE, "check_tx_removed_stale_nonce"); + assert_const( + CHECK_TX_REMOVED_ACCOUNT_BALANCE, + "check_tx_removed_account_balance", + ); + } +} diff --git a/crates/astria-telemetry/Cargo.toml b/crates/astria-telemetry/Cargo.toml index ec2d3ec51..aaec8de6f 100644 --- a/crates/astria-telemetry/Cargo.toml +++ b/crates/astria-telemetry/Cargo.toml @@ -13,6 +13,7 @@ homepage = "https://astria.org" [dependencies] base64 = { workspace = true, optional = true } base64-serde = { workspace = true, optional = true } +const_format = { workspace = true } metrics-exporter-prometheus = { version = "0.13.1", default-features = false, features = [ "http-listener", diff --git a/crates/astria-telemetry/src/lib.rs b/crates/astria-telemetry/src/lib.rs index bebbfdec6..6226e7122 100644 --- a/crates/astria-telemetry/src/lib.rs +++ b/crates/astria-telemetry/src/lib.rs @@ -45,6 +45,9 @@ use tracing_subscriber::{ #[cfg(feature = "display")] pub mod display; +#[doc(hidden)] +pub mod macros; + /// The errors that can occur when initializing telemetry. #[derive(Debug, thiserror::Error)] #[error(transparent)] diff --git a/crates/astria-telemetry/src/macros.rs b/crates/astria-telemetry/src/macros.rs new file mode 100644 index 000000000..f5799f0a5 --- /dev/null +++ b/crates/astria-telemetry/src/macros.rs @@ -0,0 +1,58 @@ +// re-export so that they need not be imported by downstream users. +// hidden because they shouldn't be imported. +#[doc(hidden)] +pub use const_format::{ + concatcp as __concatcp, + map_ascii_case as __map_ascii_case, + Case as __Case, +}; + +/// Declare a `const` string slice, using the declaring crate's name as a +/// prefix and the variable name as a suffix. +/// +/// This macro essentially performs this declaration: +/// ```text +/// METRIC_NAME := ${CARGO_CRATE_NAME}_metric_name; +/// ``` +/// +/// The purpose of this macro is to avoid accidental typos, ensuring that the +/// metric name matches the const variable name. +/// +/// # Examples +/// ``` +/// use astria_telemetry::metric_name; +/// metric_name!(pub const EXAMPLE_COUNTER); +/// // Note that this example has `astria_telemetry` a a prefix because +/// // this doctest is part of this crate. +/// // In your case, use your crate's `CARGO_CRATE_NAME` as prefix. +/// assert_eq!(EXAMPLE_COUNTER, "astria_telemetry_example_counter"); +/// ``` +#[macro_export] +macro_rules! metric_name { + ($vis:vis const $($tt:tt)*) => { + $crate::__metric_name_internal!( + $vis [$($tt)*] [::core::stringify!($($tt)*)] + ); + } +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __metric_name_internal { + ($vis:vis [$name:ident][$suffix:expr]) => { + $vis const $name: &str = $crate::macros::__concatcp!( + ::core::env!("CARGO_CRATE_NAME"), + "_", + $crate::macros::__map_ascii_case!($crate::macros::__Case::Lower, $suffix), + ); + }; +} + +#[cfg(test)] +mod tests { + #[test] + fn gives_expected_const_and_value() { + crate::metric_name!(const EXAMPLE_CONST); + assert_eq!("astria_telemetry_example_const", EXAMPLE_CONST); + } +}