metrics/
metrics.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5use crate::{
6    report::{report_async, FileReporter, Reportable},
7    report_influxdb::{InfluxdbReportable, InfluxdbReporter},
8    report_prometheus::{PrometheusReportable, PrometheusReporter},
9};
10use cfx_tasks::TaskExecutor;
11use duration_str::deserialize_duration;
12use log::{error, info};
13use serde::{Deserialize, Serialize};
14use std::{
15    sync::atomic::{AtomicBool, Ordering},
16    time::Duration,
17};
18
19pub static ORDER: Ordering = Ordering::Relaxed;
20
21static ENABLED: AtomicBool = AtomicBool::new(false);
22
23pub fn is_enabled() -> bool { ENABLED.load(ORDER) }
24
25pub fn enable() { ENABLED.store(true, ORDER); }
26
27pub trait Metric:
28    Send + Sync + Reportable + InfluxdbReportable + PrometheusReportable
29{
30    fn get_type(&self) -> &str;
31}
32
33#[derive(Debug, Serialize, Deserialize, Clone)]
34#[serde(default)]
35pub struct MetricsConfiguration {
36    pub enabled: bool,
37
38    #[serde(deserialize_with = "deserialize_duration")]
39    pub report_interval: Duration,
40
41    pub file_report_output: Option<String>,
42
43    pub influxdb_report_host: Option<String>,
44    pub influxdb_report_db: String,
45    pub influxdb_report_username: Option<String>,
46    pub influxdb_report_password: Option<String>,
47    pub influxdb_report_node: Option<String>,
48    pub prometheus_listen_addr: Option<String>,
49}
50
51impl Default for MetricsConfiguration {
52    fn default() -> Self {
53        Self {
54            enabled: false,
55            report_interval: Duration::from_secs(10),
56            file_report_output: None,
57            influxdb_report_host: None,
58            influxdb_report_db: "".into(),
59            influxdb_report_username: None,
60            influxdb_report_password: None,
61            influxdb_report_node: None,
62            prometheus_listen_addr: None,
63        }
64    }
65}
66
67pub fn initialize(config: MetricsConfiguration, executor: TaskExecutor) {
68    info!("Initializing metrics with config: {:?}", config);
69    if !config.enabled {
70        return;
71    }
72
73    enable();
74
75    // file reporter
76    if let Some(output) = config.file_report_output {
77        let reporter = FileReporter::new(output);
78        report_async(reporter, config.report_interval);
79    }
80
81    // influxdb reporter
82    if let Some(host) = config.influxdb_report_host {
83        let mut auth = None;
84
85        if let Some(username) = config.influxdb_report_username {
86            if let Some(password) = config.influxdb_report_password {
87                auth = Some((username, password));
88            }
89        }
90
91        let mut reporter = match auth {
92            Some((username, password)) => InfluxdbReporter::with_auth(
93                host,
94                config.influxdb_report_db,
95                username,
96                password,
97            ),
98            None => InfluxdbReporter::new(host, config.influxdb_report_db),
99        };
100
101        if let Some(node) = config.influxdb_report_node {
102            reporter.add_tag("node".into(), node);
103        }
104
105        report_async(reporter, config.report_interval);
106    }
107
108    // prometheus reporter
109
110    if let Some(addr) = config.prometheus_listen_addr {
111        match PrometheusReporter::new(&addr, executor) {
112            Ok(reporter) => {
113                info!("Initializing PrometheusReporter to listen on {}", addr);
114                match reporter.start_http_server() {
115                    Ok(_) => {
116                        info!("PrometheusReporter started successfully");
117                    }
118                    Err(e) => {
119                        error!("Failed to start PrometheusReporter: {}", e);
120                    }
121                }
122            }
123            Err(e) => {
124                error!("Failed to initialize PrometheusReporter: {}", e);
125            }
126        }
127    }
128}