Improved metrics (#240)

Added db metrics (kvdb_bytes_read, kvdb_bytes_written, kvdb_reads, kvdb_writes)
Added --metrics-prefix=[prefix]
This commit is contained in:
adria0.eth
2021-03-03 22:44:35 +01:00
committed by GitHub
parent ba011eba15
commit 0fcb102f03
34 changed files with 440 additions and 189 deletions

View File

@@ -475,6 +475,10 @@ usage! {
"--metrics",
"Enable prometheus metrics (only full client).",
ARG arg_metrics_prefix: (String) = "", or |c: &Config| c.metrics.as_ref()?.prefix.clone(),
"--metrics-prefix=[prefix]",
"Prepend the specified prefix to the exported metrics names.",
ARG arg_metrics_port: (u16) = 3000u16, or |c: &Config| c.metrics.as_ref()?.port.clone(),
"--metrics-port=[PORT]",
"Specify the port portion of the metrics server.",
@@ -922,6 +926,7 @@ struct Ipc {
#[serde(deny_unknown_fields)]
struct Metrics {
enable: Option<bool>,
prefix: Option<String>,
port: Option<u16>,
interface: Option<String>,
}
@@ -1338,6 +1343,7 @@ mod tests {
// METRICS
flag_metrics: false,
arg_metrics_prefix: "".into(),
arg_metrics_port: 3000u16,
arg_metrics_interface: "local".into(),
@@ -1542,6 +1548,7 @@ mod tests {
}),
metrics: Some(Metrics {
enable: Some(true),
prefix: Some("oe".to_string()),
interface: Some("local".to_string()),
port: Some(4000),
}),

View File

@@ -36,7 +36,7 @@ apis = ["rpc", "eth"]
enable = true
interface = "local"
port = 4000
prefix = "oe"
[secretstore]
http_port = 8082

View File

@@ -958,6 +958,7 @@ impl Configuration {
fn metrics_config(&self) -> Result<MetricsConfiguration, String> {
let conf = MetricsConfiguration {
enabled: self.metrics_enabled(),
prefix: self.metrics_prefix(),
interface: self.metrics_interface(),
port: self.args.arg_ports_shift + self.args.arg_metrics_port,
};
@@ -1147,6 +1148,10 @@ impl Configuration {
self.args.flag_metrics
}
fn metrics_prefix(&self) -> String {
self.args.arg_metrics_prefix.clone()
}
fn secretstore_enabled(&self) -> bool {
!self.args.flag_no_secretstore && cfg!(feature = "secretstore")
}

View File

@@ -24,7 +24,8 @@ use self::{
};
use blooms_db;
use ethcore::client::ClientConfig;
use kvdb::KeyValueDB;
use ethcore_db::KeyValueDB;
use stats::PrometheusMetrics;
use std::{fs, io, path::Path, sync::Arc};
mod blooms;
@@ -53,6 +54,10 @@ impl BlockChainDB for AppDB {
}
}
impl PrometheusMetrics for AppDB {
fn prometheus_metrics(&self, _: &mut stats::PrometheusRegistry) {}
}
/// Open a secret store DB using the given secret store data path. The DB path is one level beneath the data path.
#[cfg(feature = "secretstore")]
pub fn open_secretstore_db(data_path: &str) -> Result<Arc<dyn KeyValueDB>, String> {
@@ -101,8 +106,11 @@ pub fn open_database(
fs::create_dir_all(&blooms_path)?;
fs::create_dir_all(&trace_blooms_path)?;
let db = Database::open(&config, client_path)?;
let db_with_metrics = ethcore_db::DatabaseWithMetrics::new(db);
let db = AppDB {
key_value: Arc::new(Database::open(&config, client_path)?),
key_value: Arc::new(db_with_metrics),
blooms: blooms_db::Database::open(blooms_path)?,
trace_blooms: blooms_db::Database::open(trace_blooms_path)?,
};

View File

@@ -8,13 +8,15 @@ use hyper::{service::service_fn_ok, Body, Method, Request, Response, Server, Sta
use stats::{
prometheus::{self, Encoder},
prometheus_gauge, PrometheusMetrics,
PrometheusMetrics, PrometheusRegistry,
};
#[derive(Debug, Clone, PartialEq)]
pub struct MetricsConfiguration {
/// Are metrics enabled (default is false)?
pub enabled: bool,
/// Prefix
pub prefix: String,
/// The IP of the network interface used (default is 127.0.0.1).
pub interface: String,
/// The network port (default is 3000).
@@ -25,6 +27,7 @@ impl Default for MetricsConfiguration {
fn default() -> Self {
MetricsConfiguration {
enabled: false,
prefix: "".into(),
interface: "127.0.0.1".into(),
port: 3000,
}
@@ -35,19 +38,22 @@ struct State {
rpc_apis: Arc<rpc_apis::FullDependencies>,
}
fn handle_request(req: Request<Body>, state: Arc<Mutex<State>>) -> Response<Body> {
fn handle_request(
req: Request<Body>,
conf: Arc<MetricsConfiguration>,
state: Arc<Mutex<State>>,
) -> Response<Body> {
let (parts, _body) = req.into_parts();
match (parts.method, parts.uri.path()) {
(Method::GET, "/metrics") => {
let start = Instant::now();
let mut reg = prometheus::Registry::new();
let mut reg = PrometheusRegistry::new(conf.prefix.clone());
let state = state.lock();
state.rpc_apis.client.prometheus_metrics(&mut reg);
state.rpc_apis.sync.prometheus_metrics(&mut reg);
let elapsed = start.elapsed();
prometheus_gauge(
&mut reg,
reg.register_gauge(
"metrics_time",
"Time to perform rpc metrics",
elapsed.as_millis() as i64,
@@ -55,7 +61,7 @@ fn handle_request(req: Request<Body>, state: Arc<Mutex<State>>) -> Response<Body
let mut buffer = vec![];
let encoder = prometheus::TextEncoder::new();
let metric_families = reg.gather();
let metric_families = reg.registry().gather();
encoder
.encode(&metric_families, &mut buffer)
@@ -90,17 +96,20 @@ pub fn start_prometheus_metrics(
rpc_apis: deps.apis.clone(),
};
let state = Arc::new(Mutex::new(state));
let conf = Arc::new(conf.to_owned());
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();
service_fn_ok(move |req: Request<Body>| handle_request(req, state.clone()))
let conf = conf.clone();
service_fn_ok(move |req: Request<Body>| {
handle_request(req, conf.clone(), state.clone())
})
})
.map_err(|e| eprintln!("server error: {}", e));
println!("Listening on http://{}", addr);
info!("Started prometeus metrics at http://{}/metrics", addr);
deps.executor.spawn(server);