Browse Source

track hashchain

0xfirefist 1 year ago
parent
commit
0a3cd50d2d

+ 1 - 41
apps/fortuna/src/api.rs

@@ -5,6 +5,7 @@ use {
             BlockStatus,
             EntropyReader,
         },
+        metrics::Metrics,
         state::HashChainState,
     },
     anyhow::Result,
@@ -19,19 +20,10 @@ use {
         Router,
     },
     ethers::core::types::Address,
-    prometheus_client::{
-        encoding::EncodeLabelSet,
-        metrics::{
-            counter::Counter,
-            family::Family,
-        },
-        registry::Registry,
-    },
     std::{
         collections::HashMap,
         sync::Arc,
     },
-    tokio::sync::RwLock,
     url::Url,
 };
 pub use {
@@ -89,38 +81,6 @@ pub struct BlockchainState {
     pub confirmed_block_status: BlockStatus,
 }
 
-pub struct Metrics {
-    pub registry:        RwLock<Registry>,
-    // TODO: track useful metrics. this counter is just a placeholder to get things set up.
-    pub request_counter: Family<Label, Counter>,
-}
-
-#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)]
-pub struct Label {
-    value: String,
-}
-
-impl Metrics {
-    pub fn new() -> Self {
-        let mut metrics_registry = Registry::default();
-        let http_requests = Family::<Label, Counter>::default();
-
-        // Register the metric family with the registry.
-        metrics_registry.register(
-            // With the metric name.
-            "http_requests",
-            // And the metric help text.
-            "Number of HTTP requests received",
-            http_requests.clone(),
-        );
-
-        Metrics {
-            registry:        RwLock::new(metrics_registry),
-            request_counter: http_requests,
-        }
-    }
-}
-
 pub enum RestError {
     /// The caller passed a sequence number that isn't within the supported range
     InvalidSequenceNumber,

+ 7 - 5
apps/fortuna/src/api/revelation.rs

@@ -1,8 +1,10 @@
 use {
-    crate::api::{
-        ChainId,
-        Label,
-        RestError,
+    crate::{
+        api::{
+            ChainId,
+            RestError,
+        },
+        metrics::RequestLabel,
     },
     anyhow::Result,
     axum::{
@@ -46,7 +48,7 @@ pub async fn revelation(
     state
         .metrics
         .request_counter
-        .get_or_create(&Label {
+        .get_or_create(&RequestLabel {
             value: "/v1/chains/{chain_id}/revelations/{sequence}".to_string(),
         })
         .inc();

+ 68 - 4
apps/fortuna/src/command/run.rs

@@ -14,6 +14,10 @@ use {
             RunOptions,
         },
         keeper,
+        metrics::{
+            self,
+            ProviderLabel,
+        },
         state::{
             HashChainState,
             PebbleHashChain,
@@ -25,14 +29,17 @@ use {
         Result,
     },
     axum::Router,
+    ethers::types::Address,
     std::{
         collections::HashMap,
         net::SocketAddr,
         sync::Arc,
+        time::Duration,
     },
     tokio::{
         spawn,
         sync::watch,
+        time,
     },
     tower_http::cors::CorsLayer,
     utoipa::OpenApi,
@@ -42,6 +49,7 @@ use {
 pub async fn run_api(
     socket_addr: SocketAddr,
     chains: HashMap<String, api::BlockchainState>,
+    metrics_registry: Arc<metrics::Metrics>,
     mut rx_exit: watch::Receiver<bool>,
 ) -> Result<()> {
     #[derive(OpenApi)]
@@ -63,10 +71,9 @@ pub async fn run_api(
     )]
     struct ApiDoc;
 
-    let metrics_registry = api::Metrics::new();
     let api_state = api::ApiState {
         chains:  Arc::new(chains),
-        metrics: Arc::new(metrics_registry),
+        metrics: metrics_registry,
     };
 
     // Initialize Axum Router. Note the type here is a `Router<State>` due to the use of the
@@ -218,11 +225,68 @@ pub async fn run(opts: &RunOptions) -> Result<()> {
         Ok::<(), Error>(())
     });
 
+    let metrics_registry = Arc::new(metrics::Metrics::new());
+
     if let Some(keeper_private_key) = opts.load_keeper_private_key()? {
-        spawn(run_keeper(chains.clone(), config, keeper_private_key));
+        spawn(run_keeper(
+            chains.clone(),
+            config.clone(),
+            keeper_private_key,
+        ));
     }
 
-    run_api(opts.addr.clone(), chains, rx_exit).await?;
+    spawn(track_hashchain(
+        config.clone(),
+        opts.provider.clone(),
+        metrics_registry.clone(),
+    ));
+
+    run_api(opts.addr.clone(), chains, metrics_registry.clone(), rx_exit).await?;
 
     Ok(())
 }
+
+
+pub async fn track_hashchain(
+    config: Config,
+    provider_address: Address,
+    metrics_registry: Arc<metrics::Metrics>,
+) {
+    loop {
+        println!("fetching balance");
+        for (chain_id, chain_config) in &config.chains {
+            let contract = match PythContract::from_config(chain_config) {
+                Ok(r) => r,
+                Err(_e) => continue,
+            };
+
+            let provider_info = match contract.get_provider_info(provider_address).call().await {
+                Ok(info) => info,
+                Err(_e) => {
+                    time::sleep(Duration::from_secs(5)).await;
+                    continue;
+                }
+            };
+            let current_sequence_number = provider_info.sequence_number;
+            let end_sequence_number = provider_info.end_sequence_number;
+
+            metrics_registry
+                .current_sequence_number
+                .get_or_create(&ProviderLabel {
+                    chain_id: chain_id.clone(),
+                    address:  provider_address.to_string(),
+                })
+                // TODO: comment on i64 to u64 conversion
+                .set(current_sequence_number as i64);
+            metrics_registry
+                .end_sequence_number
+                .get_or_create(&ProviderLabel {
+                    chain_id: chain_id.clone(),
+                    address:  provider_address.to_string(),
+                })
+                .set(end_sequence_number as i64);
+        }
+
+        time::sleep(Duration::from_secs(10)).await;
+    }
+}

+ 2 - 0
apps/fortuna/src/main.rs

@@ -1,5 +1,6 @@
 #![allow(clippy::just_underscores_and_digits)]
 #![feature(slice_flatten)]
+#![feature(integer_atomics)]
 
 use {
     anyhow::Result,
@@ -12,6 +13,7 @@ pub mod chain;
 pub mod command;
 pub mod config;
 pub mod keeper;
+pub mod metrics;
 pub mod state;
 
 // Server TODO list:

+ 90 - 0
apps/fortuna/src/metrics.rs

@@ -0,0 +1,90 @@
+use {
+    crate::api::ChainId,
+    prometheus_client::{
+        encoding::EncodeLabelSet,
+        metrics::{
+            counter::Counter,
+            family::Family,
+            gauge::{
+                Gauge,
+            },
+        },
+        registry::Registry,
+    },
+    std::sync::atomic::AtomicU64,
+    tokio::sync::RwLock,
+};
+
+#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)]
+pub struct RequestLabel {
+    pub value: String,
+}
+
+#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)]
+pub struct RpcLabel {
+    pub chain_id: ChainId,
+    pub uri:      String,
+}
+
+#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)]
+pub struct ProviderLabel {
+    pub chain_id: String,
+    pub address:  String,
+}
+
+pub struct Metrics {
+    pub registry: RwLock<Registry>,
+
+    pub request_counter: Family<RequestLabel, Counter>,
+
+    pub current_sequence_number: Family<ProviderLabel, Gauge>,
+    pub end_sequence_number:     Family<ProviderLabel, Gauge>,
+    // pub balance:           Family<Label, Gauge>,
+    // pub balance_threshold: Family<Label, Gauge>,
+    //
+    // pub rpc: Family<Label, Counter>,
+    //
+    // pub gas_spending: Family<Label, Gauge>,
+    // pub requests:     Family<Label, Counter>,
+    // pub reveal:       Family<Label, Counter>,
+}
+
+impl Metrics {
+    pub fn new() -> Self {
+        let mut metrics_registry = Registry::default();
+
+        let http_requests = Family::<RequestLabel, Counter>::default();
+        metrics_registry.register(
+            // With the metric name.
+            "http_requests",
+            // And the metric help text.
+            "Number of HTTP requests received",
+            http_requests.clone(),
+        );
+
+        let current_sequence_number = Family::<ProviderLabel, Gauge>::default();
+        metrics_registry.register(
+            // With the metric name.
+            "current_sequence_number",
+            // And the metric help text.
+            "The sequence number for a new request.",
+            current_sequence_number.clone(),
+        );
+
+        let end_sequence_number = Family::<ProviderLabel, Gauge>::default();
+        metrics_registry.register(
+            // With the metric name.
+            "end_sequence_number",
+            // And the metric help text.
+            "The sequence number for the last request.",
+            end_sequence_number.clone(),
+        );
+
+        Metrics {
+            registry: RwLock::new(metrics_registry),
+            request_counter: http_requests,
+            current_sequence_number,
+            end_sequence_number,
+        }
+    }
+}