Move `metrics::Serve` into its own module (#877)

With this change, metrics/mod.rs now contains only metrics types.
This commit is contained in:
Oliver Gould 2018-04-30 10:52:08 -07:00 committed by GitHub
parent 84d131b6b0
commit f73fdc1eae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 79 deletions

View File

@ -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<M, L: Hash + Eq> {
values: IndexMap<L, M>
}
/// Serve Prometheues metrics.
#[derive(Debug, Clone)]
pub struct Serve {
metrics: Arc<Mutex<Metrics>>,
}
/// Construct the Prometheus metrics.
///
/// Returns the `Record` and `Serve` sides. The `Serve` side
@ -393,65 +378,3 @@ impl<L, V> fmt::Display for Metric<Histogram<V>, L> where
Ok(())
}
}
// ===== impl Serve =====
impl Serve {
fn new(metrics: &Arc<Mutex<Metrics>>) -> Self {
Serve {
metrics: metrics.clone(),
}
}
}
fn is_gzip(req: &HyperRequest) -> bool {
if let Some(accept_encodings) = req
.headers()
.get::<AcceptEncoding>()
{
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<Self::Response, Self::Error>;
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::<u8>::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::<u8>::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))
}
}

View File

@ -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<Mutex<Metrics>>,
}
// ===== impl Serve =====
impl Serve {
pub(super) fn new(metrics: &Arc<Mutex<Metrics>>) -> Self {
Serve {
metrics: metrics.clone(),
}
}
fn is_gzip(req: &Request) -> bool {
if let Some(accept_encodings) = req
.headers()
.get::<AcceptEncoding>()
{
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<Self::Response, Self::Error>;
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::<u8>::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::<u8>::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))
}
}