apollo_l1_gas_price: parameterize ExchangeRateOracleClient by metric set#14199
Conversation
PR SummaryLow Risk Overview
Reviewed by Cursor Bugbot for commit 2a6a5dd. Bugbot is set up for automated code reviews on this repo. Configure here. |
matanl-starkware
left a comment
There was a problem hiding this comment.
@matanl-starkware reviewed 8 files and all commit messages.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on sirandreww-starkware).
sirandreww-starkware
left a comment
There was a problem hiding this comment.
@sirandreww-starkware made 6 comments.
Reviewable status: all files reviewed, 6 unresolved discussions (waiting on ShahakShama).
crates/apollo_consensus_orchestrator/src/metrics.rs line 39 at r1 (raw file):
// The STRK/USD rate gauge (`snip35_strk_usd_rate`) plus its query // success/error/last-success-timestamp counters live in `apollo_l1_gas_price`, // owned by the `ExchangeRateOracleClient` that fetches the rate.
didn't you remove this?
Code quote:
// The STRK/USD rate gauge (`snip35_strk_usd_rate`) plus its query
// success/error/last-success-timestamp counters live in `apollo_l1_gas_price`,
// owned by the `ExchangeRateOracleClient` that fetches the rate.crates/apollo_consensus_orchestrator/src/sequencer_consensus_context.rs line 464 at r1 (raw file):
Ok(rate) => { // The oracle client publishes `snip35_strk_usd_rate` itself; consensus // only consumes the value to compute `fee_target`.
Would remove these
Code quote:
// The oracle client publishes `snip35_strk_usd_rate` itself; consensus
// only consumes the value to compute `fee_target`.crates/apollo_dashboard/src/panels/consensus.rs line 772 at r1 (raw file):
"\"Failed to resolve query to\" OR \"Timeout when resolving query to\" OR \"Query failed \ to join handle for timestamp\"", )
why log?
Code quote:
.with_log_query(
"\"Failed to resolve query to\" OR \"Timeout when resolving query to\" OR \"Query failed \
to join handle for timestamp\"",
)crates/apollo_dashboard/src/panels/consensus.rs line 782 at r1 (raw file):
PanelType::TimeSeries, ) .with_log_query("Caching conversion rate for timestamp")
why log?
Code quote:
.with_log_query("Caching conversion rate for timestamp")crates/apollo_dashboard/src/panels/consensus.rs line 789 at r1 (raw file):
"Seconds Since Last Successful STRK→USD Rate Update", "The number of seconds since the last successful STRK→USD rate update (assuming there \ was an update in the last 12 hours).",
why is this assumption here?
Code quote:
"The number of seconds since the last successful STRK→USD rate update (assuming there \
was an update in the last 12 hours).",crates/apollo_l1_gas_price/src/metrics.rs line 67 at r1 (raw file):
.finish() } }
was this really needed? no default for metrics?
Code quote:
// Manual impl: `MetricGauge` / `MetricCounter` do not derive `Debug`,
// but the surrounding `ExchangeRateOracleClient` does. Printing the prom
// name of each metric is the only useful thing to surface.
impl std::fmt::Debug for ExchangeRateOracleMetrics {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ExchangeRateOracleMetrics")
.field("rate", &self.rate.get_name())
.field("success_count", &self.success_count.get_name())
.field("error_count", &self.error_count.get_name())
.field("last_success_timestamp", &self.last_success_timestamp.get_name())
.finish()
}
}
sirandreww-starkware
left a comment
There was a problem hiding this comment.
@sirandreww-starkware resolved 3 discussions.
Reviewable status: all files reviewed, 3 unresolved discussions (waiting on ShahakShama).
Goal: Prerequisite for PR #14158 (`02_provider_holds_oracle`). Before that PR introduces a second `ExchangeRateOracleClient` for STRK→USD, parameterize the client by metric set so the two oracles update disjoint Prometheus series instead of contaminating each other's gauges and counters. Closes the issue flagged by Cursor bugbot + matanl-starkware on PR #14158. Change summary: - `apollo_l1_gas_price::metrics` defines `ExchangeRateOracleMetrics` (`rate`, `success_count`, `error_count`, `last_success_timestamp`) as a `Copy` struct of `&'static` refs, plus two `pub const` instances: `ETH_TO_STRK_ORACLE_METRICS` and `STRK_TO_USD_ORACLE_METRICS`. - `SNIP35_STRK_USD_RATE` moves from `apollo_consensus_orchestrator::metrics` into `apollo_l1_gas_price::metrics`, keeping the Prometheus name `snip35_strk_usd_rate` so the existing Grafana panel keeps working without a query rewrite. - Adds three new SNIP-35 metrics owned by the oracle client: `snip35_strk_usd_success_count`, `snip35_strk_usd_error_count`, `snip35_strk_usd_last_success_timestamp_seconds`. - `ExchangeRateOracleClient::new(config, metrics)` now stores the metric set; `spawn_query`, `resolve_query`, and `fetch_rate` route through `self.metrics.*` instead of hardcoded `ETH_TO_STRK_*` symbols. Manual `Debug` impl on `ExchangeRateOracleMetrics` (the underlying `MetricCounter`/`MetricGauge` don't derive Debug) prints prom names. - `L1GasPriceProvider::new_with_oracle` passes `ETH_TO_STRK_ORACLE_METRICS` to the existing client; PR 02 will pass `STRK_TO_USD_ORACLE_METRICS` to its new client. - `SequencerConsensusContext::compute_snip35_fee_proposal` stops calling `SNIP35_STRK_USD_RATE.set_lossy(rate)`; the oracle client publishes that gauge itself now. Consensus still reads the rate to compute `fee_target`. - `apollo_dashboard::panels::consensus` imports `SNIP35_STRK_USD_RATE` (and the 3 new metrics) from `apollo_l1_gas_price` instead of `apollo_consensus_orchestrator`; adds 3 new panels (success / error / seconds-since-last-update) to the SNIP-35 row, matching the ETH→STRK panel patterns. - `dev_grafana.json` updated by hand to add the 3 new panel entries; the Rust toolchain is unavailable in this environment so the generator could not be re-run. Verify locally with `cargo run --bin sequencer_dashboard_generator` before pushing. Decision points: - Reuse `snip35_strk_usd_rate` rather than defining a new `strk_to_usd_rate`: the existing time series + Grafana panel keep continuity, and the SNIP-35 dashboard row is the natural home for the STRK→USD oracle gauges. - Move the metric definition into `apollo_l1_gas_price` (owner) rather than keeping it in `apollo_consensus_orchestrator` and passing a `&'static` reference down: avoids cross-crate metric ownership and preserves the existing one-way crate dependency (consensus → l1_gas_price_types). - `pub const` struct of `&'static` refs (matches the existing `TEST_LOCAL_SERVER_METRICS` pattern in `apollo_infra`) rather than `static`: lets `ExchangeRateOracleClient` store the set by value (Copy) with no lifetime annotations on the struct. - Add all 3 observability metrics (success/error/timestamp) symmetrically with the ETH→STRK side rather than just the rate: keeps the new dashboard row useful — "did the STRK→USD query just fail or just stop firing?" is answerable without leaning on log queries. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5bcd1c9 to
2a6a5dd
Compare
ShahakShama
left a comment
There was a problem hiding this comment.
@ShahakShama made 3 comments.
Reviewable status: 6 of 8 files reviewed, 3 unresolved discussions (waiting on matanl-starkware and sirandreww-starkware).
crates/apollo_consensus_orchestrator/src/metrics.rs line 39 at r1 (raw file):
Previously, sirandreww-starkware (Andrew Luka) wrote…
didn't you remove this?
Done.
crates/apollo_consensus_orchestrator/src/sequencer_consensus_context.rs line 464 at r1 (raw file):
Previously, sirandreww-starkware (Andrew Luka) wrote…
Would remove these
Done.
crates/apollo_l1_gas_price/src/metrics.rs line 67 at r1 (raw file):
Previously, sirandreww-starkware (Andrew Luka) wrote…
was this really needed? no default for metrics?
no default
sirandreww-starkware
left a comment
There was a problem hiding this comment.
@sirandreww-starkware reviewed 8 files and all commit messages, made 1 comment, and resolved 3 discussions.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on ShahakShama).

Goal: Prerequisite for PR #14158 (
02_provider_holds_oracle). Before thatPR introduces a second
ExchangeRateOracleClientfor STRK→USD,parameterize the client by metric set so the two oracles update disjoint
Prometheus series instead of contaminating each other's gauges and
counters. Closes the issue flagged by Cursor bugbot + matanl-starkware on
PR #14158.
Change summary:
apollo_l1_gas_price::metricsdefinesExchangeRateOracleMetrics(
rate,success_count,error_count,last_success_timestamp) as aCopystruct of&'staticrefs, plus twopub constinstances:ETH_TO_STRK_ORACLE_METRICSandSTRK_TO_USD_ORACLE_METRICS.SNIP35_STRK_USD_RATEmoves fromapollo_consensus_orchestrator::metricsinto
apollo_l1_gas_price::metrics, keeping the Prometheus namesnip35_strk_usd_rateso the existing Grafana panel keeps workingwithout a query rewrite.
snip35_strk_usd_success_count,snip35_strk_usd_error_count,snip35_strk_usd_last_success_timestamp_seconds.ExchangeRateOracleClient::new(config, metrics)now stores the metricset;
spawn_query,resolve_query, andfetch_rateroute throughself.metrics.*instead of hardcodedETH_TO_STRK_*symbols. ManualDebugimpl onExchangeRateOracleMetrics(the underlyingMetricCounter/MetricGaugedon't derive Debug) prints prom names.L1GasPriceProvider::new_with_oraclepassesETH_TO_STRK_ORACLE_METRICSto the existing client; PR 02 will pass
STRK_TO_USD_ORACLE_METRICStoits new client.
SequencerConsensusContext::compute_snip35_fee_proposalstops callingSNIP35_STRK_USD_RATE.set_lossy(rate); the oracle client publishes thatgauge itself now. Consensus still reads the rate to compute
fee_target.apollo_dashboard::panels::consensusimportsSNIP35_STRK_USD_RATE(andthe 3 new metrics) from
apollo_l1_gas_priceinstead ofapollo_consensus_orchestrator; adds 3 new panels (success / error /seconds-since-last-update) to the SNIP-35 row, matching the ETH→STRK
panel patterns.
dev_grafana.jsonupdated by hand to add the 3 new panel entries; theRust toolchain is unavailable in this environment so the generator
could not be re-run. Verify locally with
cargo run --bin sequencer_dashboard_generatorbefore pushing.Decision points:
snip35_strk_usd_raterather than defining a newstrk_to_usd_rate: the existing time series + Grafana panel keepcontinuity, and the SNIP-35 dashboard row is the natural home for the
STRK→USD oracle gauges.
apollo_l1_gas_price(owner) ratherthan keeping it in
apollo_consensus_orchestratorand passing a&'staticreference down: avoids cross-crate metric ownership andpreserves the existing one-way crate dependency
(consensus → l1_gas_price_types).
pub conststruct of&'staticrefs (matches the existingTEST_LOCAL_SERVER_METRICSpattern inapollo_infra) rather thanstatic: letsExchangeRateOracleClientstore the set by value (Copy)with no lifetime annotations on the struct.
with the ETH→STRK side rather than just the rate: keeps the new
dashboard row useful — "did the STRK→USD query just fail or just stop
firing?" is answerable without leaning on log queries.
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com