kaspa_cli_lib/modules/
metrics.rs

1use crate::imports::*;
2use kaspa_metrics_core::{Metrics as MetricsProcessor, MetricsSinkFn};
3use workflow_core::runtime::is_nw;
4
5#[derive(Describe, Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq, Ord, PartialOrd)]
6#[serde(rename_all = "lowercase")]
7pub enum MetricsSettings {
8    #[describe("Mute logs")]
9    Mute,
10}
11
12#[async_trait]
13impl DefaultSettings for MetricsSettings {
14    async fn defaults() -> Vec<(Self, Value)> {
15        vec![]
16    }
17}
18
19pub struct Metrics {
20    settings: SettingsStore<MetricsSettings>,
21    mute: Arc<AtomicBool>,
22    metrics: Arc<MetricsProcessor>,
23}
24
25impl Default for Metrics {
26    fn default() -> Self {
27        Metrics {
28            settings: SettingsStore::try_new("metrics").expect("Failed to create miner settings store"),
29            mute: Arc::new(AtomicBool::new(true)),
30            metrics: Arc::new(MetricsProcessor::default()),
31        }
32    }
33}
34
35#[async_trait]
36impl Handler for Metrics {
37    fn verb(&self, _ctx: &Arc<dyn Context>) -> Option<&'static str> {
38        Some("metrics")
39    }
40
41    fn help(&self, _ctx: &Arc<dyn Context>) -> &'static str {
42        "Manage metrics monitoring"
43    }
44
45    async fn start(self: Arc<Self>, ctx: &Arc<dyn Context>) -> cli::Result<()> {
46        let ctx = ctx.clone().downcast_arc::<KaspaCli>()?;
47
48        self.settings.try_load().await.ok();
49        if let Some(mute) = self.settings.get(MetricsSettings::Mute) {
50            self.mute.store(mute, Ordering::Relaxed);
51        }
52
53        self.metrics.bind_rpc(Some(ctx.wallet().rpc_api().clone()));
54
55        Ok(())
56    }
57
58    async fn stop(self: Arc<Self>, _ctx: &Arc<dyn Context>) -> cli::Result<()> {
59        self.metrics.stop_task().await.map_err(|err| err.to_string())?;
60        Ok(())
61    }
62
63    async fn handle(self: Arc<Self>, ctx: &Arc<dyn Context>, argv: Vec<String>, cmd: &str) -> cli::Result<()> {
64        let ctx = ctx.clone().downcast_arc::<KaspaCli>()?;
65        self.main(ctx, argv, cmd).await.map_err(|e| e.into())
66    }
67}
68
69impl Metrics {
70    pub fn register_sink(&self, target: MetricsSinkFn) {
71        self.metrics.register_sink(target);
72    }
73
74    pub fn unregister_sink(&self) {
75        self.metrics.unregister_sink();
76    }
77
78    pub fn sink(&self) -> Option<MetricsSinkFn> {
79        self.metrics.sink()
80    }
81
82    async fn main(self: Arc<Self>, ctx: Arc<KaspaCli>, mut argv: Vec<String>, _cmd: &str) -> Result<()> {
83        if argv.is_empty() {
84            return self.display_help(ctx, argv).await;
85        }
86        match argv.remove(0).as_str() {
87            "open" => {}
88            v => {
89                tprintln!(ctx, "unknown command: '{v}'\r\n");
90
91                return self.display_help(ctx, argv).await;
92            }
93        }
94
95        Ok(())
96    }
97
98    pub async fn display_help(self: &Arc<Self>, ctx: Arc<KaspaCli>, _argv: Vec<String>) -> Result<()> {
99        // disable help in non-nw environments
100        if !is_nw() {
101            return Ok(());
102        }
103
104        ctx.term().help(&[("open", "Open metrics window"), ("close", "Close metrics window")], None)?;
105
106        Ok(())
107    }
108
109    // --- samplers
110}