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

feat(l2): custom dashboard #1539

Open
wants to merge 4 commits into
base: core/prometheus_grafana
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion cmd/ethrex/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ path = "./ethrex.rs"
[features]
default = ["dep:ethrex-storage", "libmdbx"]
dev = ["dep:ethrex-dev"]
metrics = ["ethrex-blockchain/metrics"]
metrics = ["ethrex-blockchain/metrics", "ethrex-l2/metrics"]
libmdbx = ["dep:libmdbx", "ethrex-storage/libmdbx"]
redb = ["dep:redb", "ethrex-storage/redb"]
l2 = ["ethrex-vm/l2"]
Expand Down
2 changes: 1 addition & 1 deletion crates/blockchain/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ default = ["c-kzg"]
libmdbx = ["ethrex-core/libmdbx", "ethrex-storage/default", "ethrex-vm/libmdbx"]
levm = ["ethrex-vm/levm"]
c-kzg = ["ethrex-core/c-kzg"]
metrics = ["ethrex-metrics/api"]
metrics = ["ethrex-metrics/transactions"]
2 changes: 2 additions & 0 deletions crates/blockchain/metrics/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,5 @@ path = "./mod.rs"
[features]
default = ["api"]
api = []
transactions = []
l2 = []
26 changes: 25 additions & 1 deletion crates/blockchain/metrics/api.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use axum::{routing::get, Router};

#[cfg(feature = "l2")]
use crate::metrics_l2::METRICS_L2;

use crate::{metrics_transactions::METRICS_TX, MetricsApiError};

pub async fn start_prometheus_metrics_api(port: String) -> Result<(), MetricsApiError> {
Expand All @@ -14,6 +17,27 @@ pub async fn start_prometheus_metrics_api(port: String) -> Result<(), MetricsApi
Ok(())
}

#[allow(unused_mut)]
async fn get_metrics() -> String {
METRICS_TX.gather_metrics()
let mut ret_string = match METRICS_TX.gather_metrics() {
Ok(string) => string,
Err(_) => {
tracing::error!("Failed to register METRICS_TX");
String::new()
}
};

#[cfg(feature = "l2")]
{
ret_string.push('\n');
match METRICS_L2.gather_metrics() {
Ok(string) => ret_string.push_str(&string),
Err(_) => {
tracing::error!("Failed to register METRICS_L2");
return String::new();
}
}
}

ret_string
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ services:
grafana:
ports:
- "3801:3000"
volumes:
- type: bind
source: ../metrics/provisioning/grafana_provisioning/dashboards/dashboard_config_l1.yaml
target: /etc/grafana/provisioning/dashboards/dashboard.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ services:
grafana:
ports:
- "3802:3000"
volumes:
- ../metrics/provisioning/grafana_provisioning/dashboards/l2_dashboards:/etc/grafana/provisioning/dashboards/l2_dashboards
- ../metrics/provisioning/grafana_provisioning/dashboards/dashboard_config_l2.yaml:/etc/grafana/provisioning/dashboards/dashboard.yaml
2 changes: 1 addition & 1 deletion crates/blockchain/metrics/docker-compose-metrics.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ services:
grafana:
image: grafana/grafana
volumes:
- ./provisioning/grafana_provisioning/dashboards:/etc/grafana/provisioning/dashboards
- ./provisioning/grafana_provisioning/dashboards/common_dashboards:/etc/grafana/provisioning/dashboards/common_dashboards
- ./provisioning/grafana_provisioning/datasources:/etc/grafana/provisioning/datasources
#ports: defined in the .overrides file
depends_on:
Expand Down
97 changes: 97 additions & 0 deletions crates/blockchain/metrics/metrics_l2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use prometheus::{Encoder, IntGaugeVec, Opts, Registry, TextEncoder};
use std::sync::{Arc, LazyLock, Mutex};

use crate::MetricsError;

pub static METRICS_L2: LazyLock<MetricsL2> = LazyLock::new(MetricsL2::default);

pub struct MetricsL2 {
pub status_tracker: Arc<Mutex<IntGaugeVec>>,
}

impl Default for MetricsL2 {
fn default() -> Self {
Self::new()
}
}

impl MetricsL2 {
pub fn new() -> Self {
MetricsL2 {
status_tracker: Arc::new(Mutex::new(
IntGaugeVec::new(
Opts::new(
"l2_blocks_tracker",
"Keeps track of the L2's status based on the L1's contracts",
),
&["block_type"],
)
.unwrap(),
)),
}
}

pub fn set_block_type_and_block_number(
&self,
block_type: MetricsL2BlockType,
block_number: u64,
) -> Result<(), MetricsError> {
let clone = self.status_tracker.clone();

let lock = clone
.lock()
.map_err(|e| MetricsError::MutexLockError(e.to_string()))?;

let builder = lock
.get_metric_with_label_values(&[block_type.to_str()])
.map_err(|e| MetricsError::PrometheusErr(e.to_string()))?;
let block_number_as_i64: i64 = block_number.try_into()?;

builder.set(block_number_as_i64);

Ok(())
}

pub fn gather_metrics(&self) -> Result<String, MetricsError> {
let r = Registry::new();

let clone = self.status_tracker.clone();

let lock = clone
.lock()
.map_err(|e| MetricsError::MutexLockError(e.to_string()))?;

r.register(Box::new(lock.clone()))
.map_err(|e| MetricsError::PrometheusErr(e.to_string()))?;

let encoder = TextEncoder::new();
let metric_families = r.gather();

let mut buffer = Vec::new();
encoder
.encode(&metric_families, &mut buffer)
.map_err(|e| MetricsError::PrometheusErr(e.to_string()))?;

let res = String::from_utf8(buffer)?;

Ok(res)
}
}

/// [MetricsL2BlockType::LastCommittedBlock] and [MetricsL2BlockType::LastVerifiedBlock] Matche the crates/l2/contracts/src/l1/OnChainProposer.sol variables
/// [MetricsL2BlockType::LastFetchedL1Block] Matches the variable in crates/l2/contracts/src/l1/CommonBridge.sol
pub enum MetricsL2BlockType {
LastCommittedBlock,
LastVerifiedBlock,
LastFetchedL1Block,
}

impl MetricsL2BlockType {
pub fn to_str(&self) -> &str {
match self {
MetricsL2BlockType::LastCommittedBlock => "lastCommittedBlock",
MetricsL2BlockType::LastVerifiedBlock => "lastVerifiedBlock",
MetricsL2BlockType::LastFetchedL1Block => "lastFetchedL1Block",
}
}
}
50 changes: 19 additions & 31 deletions crates/blockchain/metrics/metrics_transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use ethrex_core::types::TxType;
use prometheus::{Encoder, IntCounter, IntCounterVec, Opts, Registry, TextEncoder};
use std::sync::{Arc, LazyLock, Mutex};

use crate::MetricsError;

pub static METRICS_TX: LazyLock<MetricsTx> = LazyLock::new(MetricsTx::default);

pub struct MetricsTx {
Expand Down Expand Up @@ -71,49 +73,35 @@ impl MetricsTx {
txs_lock.inc();
}

pub fn gather_metrics(&self) -> String {
pub fn gather_metrics(&self) -> Result<String, MetricsError> {
let r = Registry::new();

let txs_tracker = self.transactions_tracker.clone();
let txs_tracker_lock = match txs_tracker.lock() {
Ok(lock) => lock,
Err(e) => {
tracing::error!("Failed to lock transactions_tracker mutex: {e}");
return String::new();
}
};
let txs_tracker_lock = txs_tracker
.lock()
.map_err(|e| MetricsError::MutexLockError(e.to_string()))?;

let txs_lock = self.transactions_total.clone();
let txs_lock = match txs_lock.lock() {
Ok(lock) => lock,
Err(e) => {
tracing::error!("Failed to lock transactions_total mutex: {e}");
return String::new();
}
};
let txs_lock = txs_lock
.lock()
.map_err(|e| MetricsError::MutexLockError(e.to_string()))?;

if r.register(Box::new(txs_lock.clone())).is_err() {
tracing::error!("Failed to register metric");
return String::new();
}
if r.register(Box::new(txs_tracker_lock.clone())).is_err() {
tracing::error!("Failed to register metric");
return String::new();
}
r.register(Box::new(txs_lock.clone()))
.map_err(|e| MetricsError::PrometheusErr(e.to_string()))?;
r.register(Box::new(txs_tracker_lock.clone()))
.map_err(|e| MetricsError::PrometheusErr(e.to_string()))?;

let encoder = TextEncoder::new();
let metric_families = r.gather();

let mut buffer = Vec::new();
if encoder.encode(&metric_families, &mut buffer).is_err() {
tracing::error!("Failed to encode metrics");
return String::new();
}
encoder
.encode(&metric_families, &mut buffer)
.map_err(|e| MetricsError::PrometheusErr(e.to_string()))?;

let res = String::from_utf8(buffer)?;

String::from_utf8(buffer).unwrap_or_else(|e| {
tracing::error!("Failed to convert buffer to String: {e}");
String::new()
})
Ok(res)
}
}

Expand Down
18 changes: 16 additions & 2 deletions crates/blockchain/metrics/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#[cfg(feature = "api")]
pub mod api;
#[cfg(feature = "api")]
#[cfg(any(feature = "api", feature = "l2"))]
pub mod metrics_l2;
#[cfg(any(feature = "api", feature = "transactions"))]
pub mod metrics_transactions;

/// A macro to conditionally enable metrics-related code.
Expand All @@ -22,7 +24,7 @@ pub mod metrics_transactions;
/// ```toml
/// ethrex-metrics = { path = "./metrics", default-features = false }
/// [features]
/// metrics = ["ethrex-metrics/api"]
/// metrics = ["ethrex-metrics/transactions"]
/// ```
///
/// In this way, when the `metrics` feature is enabled for that crate, the macro is triggered and the metrics_api is also used.
Expand Down Expand Up @@ -52,3 +54,15 @@ pub enum MetricsApiError {
#[error("{0}")]
TcpError(#[from] std::io::Error),
}

#[derive(Debug, thiserror::Error)]
pub enum MetricsError {
#[error("MetricsL2Error: {0}")]
MutexLockError(String),
#[error("MetricsL2Error: {0}")]
PrometheusErr(String),
#[error("MetricsL2Error {0}")]
TryInto(#[from] std::num::TryFromIntError),
#[error("MetricsL2Error {0}")]
FromUtf8Error(#[from] std::string::FromUtf8Error),
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
apiVersion: 1

providers:
- name: "Custom Prometheus Dashboards"
- name: "Ethrex Common Dashboards"
orgId: 1
folder: ""
type: file
disableDeletion: true
editable: true
options:
path: /etc/grafana/provisioning/dashboards/demo_dashboards
path: /etc/grafana/provisioning/dashboards/common_dashboards
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: 1

providers:
- name: "Ethrex Common Dashboards"
orgId: 1
folder: ""
type: file
disableDeletion: true
editable: true
options:
path: /etc/grafana/provisioning/dashboards/common_dashboards

- name: "EthrexL2 Dashboards"
orgId: 1
folder: ""
type: file
disableDeletion: true
editable: true
options:
path: /etc/grafana/provisioning/dashboards/l2_dashboards
Loading
Loading