dusk_node/
telemetry.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4//
5// Copyright (c) DUSK NETWORK. All rights reserved.
6
7use std::net::SocketAddr;
8use std::sync::Arc;
9use std::time::Duration;
10
11use async_trait::async_trait;
12use memory_stats::memory_stats;
13use metrics::histogram;
14use metrics_exporter_prometheus::PrometheusBuilder;
15use tokio::sync::RwLock;
16use tokio::time::sleep;
17
18use crate::{database, vm, LongLivedService, Network};
19
20#[derive(Default)]
21pub struct TelemetrySrv {
22    addr: Option<String>,
23}
24
25#[async_trait]
26impl<N: Network, DB: database::DB, VM: vm::VMExecution>
27    LongLivedService<N, DB, VM> for TelemetrySrv
28{
29    /// Returns service name.
30    fn name(&self) -> &'static str {
31        "telemetry"
32    }
33
34    /// Initialize and spawn Prometheus Exporter and Recorder
35    async fn execute(
36        &mut self,
37        network: Arc<RwLock<N>>,
38        _: Arc<RwLock<DB>>,
39        _: Arc<RwLock<VM>>,
40    ) -> anyhow::Result<usize> {
41        // If PrometheusBuilder Recorder is not enabled then a NOOP
42        // (No-overhead) recorder is used by default.
43        if let Some(addr) = &self.addr {
44            let addr = addr.parse::<SocketAddr>()?;
45            let (recorder, exporter) =
46                PrometheusBuilder::new().with_http_listener(addr).build()?;
47            metrics::set_global_recorder(recorder)?;
48            tokio::spawn(exporter);
49
50            loop {
51                sleep(Duration::from_secs(5)).await;
52                // Record memory stats
53                if let Some(usage) = memory_stats() {
54                    histogram!("dusk_physical_mem")
55                        .record(usage.physical_mem as f64);
56                    histogram!("dusk_virtual_mem")
57                        .record(usage.virtual_mem as f64);
58                }
59
60                // Record number of alive kadcast peers
61                let count = network.read().await.alive_nodes_count().await;
62                histogram!("dusk_kadcast_peers").record(count as f64);
63            }
64        }
65        Ok(0)
66    }
67}
68
69impl TelemetrySrv {
70    pub fn new(addr: Option<String>) -> Self {
71        Self { addr }
72    }
73}