diff --git a/Cargo.lock b/Cargo.lock index 2872d3b..0c6a8d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -128,17 +128,6 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.4.0" @@ -160,12 +149,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.21.7" @@ -420,19 +403,6 @@ dependencies = [ "regex", ] -[[package]] -name = "env_logger" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - [[package]] name = "env_logger" version = "0.11.6" @@ -487,11 +457,13 @@ dependencies = [ "chrono", "clap", "dbc-rust-modules", - "env_logger 0.11.6", + "env_logger", + "hyper 1.6.0", + "hyper-util", "lazy_static", "num-traits", "openssl", - "prometheus_exporter_base", + "prometheus", "regex", "reqwest 0.12.12", "serde", @@ -654,15 +626,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hermit-abi" version = "0.3.9" @@ -780,9 +743,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" dependencies = [ "bytes", "futures-channel", @@ -791,6 +754,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "httparse", + "httpdate", "itoa", "pin-project-lite", "smallvec", @@ -798,21 +762,6 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-rustls" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" -dependencies = [ - "http 0.2.12", - "hyper 0.14.30", - "log", - "rustls 0.20.9", - "rustls-native-certs", - "tokio", - "tokio-rustls 0.23.4", -] - [[package]] name = "hyper-rustls" version = "0.27.3" @@ -821,12 +770,12 @@ checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.4.1", + "hyper 1.6.0", "hyper-util", - "rustls 0.23.13", + "rustls", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls", "tower-service", "webpki-roots", ] @@ -852,7 +801,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.4.1", + "hyper 1.6.0", "hyper-util", "native-tls", "tokio", @@ -862,16 +811,17 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "cf9f1e950e0d9d1d3c47184416723cf29c0d1f93bd8cccf37e4beb6b44f31710" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.1.0", "http-body 1.0.1", - "hyper 1.4.1", + "hyper 1.6.0", + "libc", "pin-project-lite", "socket2", "tokio", @@ -1114,9 +1064,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.169" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "linked-hash-map" @@ -1194,7 +1144,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi", "libc", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", @@ -1217,70 +1167,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -1424,20 +1310,37 @@ dependencies = [ ] [[package]] -name = "prometheus_exporter_base" -version = "1.4.0" +name = "prometheus" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42dafed8b073871c93f6082ff0fc597dbf26fb58974f0140f2c6a46c9f9f624" +checksum = "3ca5326d8d0b950a9acd87e6a3f94745394f62e4dae1b1ee22b2bc0c394af43a" +dependencies = [ + "cfg-if", + "fnv", + "lazy_static", + "memchr", + "parking_lot", + "protobuf", + "thiserror 2.0.11", +] + +[[package]] +name = "protobuf" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65a1d4ddae7d8b5de68153b48f6aa3bba8cb002b243dbdbc55a5afbc98f99f4" +dependencies = [ + "once_cell", + "protobuf-support", + "thiserror 1.0.64", +] + +[[package]] +name = "protobuf-support" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e36c2f31e0a47f9280fb347ef5e461ffcd2c52dd520d8e216b52f93b0b0d7d6" dependencies = [ - "base64 0.13.1", - "env_logger 0.9.3", - "http 0.2.12", - "hyper 0.14.30", - "hyper-rustls 0.23.2", - "log", - "num", - "serde", - "serde_json", "thiserror 1.0.64", ] @@ -1458,7 +1361,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.13", + "rustls", "socket2", "thiserror 2.0.11", "tokio", @@ -1474,9 +1377,9 @@ dependencies = [ "bytes", "getrandom", "rand", - "ring 0.17.8", + "ring", "rustc-hash", - "rustls 0.23.13", + "rustls", "rustls-pki-types", "slab", "thiserror 2.0.11", @@ -1632,8 +1535,8 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", - "hyper-rustls 0.27.3", + "hyper 1.6.0", + "hyper-rustls", "hyper-tls 0.6.0", "hyper-util", "ipnet", @@ -1645,7 +1548,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.13", + "rustls", "rustls-pemfile 2.1.3", "rustls-pki-types", "serde", @@ -1655,7 +1558,7 @@ dependencies = [ "system-configuration 0.6.1", "tokio", "tokio-native-tls", - "tokio-rustls 0.26.0", + "tokio-rustls", "tower", "tower-service", "url", @@ -1676,21 +1579,6 @@ dependencies = [ "quick-error", ] -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - [[package]] name = "ring" version = "0.17.8" @@ -1701,8 +1589,8 @@ dependencies = [ "cfg-if", "getrandom", "libc", - "spin 0.9.8", - "untrusted 0.9.0", + "spin", + "untrusted", "windows-sys 0.52.0", ] @@ -1765,18 +1653,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rustls" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" -dependencies = [ - "log", - "ring 0.16.20", - "sct", - "webpki", -] - [[package]] name = "rustls" version = "0.23.13" @@ -1784,25 +1660,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" dependencies = [ "once_cell", - "ring 0.17.8", + "ring", "rustls-pki-types", "rustls-webpki", "subtle", "zeroize", ] -[[package]] -name = "rustls-native-certs" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" -dependencies = [ - "openssl-probe", - "rustls-pemfile 1.0.4", - "schannel", - "security-framework", -] - [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -1837,9 +1701,9 @@ version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ - "ring 0.17.8", + "ring", "rustls-pki-types", - "untrusted 0.9.0", + "untrusted", ] [[package]] @@ -1872,16 +1736,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", -] - [[package]] name = "security-framework" version = "2.11.1" @@ -1981,20 +1835,14 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" dependencies = [ "libc", "windows-sys 0.52.0", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" @@ -2140,15 +1988,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - [[package]] name = "thiserror" version = "1.0.64" @@ -2264,24 +2103,13 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-rustls" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" -dependencies = [ - "rustls 0.20.9", - "tokio", - "webpki", -] - [[package]] name = "tokio-rustls" version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.13", + "rustls", "rustls-pki-types", "tokio", ] @@ -2437,12 +2265,6 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - [[package]] name = "untrusted" version = "0.9.0" @@ -2644,16 +2466,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" -dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", -] - [[package]] name = "webpki-roots" version = "0.26.8" diff --git a/Cargo.toml b/Cargo.toml index 8c43980..fb459b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,6 @@ lazy_static = "1" walkdir = "2" trust-dns-resolver = { version = "0.23", features = ["tokio-runtime"] } env_logger = "0.11" -prometheus_exporter_base = { version = "=1.4.0", features = ["hyper_server"] } tokio = { version = "1", features = [ "full" ] } async-trait = { version = "0.1" } dbc-rust-modules = { git = "https://github.com/dbcdk/rust-modules", branch = "main" } @@ -26,6 +25,9 @@ url = "2" chrono = "0.4" num-traits = "0.2" reqwest = { version = "0.12", features = ["blocking", "json"] } +prometheus = "0.14.0" +hyper = { version = "1.6.0", features = ["server"] } +hyper-util = "0.1.12" [profile.release] panic = "abort" diff --git a/nixos/vault-test.nix b/nixos/vault-test.nix index eb4d6ec..8017fea 100644 --- a/nixos/vault-test.nix +++ b/nixos/vault-test.nix @@ -165,5 +165,10 @@ testLib.mkFaytheTest ({ nodes, ... }: { client.fail(""" journalctl -u faythe | grep -q "dispatch task is gone: runtime dropped the dispatch task" """) + + with subtest("Has success metrics"): + client.succeed(""" + curl localhost:9105/metrics | grep -q 'faythe_issue_successes{cert="path1-test"} 1' + """) ''; }) diff --git a/src/main.rs b/src/main.rs index 85a3e21..f775abc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -106,6 +106,11 @@ async fn run(config: &FaytheConfig) { } let metrics_port = config.metrics_port; - threads.spawn(metrics::serve(metrics_port)); + + threads.spawn(async move { + if let Err(e) = metrics::serve(metrics_port).await { + eprintln!("Metrics server error: {}", e); + } + }); threads.join_all().await; } diff --git a/src/metrics.rs b/src/metrics.rs index 87b5a3f..4046f9a 100644 --- a/src/metrics.rs +++ b/src/metrics.rs @@ -1,12 +1,17 @@ -use prometheus_exporter_base::prelude::*; -use prometheus_exporter_base::PrometheusInstance; -use std::collections::HashMap; -use std::sync::RwLock; +use std::net::SocketAddr; +use hyper::body::Incoming; +use hyper::header::CONTENT_TYPE; +use hyper::server::conn::http1; +use hyper::service::service_fn; +use hyper::Request; +use hyper::Response; +use hyper_util::rt::TokioIo; +use lazy_static::lazy_static; +use prometheus::{Encoder, TextEncoder, IntCounterVec, register_int_counter_vec}; +use tokio::net::TcpListener; -use crate::log; -#[derive(Debug, Clone, Default)] -struct MyOptions {} +type BoxedErr = Box; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum MetricsType { @@ -14,73 +19,54 @@ pub enum MetricsType { Failure, } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct MetricsEvent { - pub cert_name: String, - pub event_type: MetricsType, -} - lazy_static! { - static ref EVENTS: RwLock> = RwLock::new(HashMap::new()); + static ref ISSUE_SUCCESS: IntCounterVec = register_int_counter_vec!( + "faythe_issue_successes", + "Succesfully issued certificates.", + &["cert"] + ) + .unwrap(); + static ref ISSUE_FAILURE: IntCounterVec = register_int_counter_vec!( + "faythe_issue_failures", + "Failed certificate issue attempts.", + &["cert"] + ) + .unwrap(); } pub fn new_event(cert_name: &str, event_type: MetricsType) { - let event = MetricsEvent { - cert_name: cert_name.to_string(), - event_type, - }; - let mut guard = EVENTS.write().unwrap(); - let new_value = match guard.remove(&event) { - Some(old_value) => old_value + 1, - None => 1, - }; - guard.insert(event, new_value); + match event_type { + MetricsType::Success => ISSUE_SUCCESS.with_label_values(&[cert_name]).inc(), + MetricsType::Failure => ISSUE_FAILURE.with_label_values(&[cert_name]).inc(), + } } -pub async fn serve(port: u16) { - let addr = ServerOptions { - addr: ([0, 0, 0, 0], port).into(), - authorization: Authorization::None, - }; +async fn serve_req(_req: Request) -> Result, BoxedErr> { + let encoder = TextEncoder::new(); - log::info(&format!("starting metrics server on port: {}", port)); + let metric_families = prometheus::gather(); + let body = encoder.encode_to_string(&metric_families)?; - render_prometheus( - addr, - MyOptions::default(), - |_request, _options| async move { - let mut successes = PrometheusMetric::build() - .with_name("faythe_issue_successes") - .with_metric_type(MetricType::Counter) - .with_help("Succesfully issued certificates") - .build(); + let response = Response::builder() + .status(200) + .header(CONTENT_TYPE, encoder.format_type()) + .body(body)?; - let mut failures = PrometheusMetric::build() - .with_name("faythe_issue_failures") - .with_metric_type(MetricType::Counter) - .with_help("Failed certificate issue attempts") - .build(); + Ok(response) +} - for (event, count) in EVENTS.read().unwrap().iter() { - match &event.event_type { - MetricsType::Success => { - successes.render_and_append_instance( - &PrometheusInstance::new() - .with_label("cert", event.cert_name.as_str()) - .with_value(*count), - ); - } - MetricsType::Failure => { - failures.render_and_append_instance( - &PrometheusInstance::new() - .with_label("cert", event.cert_name.as_str()) - .with_value(*count), - ); - } - } - } - Ok(format!("{}\n{}", successes.render(), failures.render())) - }, - ) - .await; +pub async fn serve(port: u16) -> Result<(), BoxedErr> { + let addr: SocketAddr = ([0, 0, 0, 0], port).into(); + println!("Listening on http://{}", addr); + let listener = TcpListener::bind(addr).await?; + + loop { + let (stream, _) = listener.accept().await?; + let io = TokioIo::new(stream); + + let service = service_fn(serve_req); + if let Err(err) = http1::Builder::new().serve_connection(io, service).await { + eprintln!("server error: {:?}", err); + }; + } }