Skip to content

apollo_l1_gas_price: parameterize ExchangeRateOracleClient by metric set#14199

Open
ShahakShama wants to merge 1 commit into
shahak/strk_usd_oracle_01_config_fieldfrom
shahak/strk_usd_oracle_01_5_param_oracle_metrics
Open

apollo_l1_gas_price: parameterize ExchangeRateOracleClient by metric set#14199
ShahakShama wants to merge 1 commit into
shahak/strk_usd_oracle_01_config_fieldfrom
shahak/strk_usd_oracle_01_5_param_oracle_metrics

Conversation

@ShahakShama
Copy link
Copy Markdown
Collaborator

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

@cursor
Copy link
Copy Markdown

cursor Bot commented May 26, 2026

PR Summary

Low Risk
Refactors metric ownership and observability wiring without changing SNIP-35 fee math; existing snip35_strk_usd_rate series name is preserved for dashboards.

Overview
ExchangeRateOracleClient now takes an ExchangeRateOracleMetrics bundle at construction so ETH→STRK and STRK→USD clients can update separate Prometheus series (rate, success/error counters, last-success timestamp) instead of sharing hardcoded ETH_TO_STRK_* symbols.

snip35_strk_usd_rate and three new STRK→USD oracle metrics are defined and registered in apollo_l1_gas_price (same Prometheus name for the rate gauge). apollo_consensus_orchestrator drops that gauge and stops calling set_lossy on the rate in compute_snip35_fee_proposal; the oracle client publishes the rate when queries succeed. Consensus still uses the fetched rate for fee_target.

L1GasPriceProvider::new_with_oracle passes ETH_TO_STRK_ORACLE_METRICS. The SNIP-35 Grafana row imports STRK/USD metrics from apollo_l1_gas_price and adds panels for query success, errors, and time since last successful update (plus matching dev_grafana.json entries).

Reviewed by Cursor Bugbot for commit 2a6a5dd. Bugbot is set up for automated code reviews on this repo. Configure here.

@reviewable-StarkWare
Copy link
Copy Markdown

This change is Reviewable

Copy link
Copy Markdown
Collaborator Author

ShahakShama commented May 26, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

@sirandreww-starkware sirandreww-starkware self-assigned this May 26, 2026
@sirandreww-starkware sirandreww-starkware self-requested a review May 26, 2026 10:04
Copy link
Copy Markdown
Collaborator

@matanl-starkware matanl-starkware left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matanl-starkware reviewed 8 files and all commit messages.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on sirandreww-starkware).

Copy link
Copy Markdown
Contributor

@sirandreww-starkware sirandreww-starkware left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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()
    }
}

Copy link
Copy Markdown
Contributor

@sirandreww-starkware sirandreww-starkware left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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>
@ShahakShama ShahakShama force-pushed the shahak/strk_usd_oracle_01_5_param_oracle_metrics branch from 5bcd1c9 to 2a6a5dd Compare May 26, 2026 11:24
Copy link
Copy Markdown
Collaborator Author

@ShahakShama ShahakShama left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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

Copy link
Copy Markdown
Contributor

@sirandreww-starkware sirandreww-starkware left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm:

@sirandreww-starkware reviewed 8 files and all commit messages, made 1 comment, and resolved 3 discussions.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on ShahakShama).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants