1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use std::{net::SocketAddr, time::Duration};
use metrics_core::Observe;
use metrics_runtime::{
exporters::{HttpExporter, LogExporter},
observers::{JsonBuilder, PrometheusBuilder, YamlBuilder},
Receiver,
};
use ckb_async_runtime::Handle;
use ckb_metrics_config::{Config, Exporter, Format, Target};
use ckb_util::strings;
#[must_use]
pub enum Guard {
Off,
On,
}
pub fn init(config: Config, handle: Handle) -> Result<Guard, String> {
if config.exporter.is_empty() {
return Ok(Guard::Off);
}
let receiver = {
let histogram_window_secs = if config.histogram_window > 0 {
config.histogram_window
} else {
10
};
let histogram_granularity_secs = if config.histogram_granularity > 0 {
config.histogram_granularity
} else {
1
};
let upkeep_interval_millis = if config.upkeep_interval > 0 {
config.upkeep_interval
} else {
50
};
let histogram_window = Duration::from_secs(histogram_window_secs);
let histogram_granularity = Duration::from_secs(histogram_granularity_secs);
let upkeep_interval = Duration::from_millis(upkeep_interval_millis);
Receiver::builder()
.histogram(histogram_window, histogram_granularity)
.upkeep_interval(upkeep_interval)
}
.build()
.unwrap();
let controller = receiver.controller();
for (name, exporter) in config.exporter {
check_exporter_name(&name)?;
run_exporter(exporter, &handle, controller.clone())?;
}
receiver.install();
Ok(Guard::On)
}
fn check_exporter_name(name: &str) -> Result<(), String> {
strings::check_if_identifier_is_valid(name)
}
fn run_exporter<C>(exporter: Exporter, handle: &Handle, c: C) -> Result<(), String>
where
C: Observe + Sync + Send + 'static,
{
let Exporter { target, format } = exporter;
match target {
Target::Log {
level: lv,
interval,
} => {
let dur = Duration::from_secs(interval);
match format {
Format::Json { pretty } => {
let b = JsonBuilder::new().set_pretty_json(pretty);
let exporter = LogExporter::new(c, b, lv, dur);
handle.spawn(exporter.async_run());
}
Format::Yaml => {
let b = YamlBuilder::new();
let exporter = LogExporter::new(c, b, lv, dur);
handle.spawn(exporter.async_run());
}
Format::Prometheus => {
let b = PrometheusBuilder::new();
let exporter = LogExporter::new(c, b, lv, dur);
handle.spawn(exporter.async_run());
}
};
}
Target::Http { listen_address } => {
let addr = listen_address
.parse::<SocketAddr>()
.map_err(|err| format!("failed to parse listen_address because {}", err))?;
match format {
Format::Json { pretty } => {
let b = JsonBuilder::new().set_pretty_json(pretty);
let exporter = HttpExporter::new(c, b, addr);
handle.spawn(exporter.async_run());
}
Format::Yaml => {
let b = YamlBuilder::new();
let exporter = HttpExporter::new(c, b, addr);
handle.spawn(exporter.async_run());
}
Format::Prometheus => {
let b = PrometheusBuilder::new();
let exporter = HttpExporter::new(c, b, addr);
handle.spawn(exporter.async_run());
}
};
}
}
Ok(())
}