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:
@@ -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),
|
||||
}),
|
||||
|
||||
@@ -36,7 +36,7 @@ apis = ["rpc", "eth"]
|
||||
enable = true
|
||||
interface = "local"
|
||||
port = 4000
|
||||
|
||||
prefix = "oe"
|
||||
|
||||
[secretstore]
|
||||
http_port = 8082
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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)?,
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user