2020-09-14 16:08:57 +02:00
|
|
|
use std::{sync::Arc, time::Instant};
|
|
|
|
|
|
|
|
use crate::{futures::Future, rpc, rpc_apis};
|
|
|
|
|
|
|
|
use parking_lot::Mutex;
|
|
|
|
|
|
|
|
use hyper::{service::service_fn_ok, Body, Method, Request, Response, Server, StatusCode};
|
|
|
|
|
|
|
|
use stats::{
|
|
|
|
prometheus::{self, Encoder},
|
2021-03-03 22:44:35 +01:00
|
|
|
PrometheusMetrics, PrometheusRegistry,
|
2020-09-14 16:08:57 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub struct MetricsConfiguration {
|
|
|
|
/// Are metrics enabled (default is false)?
|
|
|
|
pub enabled: bool,
|
2021-03-03 22:44:35 +01:00
|
|
|
/// Prefix
|
|
|
|
pub prefix: String,
|
2020-09-14 16:08:57 +02:00
|
|
|
/// The IP of the network interface used (default is 127.0.0.1).
|
|
|
|
pub interface: String,
|
|
|
|
/// The network port (default is 3000).
|
|
|
|
pub port: u16,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for MetricsConfiguration {
|
|
|
|
fn default() -> Self {
|
|
|
|
MetricsConfiguration {
|
|
|
|
enabled: false,
|
2021-03-03 22:44:35 +01:00
|
|
|
prefix: "".into(),
|
2020-09-14 16:08:57 +02:00
|
|
|
interface: "127.0.0.1".into(),
|
|
|
|
port: 3000,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct State {
|
|
|
|
rpc_apis: Arc<rpc_apis::FullDependencies>,
|
|
|
|
}
|
|
|
|
|
2021-03-03 22:44:35 +01:00
|
|
|
fn handle_request(
|
|
|
|
req: Request<Body>,
|
|
|
|
conf: Arc<MetricsConfiguration>,
|
|
|
|
state: Arc<Mutex<State>>,
|
|
|
|
) -> Response<Body> {
|
2020-09-14 16:08:57 +02:00
|
|
|
let (parts, _body) = req.into_parts();
|
|
|
|
match (parts.method, parts.uri.path()) {
|
|
|
|
(Method::GET, "/metrics") => {
|
|
|
|
let start = Instant::now();
|
|
|
|
|
2021-03-03 22:44:35 +01:00
|
|
|
let mut reg = PrometheusRegistry::new(conf.prefix.clone());
|
2020-09-14 16:08:57 +02:00
|
|
|
let state = state.lock();
|
|
|
|
state.rpc_apis.client.prometheus_metrics(&mut reg);
|
|
|
|
state.rpc_apis.sync.prometheus_metrics(&mut reg);
|
|
|
|
let elapsed = start.elapsed();
|
2021-03-03 22:44:35 +01:00
|
|
|
reg.register_gauge(
|
2020-09-14 16:08:57 +02:00
|
|
|
"metrics_time",
|
|
|
|
"Time to perform rpc metrics",
|
|
|
|
elapsed.as_millis() as i64,
|
|
|
|
);
|
|
|
|
|
|
|
|
let mut buffer = vec![];
|
|
|
|
let encoder = prometheus::TextEncoder::new();
|
2021-03-03 22:44:35 +01:00
|
|
|
let metric_families = reg.registry().gather();
|
2020-09-14 16:08:57 +02:00
|
|
|
|
|
|
|
encoder
|
|
|
|
.encode(&metric_families, &mut buffer)
|
|
|
|
.expect("all source of metrics are static; qed");
|
|
|
|
let text = String::from_utf8(buffer).expect("metrics encoding is ASCII; qed");
|
|
|
|
|
|
|
|
Response::new(Body::from(text))
|
|
|
|
}
|
|
|
|
(_, _) => {
|
|
|
|
let mut res = Response::new(Body::from("not found"));
|
|
|
|
*res.status_mut() = StatusCode::NOT_FOUND;
|
|
|
|
res
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Start the prometheus metrics server accessible via GET <host>:<port>/metrics
|
|
|
|
pub fn start_prometheus_metrics(
|
|
|
|
conf: &MetricsConfiguration,
|
|
|
|
deps: &rpc::Dependencies<rpc_apis::FullDependencies>,
|
|
|
|
) -> Result<(), String> {
|
|
|
|
if !conf.enabled {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
|
|
|
let addr = format!("{}:{}", conf.interface, conf.port);
|
|
|
|
let addr = addr
|
|
|
|
.parse()
|
|
|
|
.map_err(|err| format!("Failed to parse address '{}': {}", addr, err))?;
|
|
|
|
|
|
|
|
let state = State {
|
|
|
|
rpc_apis: deps.apis.clone(),
|
|
|
|
};
|
|
|
|
let state = Arc::new(Mutex::new(state));
|
2021-03-03 22:44:35 +01:00
|
|
|
let conf = Arc::new(conf.to_owned());
|
2020-09-14 16:08:57 +02:00
|
|
|
let server = Server::bind(&addr)
|
|
|
|
.serve(move || {
|
|
|
|
// This is the `Service` that will handle the connection.
|
|
|
|
// `service_fn_ok` is a helper to convert a function that
|
|
|
|
// returns a Response into a `Service`.
|
|
|
|
let state = state.clone();
|
2021-03-03 22:44:35 +01:00
|
|
|
let conf = conf.clone();
|
|
|
|
service_fn_ok(move |req: Request<Body>| {
|
|
|
|
handle_request(req, conf.clone(), state.clone())
|
|
|
|
})
|
2020-09-14 16:08:57 +02:00
|
|
|
})
|
|
|
|
.map_err(|e| eprintln!("server error: {}", e));
|
2021-03-03 22:44:35 +01:00
|
|
|
info!("Started prometeus metrics at http://{}/metrics", addr);
|
2020-09-14 16:08:57 +02:00
|
|
|
|
|
|
|
deps.executor.spawn(server);
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|