Skip to content

Commit

Permalink
refactor: move tracing and metric enum to their modules (#1060)
Browse files Browse the repository at this point in the history
  • Loading branch information
dinhani-cw authored Jun 10, 2024
1 parent b6df5b9 commit feba059
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 76 deletions.
74 changes: 5 additions & 69 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,11 @@ use crate::eth::Executor;
use crate::eth::TransactionRelayer;
use crate::ext::binary_name;
use crate::ext::parse_duration;
#[cfg(feature = "metrics")]
use crate::infra::metrics::MetricsHistogramKind;
use crate::infra::tracing::info_task_spawn;
use crate::infra::tracing::warn_task_tx_closed;
use crate::infra::tracing::TracingLogFormat;
use crate::infra::BlockchainClient;
use crate::GlobalState;

Expand Down Expand Up @@ -85,6 +88,7 @@ pub struct CommonConfig {
#[arg(long = "metrics-exporter-address", env = "METRICS_EXPORTER_ADDRESS", default_value = "0.0.0.0:9000")]
pub metrics_exporter_address: SocketAddr,

#[cfg(feature = "metrics")]
/// Metrics histograms will be collected using summaries or histograms (buckets)?
#[arg(long = "metrics-histogram-kind", env = "METRICS_HISTOGRAM_KIND", default_value = "summary")]
pub metrics_histogram_kind: MetricsHistogramKind,
Expand All @@ -99,7 +103,7 @@ pub struct CommonConfig {

/// How tracing events will be formatted.
#[arg(long = "log-format", env = "LOG_FORMAT", default_value = "normal")]
pub log_format: LogFormat,
pub log_format: TracingLogFormat,

/// Sentry URL where error events will be pushed.
#[arg(long = "sentry-url", env = "SENTRY_URL")]
Expand Down Expand Up @@ -890,74 +894,6 @@ impl FromStr for PermanentStorageKind {
}
}

// -----------------------------------------------------------------------------
// Enum: LogFormat
// -----------------------------------------------------------------------------

/// Tracing event log format.
#[derive(DebugAsJson, strum::Display, Clone, Copy, Eq, PartialEq, serde::Serialize)]
pub enum LogFormat {
/// Minimal format: Time (no date), level, and message.
#[strum(to_string = "minimal")]
Minimal,

/// Normal format: Default `tracing` crate configuration.
#[strum(to_string = "normal")]
Normal,

/// Verbose format: Full datetime, level, thread, target, and message.
#[strum(to_string = "verbose")]
Verbose,

/// JSON format: Verbose information formatted as JSON.
#[strum(to_string = "json")]
Json,
}

impl FromStr for LogFormat {
type Err = anyhow::Error;

fn from_str(s: &str) -> anyhow::Result<Self, Self::Err> {
match s.to_lowercase().trim() {
"json" => Ok(Self::Json),
"minimal" => Ok(Self::Minimal),
"normal" => Ok(Self::Normal),
"verbose" | "full" => Ok(Self::Verbose),
s => Err(anyhow!("unknown log format: {}", s)),
}
}
}

// -----------------------------------------------------------------------------
// Enum: MetricsHistogramKind
// -----------------------------------------------------------------------------

/// See: <https://prometheus.io/docs/practices/histograms/>
#[derive(DebugAsJson, Clone, Copy, Eq, PartialEq, serde::Serialize)]
pub enum MetricsHistogramKind {
/// Quantiles are calculated on client-side based on recent data kept in-memory.
///
/// Client defines the quantiles to calculate.
Summary,

/// Quantiles are calculated on server-side based on bucket counts.
///
/// Cient defines buckets to group observations.
Histogram,
}

impl FromStr for MetricsHistogramKind {
type Err = anyhow::Error;

fn from_str(s: &str) -> anyhow::Result<Self, Self::Err> {
match s.to_lowercase().trim() {
"summary" => Ok(Self::Summary),
"histogram" => Ok(Self::Histogram),
s => Err(anyhow!("unknown metrics histogram kind: {}", s)),
}
}
}

// -----------------------------------------------------------------------------
// Enum: ValidatorMethodConfig
// -----------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion src/infra/metrics/metrics_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use std::stringify;
use metrics_exporter_prometheus::Matcher;
use metrics_exporter_prometheus::PrometheusBuilder;

use crate::config::MetricsHistogramKind;
use crate::infra::metrics::metrics_for_consensus;
use crate::infra::metrics::metrics_for_evm;
use crate::infra::metrics::metrics_for_executor;
Expand All @@ -17,6 +16,7 @@ use crate::infra::metrics::metrics_for_json_rpc;
use crate::infra::metrics::metrics_for_rocks;
use crate::infra::metrics::metrics_for_storage_read;
use crate::infra::metrics::metrics_for_storage_write;
use crate::infra::metrics::MetricsHistogramKind;

/// Default bucket for duration based metrics.
const BUCKET_FOR_DURATION: [f64; 37] = [
Expand Down
41 changes: 41 additions & 0 deletions src/infra/metrics/metrics_types.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
use std::borrow::Cow;
use std::str::FromStr;

use anyhow::anyhow;
use display_json::DebugAsJson;
use metrics::describe_counter;
use metrics::describe_gauge;
use metrics::describe_histogram;
use metrics::Label;

use crate::ext::not;

// -----------------------------------------------------------------------------
// Metric
// -----------------------------------------------------------------------------

/// Metric definition.
pub(super) struct Metric {
pub(super) kind: &'static str,
Expand All @@ -32,6 +39,10 @@ impl Metric {
}
}

// -----------------------------------------------------------------------------
// MetricLabelValue
// -----------------------------------------------------------------------------

/// Representation of a metric label value.
///
/// It exists to improve two aspects `metrics` crate does not cover:
Expand Down Expand Up @@ -91,3 +102,33 @@ pub(super) fn into_labels(labels: Vec<(&'static str, MetricLabelValue)>) -> Vec<
.map(|(key, value)| Label::new(key, value))
.collect()
}

// -----------------------------------------------------------------------------
// MetricsHistogramKind
// -----------------------------------------------------------------------------

/// See: <https://prometheus.io/docs/practices/histograms/>
#[derive(DebugAsJson, Clone, Copy, Eq, PartialEq, serde::Serialize)]
pub enum MetricsHistogramKind {
/// Quantiles are calculated on client-side based on recent data kept in-memory.
///
/// Client defines the quantiles to calculate.
Summary,

/// Quantiles are calculated on server-side based on bucket counts.
///
/// Cient defines buckets to group observations.
Histogram,
}

impl FromStr for MetricsHistogramKind {
type Err = anyhow::Error;

fn from_str(s: &str) -> anyhow::Result<Self, Self::Err> {
match s.to_lowercase().trim() {
"summary" => Ok(Self::Summary),
"histogram" => Ok(Self::Histogram),
s => Err(anyhow!("unknown metrics histogram kind: {}", s)),
}
}
}
52 changes: 46 additions & 6 deletions src/infra/tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
use std::io::stdout;
use std::io::IsTerminal;
use std::net::SocketAddr;
use std::str::FromStr;

use anyhow::anyhow;
use chrono::Local;
use console_subscriber::ConsoleLayer;
use display_json::DebugAsJson;
use opentelemetry::KeyValue;
use opentelemetry_otlp::WithExportConfig;
use opentelemetry_sdk::runtime;
Expand All @@ -18,13 +21,12 @@ use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::EnvFilter;
use tracing_subscriber::Layer;

use crate::config::LogFormat;
use crate::ext::binary_name;
use crate::ext::named_spawn;

/// Init application tracing.
pub async fn init_tracing(
log_format: LogFormat,
log_format: TracingLogFormat,
opentelemetry_url: Option<&str>,
sentry_url: Option<&str>,
tokio_console_address: SocketAddr,
Expand All @@ -36,23 +38,23 @@ pub async fn init_tracing(

println!("tracing registry: enabling console logs | format={} ansi={}", log_format, enable_ansi);
let stdout_layer = match log_format {
LogFormat::Json => fmt::Layer::default()
TracingLogFormat::Json => fmt::Layer::default()
.json()
.with_target(true)
.with_thread_ids(true)
.with_thread_names(true)
.with_filter(EnvFilter::from_default_env())
.boxed(),
LogFormat::Minimal => fmt::Layer::default()
TracingLogFormat::Minimal => fmt::Layer::default()
.with_thread_ids(false)
.with_thread_names(false)
.with_target(false)
.with_ansi(enable_ansi)
.with_timer(MinimalTimer)
.with_filter(EnvFilter::from_default_env())
.boxed(),
LogFormat::Normal => fmt::Layer::default().with_ansi(enable_ansi).with_filter(EnvFilter::from_default_env()).boxed(),
LogFormat::Verbose => fmt::Layer::default()
TracingLogFormat::Normal => fmt::Layer::default().with_ansi(enable_ansi).with_filter(EnvFilter::from_default_env()).boxed(),
TracingLogFormat::Verbose => fmt::Layer::default()
.with_ansi(enable_ansi)
.with_target(true)
.with_thread_ids(true)
Expand Down Expand Up @@ -127,6 +129,44 @@ pub async fn init_tracing(
}
}

// -----------------------------------------------------------------------------
// Tracing types
// -----------------------------------------------------------------------------

/// Tracing event log format.
#[derive(DebugAsJson, strum::Display, Clone, Copy, Eq, PartialEq, serde::Serialize)]
pub enum TracingLogFormat {
/// Minimal format: Time (no date), level, and message.
#[strum(to_string = "minimal")]
Minimal,

/// Normal format: Default `tracing` crate configuration.
#[strum(to_string = "normal")]
Normal,

/// Verbose format: Full datetime, level, thread, target, and message.
#[strum(to_string = "verbose")]
Verbose,

/// JSON format: Verbose information formatted as JSON.
#[strum(to_string = "json")]
Json,
}

impl FromStr for TracingLogFormat {
type Err = anyhow::Error;

fn from_str(s: &str) -> anyhow::Result<Self, Self::Err> {
match s.to_lowercase().trim() {
"json" => Ok(Self::Json),
"minimal" => Ok(Self::Minimal),
"normal" => Ok(Self::Normal),
"verbose" | "full" => Ok(Self::Verbose),
s => Err(anyhow!("unknown log format: {}", s)),
}
}
}

struct MinimalTimer;

impl FormatTime for MinimalTimer {
Expand Down

0 comments on commit feba059

Please sign in to comment.