statistics.rs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2024 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use tinyjson::JsonValue;
  19. use darkfi::{Error, Result};
  20. use darkfi_sdk::blockchain::block_epoch;
  21. use crate::{metrics_store::GasMetrics, ExplorerService};
  22. #[derive(Debug, Clone)]
  23. /// Structure representing basic statistic extracted from the database.
  24. pub struct BaseStatistics {
  25. /// Current blockchain height
  26. pub height: u32,
  27. /// Current blockchain epoch (based on current height)
  28. pub epoch: u8,
  29. /// Blockchains' last block hash
  30. pub last_block: String,
  31. /// Blockchain total blocks
  32. pub total_blocks: usize,
  33. /// Blockchain total transactions
  34. pub total_txs: usize,
  35. }
  36. impl BaseStatistics {
  37. /// Auxiliary function to convert `BaseStatistics` into a `JsonValue` array.
  38. pub fn to_json_array(&self) -> JsonValue {
  39. JsonValue::Array(vec![
  40. JsonValue::Number(self.height as f64),
  41. JsonValue::Number(self.epoch as f64),
  42. JsonValue::String(self.last_block.clone()),
  43. JsonValue::Number(self.total_blocks as f64),
  44. JsonValue::Number(self.total_txs as f64),
  45. ])
  46. }
  47. }
  48. /// Structure representing metrics extracted from the database.
  49. #[derive(Default)]
  50. pub struct MetricStatistics {
  51. /// Metrics used to store explorer statistics
  52. pub metrics: GasMetrics,
  53. }
  54. impl MetricStatistics {
  55. pub fn new(metrics: GasMetrics) -> Self {
  56. Self { metrics }
  57. }
  58. /// Auxiliary function to convert [`MetricStatistics`] into a [`JsonValue`] array.
  59. pub fn to_json_array(&self) -> JsonValue {
  60. JsonValue::Array(vec![
  61. JsonValue::Number(self.metrics.avg_total_gas_used() as f64),
  62. JsonValue::Number(self.metrics.total_gas.min as f64),
  63. JsonValue::Number(self.metrics.total_gas.max as f64),
  64. JsonValue::Number(self.metrics.avg_wasm_gas_used() as f64),
  65. JsonValue::Number(self.metrics.wasm_gas.min as f64),
  66. JsonValue::Number(self.metrics.wasm_gas.max as f64),
  67. JsonValue::Number(self.metrics.avg_zk_circuits_gas_used() as f64),
  68. JsonValue::Number(self.metrics.zk_circuits_gas.min as f64),
  69. JsonValue::Number(self.metrics.zk_circuits_gas.max as f64),
  70. JsonValue::Number(self.metrics.avg_signatures_gas_used() as f64),
  71. JsonValue::Number(self.metrics.signatures_gas.min as f64),
  72. JsonValue::Number(self.metrics.signatures_gas.max as f64),
  73. JsonValue::Number(self.metrics.avg_deployments_gas_used() as f64),
  74. JsonValue::Number(self.metrics.deployments_gas.min as f64),
  75. JsonValue::Number(self.metrics.deployments_gas.max as f64),
  76. JsonValue::Number(self.metrics.timestamp.inner() as f64),
  77. ])
  78. }
  79. }
  80. impl ExplorerService {
  81. /// Fetches the latest [`BaseStatistics`] from the explorer database, or returns `None` if no block exists.
  82. pub fn get_base_statistics(&self) -> Result<Option<BaseStatistics>> {
  83. let last_block = self.last_block();
  84. Ok(last_block
  85. // Throw database error if last_block retrievals fails
  86. .map_err(|e| {
  87. Error::DatabaseError(format!(
  88. "[get_base_statistics] Retrieving last block failed: {:?}",
  89. e
  90. ))
  91. })?
  92. // Calculate base statistics and return result
  93. .map(|(height, header_hash)| {
  94. let epoch = block_epoch(height);
  95. let total_blocks = self.get_block_count();
  96. let total_txs = self.get_transaction_count();
  97. BaseStatistics { height, epoch, last_block: header_hash, total_blocks, total_txs }
  98. }))
  99. }
  100. /// Fetches the latest metrics from the explorer database, returning a vector of
  101. /// [`MetricStatistics`] if found, or an empty Vec if no metrics exist.
  102. pub async fn get_metrics_statistics(&self) -> Result<Vec<MetricStatistics>> {
  103. // Fetch all metrics from the metrics store, handling any potential errors
  104. let metrics = self.db.metrics_store.get_all_metrics().map_err(|e| {
  105. Error::DatabaseError(format!(
  106. "[get_metrics_statistics] Retrieving metrics failed: {:?}",
  107. e
  108. ))
  109. })?;
  110. // Transform the fetched metrics into `MetricStatistics`, collect them into a vector
  111. let metric_statistics =
  112. metrics.iter().map(|metrics| MetricStatistics::new(metrics.clone())).collect();
  113. Ok(metric_statistics)
  114. }
  115. /// Fetches the latest metrics from the explorer database, returning [`MetricStatistics`] if found,
  116. /// or zero-initialized defaults when not.
  117. pub async fn get_latest_metrics_statistics(&self) -> Result<MetricStatistics> {
  118. // Fetch the latest metrics, handling any potential errors
  119. match self.db.metrics_store.get_last().map_err(|e| {
  120. Error::DatabaseError(format!(
  121. "[get_metrics_statistics] Retrieving latest metrics failed: {:?}",
  122. e
  123. ))
  124. })? {
  125. // Transform metrics into `MetricStatistics` when found
  126. Some((_, metrics)) => Ok(MetricStatistics::new(metrics)),
  127. // Return default statistics when no metrics exist
  128. None => Ok(MetricStatistics::default()),
  129. }
  130. }
  131. }