2020-05-04 13:27:58 +00:00
|
|
|
use prometheus::{Encoder, Registry, TextEncoder};
|
2020-04-24 10:56:04 +00:00
|
|
|
use std::{
|
|
|
|
error::Error,
|
|
|
|
net::SocketAddr,
|
|
|
|
sync::{
|
2020-05-04 13:27:58 +00:00
|
|
|
atomic::{AtomicBool, Ordering},
|
2020-04-24 10:56:04 +00:00
|
|
|
Arc,
|
|
|
|
},
|
|
|
|
thread,
|
|
|
|
};
|
2020-05-27 15:58:57 +00:00
|
|
|
use tiny_http;
|
|
|
|
use tracing::*;
|
2020-04-24 10:56:04 +00:00
|
|
|
|
|
|
|
pub struct SimpleMetrics {
|
|
|
|
running: Arc<AtomicBool>,
|
|
|
|
handle: Option<thread::JoinHandle<()>>,
|
|
|
|
registry: Option<Registry>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SimpleMetrics {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
let running = Arc::new(AtomicBool::new(false));
|
|
|
|
let registry = Some(Registry::new());
|
|
|
|
|
|
|
|
Self {
|
|
|
|
running,
|
|
|
|
handle: None,
|
|
|
|
registry,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn registry(&self) -> &Registry {
|
|
|
|
match self.registry {
|
|
|
|
Some(ref r) => r,
|
|
|
|
None => panic!("You cannot longer register new metrics after the server has started!"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn run(&mut self, addr: SocketAddr) -> Result<(), Box<dyn Error>> {
|
|
|
|
self.running.store(true, Ordering::Relaxed);
|
|
|
|
let running2 = self.running.clone();
|
|
|
|
|
|
|
|
let registry = self
|
|
|
|
.registry
|
|
|
|
.take()
|
|
|
|
.expect("ServerMetrics must be already started");
|
|
|
|
|
|
|
|
//TODO: make this a job
|
|
|
|
self.handle = Some(thread::spawn(move || {
|
2020-05-04 13:27:58 +00:00
|
|
|
let server = tiny_http::Server::http(addr).unwrap();
|
2020-05-15 12:29:17 +00:00
|
|
|
const TIMEOUT: std::time::Duration = std::time::Duration::from_secs(1);
|
2020-05-04 13:27:58 +00:00
|
|
|
debug!("starting tiny_http server to serve metrics");
|
2020-04-24 10:56:04 +00:00
|
|
|
while running2.load(Ordering::Relaxed) {
|
2020-05-15 12:29:17 +00:00
|
|
|
let request = match server.recv_timeout(TIMEOUT) {
|
2020-05-04 13:27:58 +00:00
|
|
|
Ok(Some(rq)) => rq,
|
|
|
|
Ok(None) => continue,
|
2020-05-27 15:58:57 +00:00
|
|
|
Err(e) => {
|
2020-07-05 22:13:53 +00:00
|
|
|
println!("Error: {}", e);
|
2020-05-27 15:58:57 +00:00
|
|
|
break;
|
|
|
|
},
|
2020-05-04 13:27:58 +00:00
|
|
|
};
|
|
|
|
let mf = registry.gather();
|
|
|
|
let encoder = TextEncoder::new();
|
|
|
|
let mut buffer = vec![];
|
2020-05-27 15:58:57 +00:00
|
|
|
encoder
|
|
|
|
.encode(&mf, &mut buffer)
|
|
|
|
.expect("Failed to encoder metrics text.");
|
|
|
|
let response = tiny_http::Response::from_string(
|
|
|
|
String::from_utf8(buffer).expect("Failed to parse bytes as a string."),
|
|
|
|
);
|
2020-05-15 12:29:17 +00:00
|
|
|
match request.respond(response) {
|
2020-05-27 15:58:57 +00:00
|
|
|
Err(e) => error!(
|
|
|
|
?e,
|
|
|
|
"The metrics HTTP server had encountered and error with answering"
|
|
|
|
),
|
2020-05-15 12:29:17 +00:00
|
|
|
_ => (),
|
|
|
|
}
|
2020-04-24 10:56:04 +00:00
|
|
|
}
|
2020-07-05 22:13:53 +00:00
|
|
|
debug!("Stopping tiny_http server to serve metrics");
|
2020-04-24 10:56:04 +00:00
|
|
|
}));
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for SimpleMetrics {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
self.running.store(false, Ordering::Relaxed);
|
|
|
|
let handle = self.handle.take();
|
|
|
|
handle
|
|
|
|
.expect("ServerMetrics worker handle does not exist.")
|
|
|
|
.join()
|
|
|
|
.expect("Error shutting down prometheus metric exporter");
|
|
|
|
}
|
2020-05-27 15:58:57 +00:00
|
|
|
}
|