Place zcashd.debug.* metrics behind a -debugmetrics config option

This commit is contained in:
Jack Grigg 2022-11-19 08:30:57 +00:00
parent 27ffefed12
commit 93de2aae0e
7 changed files with 66 additions and 4 deletions

12
Cargo.lock generated
View File

@ -50,6 +50,15 @@ dependencies = [
"version_check",
]
[[package]]
name = "aho-corasick"
version = "0.7.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
dependencies = [
"memchr",
]
[[package]]
name = "anyhow"
version = "1.0.65"
@ -964,6 +973,7 @@ dependencies = [
"memuse",
"metrics",
"metrics-exporter-prometheus",
"metrics-util",
"nonempty",
"orchard",
"rand 0.8.5",
@ -977,6 +987,7 @@ dependencies = [
"subtle",
"thiserror",
"time",
"tokio",
"tracing",
"tracing-appender",
"tracing-core",
@ -1108,6 +1119,7 @@ version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d24dc2dbae22bff6f1f9326ffce828c9f07ef9cc1e8002e5279f845432a30a"
dependencies = [
"aho-corasick",
"crossbeam-epoch",
"crossbeam-utils",
"hashbrown",

View File

@ -77,6 +77,8 @@ rayon = "1.5"
ipnet = "2"
metrics = "0.20"
metrics-exporter-prometheus = "0.11"
metrics-util = { version = "0.14", default-features = false, features = ["layer-filter"] }
tokio = { version = "1", features = ["rt", "net", "time"] }
# General tool dependencies
gumdrop = "0.8"

View File

@ -343,6 +343,9 @@ Monitoring options:
any request path. Use -metricsallowip and -metricsbind to control
access.
-debugmetrics
Include debug metrics in exposed node metrics.
Debugging/Testing options:
-debug=<category>

View File

@ -51,6 +51,10 @@ criteria = "safe-to-deploy"
version = "0.7.6"
criteria = "safe-to-deploy"
[[exemptions.aho-corasick]]
version = "0.7.19"
criteria = "safe-to-deploy"
[[exemptions.anyhow]]
version = "1.0.56"
criteria = "safe-to-deploy"

View File

@ -438,6 +438,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-prometheusport=<port>", _("Expose node metrics in the Prometheus exposition format. "
"An HTTP listener will be started on <port>, which responds to GET requests on any request path. "
"Use -metricsallowip and -metricsbind to control access."));
strUsage += HelpMessageOpt("-debugmetrics", _("Include debug metrics in exposed node metrics."));
strUsage += HelpMessageGroup(_("Debugging/Testing options:"));
if (showDebug)
@ -1471,10 +1472,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
metricsBindCstr = metricsBind.c_str();
}
bool debugMetrics = GetBoolArg("-debugmetrics", false);
// Start up the metrics runtime. This spins off a Rust thread that runs
// the Prometheus exporter. We just let this thread die at process end.
LogPrintf("metrics thread start");
if (!metrics_run(metricsBindCstr, vAllowCstr.data(), vAllowCstr.size(), prometheusPort)) {
if (!metrics_run(metricsBindCstr, vAllowCstr.data(), vAllowCstr.size(), prometheusPort, debugMetrics)) {
return InitError(strprintf(_("Failed to start Prometheus metrics exporter")));
}
}

View File

@ -24,7 +24,8 @@ bool metrics_run(
const char* bind_address,
const char* const* allow_ips,
size_t allow_ips_len,
uint16_t prometheus_port);
uint16_t prometheus_port,
bool debug_metrics);
struct MetricsCallsite;
typedef struct MetricsCallsite MetricsCallsite;

View File

@ -1,18 +1,48 @@
use libc::{c_char, c_double};
use metrics::{try_recorder, Key, Label};
use metrics_exporter_prometheus::PrometheusBuilder;
use metrics_exporter_prometheus::{BuildError, PrometheusBuilder};
use metrics_util::layers::{FilterLayer, Stack};
use std::ffi::CStr;
use std::net::{IpAddr, SocketAddr};
use std::ptr;
use std::slice;
use std::thread;
use tracing::error;
/// Builds the recorder and exporter, applies the given filters to the recorder, and
/// installs both of them globally.
fn metrics_install(builder: PrometheusBuilder, filters: &[&str]) -> Result<(), BuildError> {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.map_err(|e| BuildError::FailedToCreateRuntime(e.to_string()))?;
let (recorder, exporter) = {
let _g = runtime.enter();
builder.build()?
};
thread::Builder::new()
.name("zc-metrics".to_string())
.spawn(move || runtime.block_on(exporter))
.map_err(|e| BuildError::FailedToCreateRuntime(e.to_string()))?;
Stack::new(recorder)
.push(FilterLayer::from_patterns(filters))
.install()?;
Ok(())
}
#[no_mangle]
pub extern "C" fn metrics_run(
bind_address: *const c_char,
allow_ips: *const *const c_char,
allow_ips_len: usize,
prometheus_port: u16,
debug_metrics: bool,
) -> bool {
// Convert the C string IPs to Rust strings.
let allow_ips = unsafe { slice::from_raw_parts(allow_ips, allow_ips_len) };
@ -54,6 +84,13 @@ pub extern "C" fn metrics_run(
prometheus_port,
);
// Metrics matching any of these filters will be discarded.
let filters = if debug_metrics {
&[][..]
} else {
&["zcashd.debug."]
};
allow_ips
.into_iter()
.try_fold(
@ -66,7 +103,7 @@ pub extern "C" fn metrics_run(
},
)
.and_then(|builder| {
builder.install().map_err(|e| {
metrics_install(builder, filters).map_err(|e| {
error!("Could not install Prometheus exporter: {}", e);
e
})