diff --git a/Cargo.lock b/Cargo.lock index 96662d1..5983f7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,6 +21,12 @@ version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61" +[[package]] +name = "ascii" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbf56136a5198c7b01a49e3afcbef6cf84597273d298f54432926024107b0109" + [[package]] name = "atty" version = "0.2.14" @@ -44,16 +50,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" -[[package]] -name = "base64" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -dependencies = [ - "byteorder", - "safemem", -] - [[package]] name = "base64-compat" version = "1.0.0" @@ -117,7 +113,7 @@ source = "git+https://github.com/romanz/rust-bitcoincore-rpc?rev=06ac9fa3e834413 dependencies = [ "bitcoincore-rpc-json", "jsonrpc", - "log 0.4.14", + "log", "serde", "serde_json", ] @@ -185,6 +181,24 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "winapi", +] + +[[package]] +name = "chunked_transfer" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e" + [[package]] name = "clang-sys" version = "1.2.0" @@ -325,8 +339,7 @@ dependencies = [ "crossbeam-channel", "dirs-next", "env_logger", - "hyper", - "log 0.4.14", + "log", "parking_lot", "prometheus", "rayon", @@ -335,6 +348,7 @@ dependencies = [ "serde_derive", "serde_json", "signal-hook", + "tiny_http", ] [[package]] @@ -345,7 +359,7 @@ checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" dependencies = [ "atty", "humantime", - "log 0.4.14", + "log", "regex", "termcolor", ] @@ -374,6 +388,16 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -412,12 +436,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "httparse" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a87b616e37e93c22fb19bcd386f02f3af5ea98a25670ad0fce773de23c5e68" - [[package]] name = "humantime" version = "1.3.0" @@ -427,30 +445,11 @@ dependencies = [ "quick-error", ] -[[package]] -name = "hyper" -version = "0.10.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" -dependencies = [ - "base64", - "httparse", - "language-tags", - "log 0.3.9", - "mime", - "num_cpus", - "time", - "traitobject", - "typeable", - "unicase", - "url", -] - [[package]] name = "idna" -version = "0.1.5" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" dependencies = [ "matches", "unicode-bidi", @@ -493,12 +492,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" - [[package]] name = "lazy_static" version = "1.4.0" @@ -547,15 +540,6 @@ dependencies = [ "scopeguard", ] -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -dependencies = [ - "log 0.4.14", -] - [[package]] name = "log" version = "0.4.14" @@ -595,15 +579,6 @@ dependencies = [ "autocfg 1.0.1", ] -[[package]] -name = "mime" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -dependencies = [ - "log 0.3.9", -] - [[package]] name = "miniz_oxide" version = "0.4.4" @@ -621,7 +596,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" dependencies = [ "memchr", - "version_check 0.9.3", + "version_check", +] + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg 1.0.1", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg 1.0.1", ] [[package]] @@ -673,9 +667,9 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "percent-encoding" -version = "1.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "proc-macro2" @@ -941,12 +935,6 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" -[[package]] -name = "safemem" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" - [[package]] name = "scopeguard" version = "1.1.0" @@ -1076,13 +1064,16 @@ dependencies = [ ] [[package]] -name = "time" -version = "0.1.43" +name = "tiny_http" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "9ce51b50006056f590c9b7c3808c3bd70f0d1101666629713866c227d6e58d39" dependencies = [ - "libc", - "winapi", + "ascii", + "chrono", + "chunked_transfer", + "log", + "url", ] [[package]] @@ -1109,27 +1100,6 @@ dependencies = [ "serde", ] -[[package]] -name = "traitobject" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" - -[[package]] -name = "typeable" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" - -[[package]] -name = "unicase" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -dependencies = [ - "version_check 0.1.5", -] - [[package]] name = "unicode-bidi" version = "0.3.5" @@ -1162,21 +1132,16 @@ checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "url" -version = "1.7.2" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" dependencies = [ + "form_urlencoded", "idna", "matches", "percent-encoding", ] -[[package]] -name = "version_check" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" - [[package]] name = "version_check" version = "0.9.3" diff --git a/Cargo.toml b/Cargo.toml index 678de52..34fabe4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ build = "build.rs" [features] default = ["metrics"] -metrics = ["prometheus", "hyper"] +metrics = ["prometheus", "tiny_http"] [package.metadata.configure_me] spec = "internal/config_specification.toml" @@ -26,7 +26,6 @@ configure_me = "0.4" crossbeam-channel = "0.5" dirs-next = "2.0" env_logger = "0.7" -hyper = { version = "0.10", optional = true } log = "0.4" parking_lot = "0.11" prometheus = { version = "0.12", features = ["process"], optional = true } @@ -35,6 +34,7 @@ serde = "1.0" serde_derive = "1.0" serde_json = "1.0" signal-hook = "0.3" +tiny_http = { version = "0.8", optional = true } [dependencies.bitcoincore-rpc] # use bitcoin 0.27 (until https://github.com/rust-bitcoin/rust-bitcoincore-rpc/pull/196 is merged) diff --git a/src/metrics.rs b/src/metrics.rs index 102c4f7..5e8bb44 100644 --- a/src/metrics.rs +++ b/src/metrics.rs @@ -1,15 +1,16 @@ #[cfg(feature = "metrics")] mod metrics_impl { use anyhow::{Context, Result}; - use hyper::server::{Handler, Listening, Request, Response, Server}; use prometheus::process_collector::ProcessCollector; use prometheus::{self, Encoder, HistogramOpts, HistogramVec, Registry}; + use tiny_http::{Response, Server}; use std::net::SocketAddr; + use crate::thread::spawn; + pub struct Metrics { reg: Registry, - listen: Listening, } impl Metrics { @@ -19,11 +20,24 @@ mod metrics_impl { reg.register(Box::new(ProcessCollector::for_self())) .expect("failed to register ProcessCollector"); - let listen = Server::http(addr)? - .handle(RegistryHandler { reg: reg.clone() }) - .with_context(|| format!("failed to serve on {}", addr))?; + let result = Self { reg }; + let reg = result.reg.clone(); + spawn("metrics", move || { + let server = Server::http(addr).unwrap(); + for request in server.incoming_requests() { + let mut buffer = vec![]; + prometheus::TextEncoder::new() + .encode(®.gather(), &mut buffer) + .context("failed to encode metrics")?; + request + .respond(Response::from_data(buffer)) + .context("failed to send HTTP response")?; + } + Ok(()) + }); + info!("serving Prometheus metrics on {}", addr); - Ok(Self { reg, listen }) + Ok(result) } pub fn histogram_vec(&self, name: &str, desc: &str, label: &str) -> Histogram { @@ -36,15 +50,6 @@ mod metrics_impl { } } - impl Drop for Metrics { - fn drop(&mut self) { - debug!("closing Prometheus server"); - if let Err(e) = self.listen.close() { - warn!("failed to stop Prometheus server: {}", e); - } - } - } - #[derive(Clone)] pub struct Histogram { hist: HistogramVec, @@ -64,28 +69,6 @@ mod metrics_impl { .observe_closure_duration(func) } } - - struct RegistryHandler { - reg: Registry, - } - - impl RegistryHandler { - fn gather(&self) -> Result> { - let mut buffer = vec![]; - prometheus::TextEncoder::new() - .encode(&self.reg.gather(), &mut buffer) - .context("failed to encode metrics")?; - Ok(buffer) - } - } - - impl Handler for RegistryHandler { - fn handle(&self, req: Request, res: Response) { - trace!("{} {}", req.method, req.uri); - let buffer = self.gather().expect("failed to gather metrics"); - res.send(&buffer).expect("failed to send metrics"); - } - } } #[cfg(feature = "metrics")] diff --git a/src/server.rs b/src/server.rs index 4dd0460..b9b4ece 100644 --- a/src/server.rs +++ b/src/server.rs @@ -9,7 +9,6 @@ use std::{ convert::TryFrom, io::{BufRead, BufReader, Write}, net::{Shutdown, TcpListener, TcpStream}, - thread, }; use crate::{ @@ -17,22 +16,9 @@ use crate::{ daemon::rpc_connect, electrum::{Client, Rpc}, signals, + thread::spawn, }; -fn spawn(name: &'static str, f: F) -> thread::JoinHandle<()> -where - F: 'static + Send + FnOnce() -> Result<()>, -{ - thread::Builder::new() - .name(name.to_owned()) - .spawn(move || { - if let Err(e) = f() { - warn!("{} thread failed: {}", name, e); - } - }) - .expect("failed to spawn a thread") -} - struct Peer { id: usize, client: Client,