From 29330b0dc14d9d4634077d1badf2b16d532e1185 Mon Sep 17 00:00:00 2001 From: Oliver Gould Date: Mon, 30 Apr 2018 10:52:08 -0700 Subject: [PATCH] Move `metrics::Serve` into its own module (#877) With this change, metrics/mod.rs now contains only metrics types. --- proxy/src/telemetry/metrics/mod.rs | 81 +--------------------------- proxy/src/telemetry/metrics/serve.rs | 78 +++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 79 deletions(-) create mode 100644 proxy/src/telemetry/metrics/serve.rs diff --git a/proxy/src/telemetry/metrics/mod.rs b/proxy/src/telemetry/metrics/mod.rs index 712035b56..996cc119e 100644 --- a/proxy/src/telemetry/metrics/mod.rs +++ b/proxy/src/telemetry/metrics/mod.rs @@ -30,18 +30,7 @@ use std::default::Default; use std::{fmt, time}; use std::hash::Hash; use std::sync::{Arc, Mutex}; -use std::io::Write; -use deflate::CompressionOptions; -use deflate::write::GzEncoder; -use futures::future::{self, FutureResult}; -use hyper::{self, Body, StatusCode}; -use hyper::header::{AcceptEncoding, ContentEncoding, ContentType, Encoding, QualityItem}; -use hyper::server::{ - Response as HyperResponse, - Request as HyperRequest, - Service as HyperService, -}; use indexmap::IndexMap; use ctx; @@ -52,6 +41,7 @@ mod histogram; mod labels; mod latency; mod record; +mod serve; use self::counter::Counter; use self::gauge::Gauge; @@ -64,6 +54,7 @@ use self::labels::{ }; pub use self::labels::DstLabels; pub use self::record::Record; +pub use self::serve::Serve; #[derive(Debug, Clone)] struct Metrics { @@ -96,12 +87,6 @@ struct Metric { values: IndexMap } -/// Serve Prometheues metrics. -#[derive(Debug, Clone)] -pub struct Serve { - metrics: Arc>, -} - /// Construct the Prometheus metrics. /// /// Returns the `Record` and `Serve` sides. The `Serve` side @@ -393,65 +378,3 @@ impl fmt::Display for Metric, L> where Ok(()) } } - -// ===== impl Serve ===== - -impl Serve { - fn new(metrics: &Arc>) -> Self { - Serve { - metrics: metrics.clone(), - } - } -} - -fn is_gzip(req: &HyperRequest) -> bool { - if let Some(accept_encodings) = req - .headers() - .get::() - { - return accept_encodings - .iter() - .any(|&QualityItem { ref item, .. }| item == &Encoding::Gzip) - } - false -} - -impl HyperService for Serve { - type Request = HyperRequest; - type Response = HyperResponse; - type Error = hyper::Error; - type Future = FutureResult; - - fn call(&self, req: Self::Request) -> Self::Future { - if req.path() != "/metrics" { - return future::ok(HyperResponse::new() - .with_status(StatusCode::NotFound)); - } - - let metrics = self.metrics.lock() - .expect("metrics lock poisoned"); - - let resp = if is_gzip(&req) { - trace!("gzipping metrics"); - let mut writer = GzEncoder::new(Vec::::new(), CompressionOptions::fast()); - write!(&mut writer, "{}", *metrics) - .and_then(|_| writer.finish()) - .map(|body| { - HyperResponse::new() - .with_header(ContentEncoding(vec![Encoding::Gzip])) - .with_header(ContentType::plaintext()) - .with_body(Body::from(body)) - }) - } else { - let mut writer = Vec::::new(); - write!(&mut writer, "{}", *metrics) - .map(|_| { - HyperResponse::new() - .with_header(ContentType::plaintext()) - .with_body(Body::from(writer)) - }) - }; - - future::result(resp.map_err(hyper::Error::Io)) - } -} diff --git a/proxy/src/telemetry/metrics/serve.rs b/proxy/src/telemetry/metrics/serve.rs new file mode 100644 index 000000000..bae2d97c2 --- /dev/null +++ b/proxy/src/telemetry/metrics/serve.rs @@ -0,0 +1,78 @@ +use deflate::CompressionOptions; +use deflate::write::GzEncoder; +use futures::future::{self, FutureResult}; +use hyper::{self, Body, StatusCode}; +use hyper::header::{AcceptEncoding, ContentEncoding, ContentType, Encoding, QualityItem}; +use hyper::server::{Request, Response, Service}; +use std::io::Write; +use std::sync::{Arc, Mutex}; + +use super::Metrics; + +/// Serve Prometheues metrics. +#[derive(Debug, Clone)] +pub struct Serve { + metrics: Arc>, +} + +// ===== impl Serve ===== + +impl Serve { + pub(super) fn new(metrics: &Arc>) -> Self { + Serve { + metrics: metrics.clone(), + } + } + + fn is_gzip(req: &Request) -> bool { + if let Some(accept_encodings) = req + .headers() + .get::() + { + return accept_encodings + .iter() + .any(|&QualityItem { ref item, .. }| item == &Encoding::Gzip) + } + false + } +} + +impl Service for Serve { + type Request = Request; + type Response = Response; + type Error = hyper::Error; + type Future = FutureResult; + + fn call(&self, req: Self::Request) -> Self::Future { + if req.path() != "/metrics" { + return future::ok(Response::new() + .with_status(StatusCode::NotFound)); + } + + let metrics = self.metrics.lock() + .expect("metrics lock poisoned"); + + let resp = if Self::is_gzip(&req) { + trace!("gzipping metrics"); + let mut writer = GzEncoder::new(Vec::::new(), CompressionOptions::fast()); + write!(&mut writer, "{}", *metrics) + .and_then(|_| writer.finish()) + .map(|body| { + Response::new() + .with_header(ContentEncoding(vec![Encoding::Gzip])) + .with_header(ContentType::plaintext()) + .with_body(Body::from(body)) + }) + } else { + let mut writer = Vec::::new(); + write!(&mut writer, "{}", *metrics) + .map(|_| { + Response::new() + .with_header(ContentType::plaintext()) + .with_body(Body::from(writer)) + }) + }; + + future::result(resp.map_err(hyper::Error::Io)) + } +}