mirror of
https://github.com/logos-blockchain/logos-blockchain-testing.git
synced 2026-01-02 21:33:07 +00:00
workflows: add try_* builder APIs for URLs and rates
This commit is contained in:
parent
f0e9d2807b
commit
8a6d7236ef
@ -13,6 +13,18 @@ use crate::{
|
||||
workloads::{chaos::RandomRestartWorkload, da, transaction},
|
||||
};
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum BuilderInputError {
|
||||
#[error("{field} must be non-zero")]
|
||||
ZeroValue { field: &'static str },
|
||||
#[error("invalid url for {field}: '{value}': {message}")]
|
||||
InvalidUrl {
|
||||
field: &'static str,
|
||||
value: String,
|
||||
message: String,
|
||||
},
|
||||
}
|
||||
|
||||
macro_rules! non_zero_rate_fn {
|
||||
($name:ident, $message:literal) => {
|
||||
const fn $name(rate: u64) -> NonZeroU64 {
|
||||
@ -106,6 +118,13 @@ pub trait ObservabilityBuilderExt: Sized {
|
||||
/// Convenience wrapper that parses a URL string (panics if invalid).
|
||||
fn with_metrics_query_url_str(self, url: &str) -> CoreScenarioBuilder<ObservabilityCapability>;
|
||||
|
||||
/// Like `with_metrics_query_url_str`, but returns an error instead of
|
||||
/// panicking.
|
||||
fn try_with_metrics_query_url_str(
|
||||
self,
|
||||
url: &str,
|
||||
) -> Result<CoreScenarioBuilder<ObservabilityCapability>, BuilderInputError>;
|
||||
|
||||
/// Configure the OTLP HTTP metrics ingest endpoint to which nodes should
|
||||
/// export metrics (must be a full URL, including any required path).
|
||||
fn with_metrics_otlp_ingest_url(
|
||||
@ -119,12 +138,25 @@ pub trait ObservabilityBuilderExt: Sized {
|
||||
url: &str,
|
||||
) -> CoreScenarioBuilder<ObservabilityCapability>;
|
||||
|
||||
/// Like `with_metrics_otlp_ingest_url_str`, but returns an error instead of
|
||||
/// panicking.
|
||||
fn try_with_metrics_otlp_ingest_url_str(
|
||||
self,
|
||||
url: &str,
|
||||
) -> Result<CoreScenarioBuilder<ObservabilityCapability>, BuilderInputError>;
|
||||
|
||||
/// Optional Grafana base URL for printing/logging (human access).
|
||||
fn with_grafana_url(self, url: reqwest::Url) -> CoreScenarioBuilder<ObservabilityCapability>;
|
||||
|
||||
/// Convenience wrapper that parses a URL string (panics if invalid).
|
||||
fn with_grafana_url_str(self, url: &str) -> CoreScenarioBuilder<ObservabilityCapability>;
|
||||
|
||||
/// Like `with_grafana_url_str`, but returns an error instead of panicking.
|
||||
fn try_with_grafana_url_str(
|
||||
self,
|
||||
url: &str,
|
||||
) -> Result<CoreScenarioBuilder<ObservabilityCapability>, BuilderInputError>;
|
||||
|
||||
#[deprecated(note = "use with_metrics_query_url")]
|
||||
fn with_external_prometheus(
|
||||
self,
|
||||
@ -175,6 +207,18 @@ impl ObservabilityBuilderExt for CoreScenarioBuilder<()> {
|
||||
self.with_metrics_query_url(parsed)
|
||||
}
|
||||
|
||||
fn try_with_metrics_query_url_str(
|
||||
self,
|
||||
url: &str,
|
||||
) -> Result<CoreScenarioBuilder<ObservabilityCapability>, BuilderInputError> {
|
||||
let parsed = reqwest::Url::parse(url).map_err(|err| BuilderInputError::InvalidUrl {
|
||||
field: "metrics_query_url",
|
||||
value: url.to_string(),
|
||||
message: err.to_string(),
|
||||
})?;
|
||||
Ok(self.with_metrics_query_url(parsed))
|
||||
}
|
||||
|
||||
fn with_metrics_otlp_ingest_url(
|
||||
self,
|
||||
url: reqwest::Url,
|
||||
@ -194,6 +238,18 @@ impl ObservabilityBuilderExt for CoreScenarioBuilder<()> {
|
||||
self.with_metrics_otlp_ingest_url(parsed)
|
||||
}
|
||||
|
||||
fn try_with_metrics_otlp_ingest_url_str(
|
||||
self,
|
||||
url: &str,
|
||||
) -> Result<CoreScenarioBuilder<ObservabilityCapability>, BuilderInputError> {
|
||||
let parsed = reqwest::Url::parse(url).map_err(|err| BuilderInputError::InvalidUrl {
|
||||
field: "metrics_otlp_ingest_url",
|
||||
value: url.to_string(),
|
||||
message: err.to_string(),
|
||||
})?;
|
||||
Ok(self.with_metrics_otlp_ingest_url(parsed))
|
||||
}
|
||||
|
||||
fn with_grafana_url(self, url: reqwest::Url) -> CoreScenarioBuilder<ObservabilityCapability> {
|
||||
self.with_capabilities(ObservabilityCapability {
|
||||
metrics_query_url: None,
|
||||
@ -206,6 +262,18 @@ impl ObservabilityBuilderExt for CoreScenarioBuilder<()> {
|
||||
let parsed = reqwest::Url::parse(url).expect("grafana url must be valid");
|
||||
self.with_grafana_url(parsed)
|
||||
}
|
||||
|
||||
fn try_with_grafana_url_str(
|
||||
self,
|
||||
url: &str,
|
||||
) -> Result<CoreScenarioBuilder<ObservabilityCapability>, BuilderInputError> {
|
||||
let parsed = reqwest::Url::parse(url).map_err(|err| BuilderInputError::InvalidUrl {
|
||||
field: "grafana_url",
|
||||
value: url.to_string(),
|
||||
message: err.to_string(),
|
||||
})?;
|
||||
Ok(self.with_grafana_url(parsed))
|
||||
}
|
||||
}
|
||||
|
||||
impl ObservabilityBuilderExt for CoreScenarioBuilder<ObservabilityCapability> {
|
||||
@ -222,6 +290,18 @@ impl ObservabilityBuilderExt for CoreScenarioBuilder<ObservabilityCapability> {
|
||||
self.with_metrics_query_url(parsed)
|
||||
}
|
||||
|
||||
fn try_with_metrics_query_url_str(
|
||||
self,
|
||||
url: &str,
|
||||
) -> Result<CoreScenarioBuilder<ObservabilityCapability>, BuilderInputError> {
|
||||
let parsed = reqwest::Url::parse(url).map_err(|err| BuilderInputError::InvalidUrl {
|
||||
field: "metrics_query_url",
|
||||
value: url.to_string(),
|
||||
message: err.to_string(),
|
||||
})?;
|
||||
Ok(self.with_metrics_query_url(parsed))
|
||||
}
|
||||
|
||||
fn with_metrics_otlp_ingest_url(
|
||||
mut self,
|
||||
url: reqwest::Url,
|
||||
@ -238,6 +318,18 @@ impl ObservabilityBuilderExt for CoreScenarioBuilder<ObservabilityCapability> {
|
||||
self.with_metrics_otlp_ingest_url(parsed)
|
||||
}
|
||||
|
||||
fn try_with_metrics_otlp_ingest_url_str(
|
||||
self,
|
||||
url: &str,
|
||||
) -> Result<CoreScenarioBuilder<ObservabilityCapability>, BuilderInputError> {
|
||||
let parsed = reqwest::Url::parse(url).map_err(|err| BuilderInputError::InvalidUrl {
|
||||
field: "metrics_otlp_ingest_url",
|
||||
value: url.to_string(),
|
||||
message: err.to_string(),
|
||||
})?;
|
||||
Ok(self.with_metrics_otlp_ingest_url(parsed))
|
||||
}
|
||||
|
||||
fn with_grafana_url(
|
||||
mut self,
|
||||
url: reqwest::Url,
|
||||
@ -250,6 +342,18 @@ impl ObservabilityBuilderExt for CoreScenarioBuilder<ObservabilityCapability> {
|
||||
let parsed = reqwest::Url::parse(url).expect("grafana url must be valid");
|
||||
self.with_grafana_url(parsed)
|
||||
}
|
||||
|
||||
fn try_with_grafana_url_str(
|
||||
self,
|
||||
url: &str,
|
||||
) -> Result<CoreScenarioBuilder<ObservabilityCapability>, BuilderInputError> {
|
||||
let parsed = reqwest::Url::parse(url).map_err(|err| BuilderInputError::InvalidUrl {
|
||||
field: "grafana_url",
|
||||
value: url.to_string(),
|
||||
message: err.to_string(),
|
||||
})?;
|
||||
Ok(self.with_grafana_url(parsed))
|
||||
}
|
||||
}
|
||||
|
||||
/// Builder for transaction workloads.
|
||||
@ -279,6 +383,16 @@ impl<Caps> TransactionFlowBuilder<Caps> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Like `rate`, but returns an error instead of panicking.
|
||||
pub fn try_rate(self, rate: u64) -> Result<Self, BuilderInputError> {
|
||||
let Some(rate) = NonZeroU64::new(rate) else {
|
||||
return Err(BuilderInputError::ZeroValue {
|
||||
field: "transaction_rate",
|
||||
});
|
||||
};
|
||||
Ok(self.rate_per_block(rate))
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
/// Set transaction submission rate per block.
|
||||
pub const fn rate_per_block(mut self, rate: NonZeroU64) -> Self {
|
||||
@ -296,6 +410,17 @@ impl<Caps> TransactionFlowBuilder<Caps> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Like `users`, but returns an error instead of panicking.
|
||||
pub fn try_users(mut self, users: usize) -> Result<Self, BuilderInputError> {
|
||||
let Some(value) = NonZeroUsize::new(users) else {
|
||||
return Err(BuilderInputError::ZeroValue {
|
||||
field: "transaction_users",
|
||||
});
|
||||
};
|
||||
self.users = Some(value);
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
/// Attach the transaction workload to the scenario.
|
||||
pub fn apply(mut self) -> CoreScenarioBuilder<Caps> {
|
||||
@ -347,6 +472,16 @@ impl<Caps> DataAvailabilityFlowBuilder<Caps> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Like `channel_rate`, but returns an error instead of panicking.
|
||||
pub fn try_channel_rate(self, rate: u64) -> Result<Self, BuilderInputError> {
|
||||
let Some(rate) = NonZeroU64::new(rate) else {
|
||||
return Err(BuilderInputError::ZeroValue {
|
||||
field: "da_channel_rate",
|
||||
});
|
||||
};
|
||||
Ok(self.channel_rate_per_block(rate))
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
/// Set the number of DA channels to run.
|
||||
pub const fn channel_rate_per_block(mut self, rate: NonZeroU64) -> Self {
|
||||
@ -361,6 +496,16 @@ impl<Caps> DataAvailabilityFlowBuilder<Caps> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Like `blob_rate`, but returns an error instead of panicking.
|
||||
pub fn try_blob_rate(self, rate: u64) -> Result<Self, BuilderInputError> {
|
||||
let Some(rate) = NonZeroU64::new(rate) else {
|
||||
return Err(BuilderInputError::ZeroValue {
|
||||
field: "da_blob_rate",
|
||||
});
|
||||
};
|
||||
Ok(self.blob_rate_per_block(rate))
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
/// Set blob publish rate per block.
|
||||
pub const fn blob_rate_per_block(mut self, rate: NonZeroU64) -> Self {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user