Move `metrics::Serve` into its own module (#877)
With this change, metrics/mod.rs now contains only metrics types.
This commit is contained in:
parent
19e6a9c4a6
commit
29330b0dc1
|
@ -30,18 +30,7 @@ use std::default::Default;
|
||||||
use std::{fmt, time};
|
use std::{fmt, time};
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::sync::{Arc, Mutex};
|
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 indexmap::IndexMap;
|
||||||
|
|
||||||
use ctx;
|
use ctx;
|
||||||
|
@ -52,6 +41,7 @@ mod histogram;
|
||||||
mod labels;
|
mod labels;
|
||||||
mod latency;
|
mod latency;
|
||||||
mod record;
|
mod record;
|
||||||
|
mod serve;
|
||||||
|
|
||||||
use self::counter::Counter;
|
use self::counter::Counter;
|
||||||
use self::gauge::Gauge;
|
use self::gauge::Gauge;
|
||||||
|
@ -64,6 +54,7 @@ use self::labels::{
|
||||||
};
|
};
|
||||||
pub use self::labels::DstLabels;
|
pub use self::labels::DstLabels;
|
||||||
pub use self::record::Record;
|
pub use self::record::Record;
|
||||||
|
pub use self::serve::Serve;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct Metrics {
|
struct Metrics {
|
||||||
|
@ -96,12 +87,6 @@ struct Metric<M, L: Hash + Eq> {
|
||||||
values: IndexMap<L, M>
|
values: IndexMap<L, M>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serve Prometheues metrics.
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Serve {
|
|
||||||
metrics: Arc<Mutex<Metrics>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Construct the Prometheus metrics.
|
/// Construct the Prometheus metrics.
|
||||||
///
|
///
|
||||||
/// Returns the `Record` and `Serve` sides. The `Serve` side
|
/// 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(())
|
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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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))
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue