mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-08-05 20:43:14 +00:00
feat(dashboard_gen): make unit an enum
This commit is contained in:
parent
ea36fa2e93
commit
ec53979442
@ -10,7 +10,7 @@
|
||||
)]
|
||||
|
||||
use dashboard_gen::{
|
||||
Color, Dashboard, FieldOverride, Panel, Target, avg, percentiles, percentiles_labeled,
|
||||
Color, Dashboard, FieldOverride, Panel, Target, Unit, avg, percentiles, percentiles_labeled,
|
||||
rate_per_min,
|
||||
};
|
||||
use json_pretty_compact::PrettyCompactFormatter;
|
||||
@ -26,7 +26,7 @@ fn sequencer_dashboard() -> Dashboard {
|
||||
[
|
||||
Panel::stat("Chain height")
|
||||
.width(6)
|
||||
.unit("short")
|
||||
.unit(Unit::Short)
|
||||
.decimals(0)
|
||||
.color(Color::fixed("blue"))
|
||||
.target(
|
||||
@ -34,7 +34,7 @@ fn sequencer_dashboard() -> Dashboard {
|
||||
),
|
||||
Panel::timeseries("Block production rate")
|
||||
.width(18)
|
||||
.unit("short")
|
||||
.unit(Unit::Short)
|
||||
.target(rate_per_min(
|
||||
sequencer_core_metrics::names::BLOCK_COUNT,
|
||||
"blocks/min",
|
||||
@ -45,7 +45,7 @@ fn sequencer_dashboard() -> Dashboard {
|
||||
9,
|
||||
[Panel::timeseries("Block creation time")
|
||||
.width(24)
|
||||
.unit("s")
|
||||
.unit(Unit::Seconds)
|
||||
.targets(percentiles(
|
||||
sequencer_core_metrics::names::BLOCK_CREATION_TIME,
|
||||
PERCENTILES,
|
||||
@ -62,7 +62,7 @@ fn sequencer_dashboard() -> Dashboard {
|
||||
[
|
||||
Panel::timeseries("Transaction application time")
|
||||
.width(12)
|
||||
.unit("s")
|
||||
.unit(Unit::Seconds)
|
||||
.targets(percentiles_labeled(
|
||||
sequencer_core_metrics::names::MEMPOOL_TRANSACTION_APPLICATION_TIME,
|
||||
PERCENTILES,
|
||||
@ -70,7 +70,7 @@ fn sequencer_dashboard() -> Dashboard {
|
||||
)),
|
||||
Panel::timeseries("Mempool size")
|
||||
.width(12)
|
||||
.unit("short")
|
||||
.unit(Unit::Short)
|
||||
.span_nulls()
|
||||
.target(
|
||||
Target::new(sequencer_core_metrics::names::MEMPOOL_SIZE)
|
||||
@ -83,7 +83,7 @@ fn sequencer_dashboard() -> Dashboard {
|
||||
[
|
||||
Panel::timeseries("Transactions per block")
|
||||
.width(12)
|
||||
.unit("short")
|
||||
.unit(Unit::Short)
|
||||
.targets(percentiles(
|
||||
sequencer_core_metrics::names::TRANSACTIONS_PER_BLOCK,
|
||||
PERCENTILES,
|
||||
@ -96,7 +96,7 @@ fn sequencer_dashboard() -> Dashboard {
|
||||
),
|
||||
Panel::timeseries("Transaction throughput (per minute)")
|
||||
.width(12)
|
||||
.unit("short")
|
||||
.unit(Unit::Short)
|
||||
.target(rate_per_min(
|
||||
sequencer_service_metrics::names::SUBMITTED_TRANSACTION_COUNT,
|
||||
"submitted",
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
use std::fmt::Write as _;
|
||||
|
||||
use crate::{
|
||||
Unit,
|
||||
input::PanelInput,
|
||||
schema::{
|
||||
AxisPlacement, Color, GradientMode, LineInterpolation, PanelType, ShowPoints, StackingMode,
|
||||
@ -38,7 +39,11 @@ fn panel_expr_inner(panel: &PanelInput) -> Result<String, std::fmt::Error> {
|
||||
let defaults = &panel.field_config.defaults;
|
||||
// `short` is the builder's own default unit, so it round-trips without a call.
|
||||
if let Some(unit) = defaults.unit.as_deref().filter(|u| *u != "short") {
|
||||
write!(expr, "\n .unit({unit:?})")?;
|
||||
write!(
|
||||
expr,
|
||||
"\n .unit({})",
|
||||
Unit::from_id(unit).to_rust_source()
|
||||
)?;
|
||||
}
|
||||
if let Some(decimals) = defaults.decimals {
|
||||
write!(expr, "\n .decimals({decimals})")?;
|
||||
|
||||
@ -22,11 +22,13 @@ use schema::{
|
||||
Stacking, StatColorMode, StatOptions, TimeRange, TimeSeriesOptions, Tooltip, TooltipMode,
|
||||
};
|
||||
use serde::Serialize;
|
||||
pub use unit::Unit;
|
||||
|
||||
mod codegen;
|
||||
mod input;
|
||||
mod schema;
|
||||
mod styling;
|
||||
mod unit;
|
||||
|
||||
/// Datasource uid every panel/target points at. Dashboards stay portable across
|
||||
/// environments because they reference the datasource by this stable uid rather
|
||||
@ -114,7 +116,7 @@ pub struct Panel {
|
||||
kind: Kind,
|
||||
targets: Vec<Target>,
|
||||
width: u32,
|
||||
unit: Option<String>,
|
||||
unit: Option<Unit>,
|
||||
decimals: Option<u32>,
|
||||
color: Option<Color>,
|
||||
span_nulls: bool,
|
||||
@ -168,8 +170,8 @@ impl Panel {
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn unit(mut self, unit: impl Into<String>) -> Self {
|
||||
self.unit = Some(unit.into());
|
||||
pub fn unit(mut self, unit: Unit) -> Self {
|
||||
self.unit = Some(unit);
|
||||
self
|
||||
}
|
||||
|
||||
@ -439,8 +441,8 @@ pub fn rate_per_min(metric: &str, legend: &str) -> Target {
|
||||
Target::new(format!("rate({metric}[1m]) * 60")).legend(legend)
|
||||
}
|
||||
|
||||
fn default_unit() -> String {
|
||||
"short".to_owned()
|
||||
const fn default_unit() -> Unit {
|
||||
Unit::Short
|
||||
}
|
||||
|
||||
fn ref_letter(index: usize) -> String {
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{DATASOURCE_UID, FieldOverride, Target};
|
||||
use crate::{DATASOURCE_UID, FieldOverride, Target, unit::Unit};
|
||||
|
||||
#[derive(Clone, Copy, Serialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
@ -245,7 +245,7 @@ pub struct Defaults {
|
||||
pub color: Option<Color>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub custom: Option<Custom>,
|
||||
pub unit: String,
|
||||
pub unit: Unit,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub decimals: Option<u32>,
|
||||
}
|
||||
|
||||
107
tools/dashboard_gen/src/unit.rs
Normal file
107
tools/dashboard_gen/src/unit.rs
Normal file
@ -0,0 +1,107 @@
|
||||
//! Panel value units.
|
||||
//!
|
||||
//! Grafana identifies a field's unit by a short id string (`"s"`, `"bytes"`,
|
||||
//! `"reqps"`, …). We model the handful we actually use as named variants and
|
||||
//! fall back to [`Unit::custom`] for anything else, so the value always
|
||||
//! serializes to the exact id Grafana expects.
|
||||
|
||||
use serde::{Serialize, Serializer};
|
||||
|
||||
/// A panel value unit. Serializes to Grafana's unit id string.
|
||||
///
|
||||
/// Only the most common units are named; [`Unit::custom`] carries any other
|
||||
/// Grafana unit id verbatim.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Unit {
|
||||
/// Plain number, SI-abbreviated (`short`). Grafana's default.
|
||||
Short,
|
||||
/// Percentage on a 0–100 scale (`percent`).
|
||||
Percent,
|
||||
/// Percentage on a 0.0–1.0 scale (`percentunit`).
|
||||
PercentUnit,
|
||||
/// Seconds (`s`).
|
||||
Seconds,
|
||||
/// Milliseconds (`ms`).
|
||||
Milliseconds,
|
||||
/// Nanoseconds (`ns`).
|
||||
Nanoseconds,
|
||||
/// Bytes, IEC/binary (`bytes`).
|
||||
Bytes,
|
||||
/// Bytes per second, SI (`Bps`).
|
||||
BytesPerSec,
|
||||
/// Requests per second (`reqps`).
|
||||
RequestsPerSec,
|
||||
/// Operations per second (`ops`).
|
||||
OpsPerSec,
|
||||
/// Any other Grafana unit id, kept verbatim.
|
||||
Custom(String),
|
||||
}
|
||||
|
||||
impl Unit {
|
||||
/// Wrap an arbitrary Grafana unit id (e.g. `"dtdurationms"`, `"celsius"`).
|
||||
#[must_use]
|
||||
pub fn custom(id: impl Into<String>) -> Self {
|
||||
Self::Custom(id.into())
|
||||
}
|
||||
|
||||
/// The Grafana unit id this value serializes to.
|
||||
fn as_id(&self) -> &str {
|
||||
match self {
|
||||
Self::Short => "short",
|
||||
Self::Percent => "percent",
|
||||
Self::PercentUnit => "percentunit",
|
||||
Self::Seconds => "s",
|
||||
Self::Milliseconds => "ms",
|
||||
Self::Nanoseconds => "ns",
|
||||
Self::Bytes => "bytes",
|
||||
Self::BytesPerSec => "Bps",
|
||||
Self::RequestsPerSec => "reqps",
|
||||
Self::OpsPerSec => "ops",
|
||||
Self::Custom(id) => id,
|
||||
}
|
||||
}
|
||||
|
||||
/// Reverse of [`Self::as_id`]: map a Grafana unit id back to a `Unit`,
|
||||
/// falling back to [`Self::Custom`] for ids we don't name. Used by the
|
||||
/// panel→Rust transpiler.
|
||||
#[must_use]
|
||||
pub(crate) fn from_id(id: &str) -> Self {
|
||||
match id {
|
||||
"short" => Self::Short,
|
||||
"percent" => Self::Percent,
|
||||
"percentunit" => Self::PercentUnit,
|
||||
"s" => Self::Seconds,
|
||||
"ms" => Self::Milliseconds,
|
||||
"ns" => Self::Nanoseconds,
|
||||
"bytes" => Self::Bytes,
|
||||
"Bps" => Self::BytesPerSec,
|
||||
"reqps" => Self::RequestsPerSec,
|
||||
"ops" => Self::OpsPerSec,
|
||||
other => Self::custom(other),
|
||||
}
|
||||
}
|
||||
|
||||
/// The Rust builder expression that reconstructs this unit, for codegen.
|
||||
#[must_use]
|
||||
pub(crate) fn to_rust_source(&self) -> String {
|
||||
match self {
|
||||
Self::Custom(id) => format!("Unit::custom({id:?})"),
|
||||
named @ (Self::Short
|
||||
| Self::Percent
|
||||
| Self::PercentUnit
|
||||
| Self::Seconds
|
||||
| Self::Milliseconds
|
||||
| Self::Nanoseconds
|
||||
| Self::Bytes
|
||||
| Self::BytesPerSec
|
||||
| Self::RequestsPerSec
|
||||
| Self::OpsPerSec) => format!("Unit::{named:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Unit {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_str(self.as_id())
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user