2020-09-13 16:26:50 +00:00
|
|
|
|
use prometheus::{
|
2020-09-14 12:56:05 +00:00
|
|
|
|
Encoder, Gauge, HistogramOpts, HistogramVec, IntCounter, IntCounterVec, IntGauge, IntGaugeVec,
|
|
|
|
|
Opts, Registry, TextEncoder,
|
2020-09-13 16:26:50 +00:00
|
|
|
|
};
|
2019-09-10 13:22:34 +00:00
|
|
|
|
use std::{
|
|
|
|
|
convert::TryInto,
|
2020-02-01 20:39:39 +00:00
|
|
|
|
error::Error,
|
2019-10-11 12:19:55 +00:00
|
|
|
|
net::SocketAddr,
|
2019-09-10 13:22:34 +00:00
|
|
|
|
sync::{
|
2020-02-19 17:08:57 +00:00
|
|
|
|
atomic::{AtomicBool, AtomicU64, Ordering},
|
2019-09-10 13:22:34 +00:00
|
|
|
|
Arc,
|
|
|
|
|
},
|
|
|
|
|
thread,
|
2019-09-20 04:41:44 +00:00
|
|
|
|
time::{Duration, SystemTime, UNIX_EPOCH},
|
2019-09-10 13:22:34 +00:00
|
|
|
|
};
|
2020-06-21 14:26:06 +00:00
|
|
|
|
use tracing::{debug, error};
|
2019-09-06 14:21:09 +00:00
|
|
|
|
|
2020-09-13 16:26:50 +00:00
|
|
|
|
type RegistryFn = Box<dyn FnOnce(&Registry) -> Result<(), prometheus::Error>>;
|
|
|
|
|
|
2020-10-20 16:31:19 +00:00
|
|
|
|
pub struct PhysicsMetrics {
|
|
|
|
|
pub velocities_cache_len: IntGauge,
|
|
|
|
|
pub entity_entity_collision_checks_count: IntCounter,
|
|
|
|
|
pub entity_entity_collisions_count: IntCounter,
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-14 12:56:05 +00:00
|
|
|
|
pub struct StateTickMetrics {
|
|
|
|
|
// Counter will only give us granularity on pool speed (2s?) for actuall spike detection we
|
|
|
|
|
// need the Historgram
|
|
|
|
|
pub state_tick_time_hist: HistogramVec,
|
|
|
|
|
pub state_tick_time_count: IntCounterVec,
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-13 16:26:50 +00:00
|
|
|
|
pub struct PlayerMetrics {
|
2020-09-16 22:19:48 +00:00
|
|
|
|
pub clients_connected: IntCounter,
|
2020-09-13 16:26:50 +00:00
|
|
|
|
pub players_connected: IntCounter,
|
2020-09-16 22:19:48 +00:00
|
|
|
|
pub clients_disconnected: IntCounterVec, // timeout, network_error, gracefully
|
2020-09-13 16:26:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct NetworkRequestMetrics {
|
|
|
|
|
pub chunks_request_dropped: IntCounter,
|
2020-09-14 12:56:05 +00:00
|
|
|
|
pub chunks_served_from_memory: IntCounter,
|
2020-09-13 16:26:50 +00:00
|
|
|
|
pub chunks_generation_triggered: IntCounter,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct ChunkGenMetrics {
|
|
|
|
|
pub chunks_requested: IntCounter,
|
|
|
|
|
pub chunks_served: IntCounter,
|
|
|
|
|
pub chunks_canceled: IntCounter,
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-19 17:08:57 +00:00
|
|
|
|
pub struct TickMetrics {
|
2019-09-09 08:46:58 +00:00
|
|
|
|
pub chonks_count: IntGauge,
|
|
|
|
|
pub chunks_count: IntGauge,
|
2020-09-28 11:35:49 +00:00
|
|
|
|
pub chunk_groups_count: IntGauge,
|
2019-09-07 13:10:57 +00:00
|
|
|
|
pub entity_count: IntGauge,
|
|
|
|
|
pub tick_time: IntGaugeVec,
|
|
|
|
|
pub build_info: IntGauge,
|
2019-09-10 13:22:34 +00:00
|
|
|
|
pub start_time: IntGauge,
|
|
|
|
|
pub time_of_day: Gauge,
|
2019-09-07 13:10:57 +00:00
|
|
|
|
pub light_count: IntGauge,
|
2020-02-19 17:08:57 +00:00
|
|
|
|
tick: Arc<AtomicU64>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct ServerMetrics {
|
2019-09-20 04:41:44 +00:00
|
|
|
|
running: Arc<AtomicBool>,
|
2020-02-19 17:08:57 +00:00
|
|
|
|
handle: Option<thread::JoinHandle<()>>,
|
|
|
|
|
registry: Option<Registry>,
|
|
|
|
|
tick: Arc<AtomicU64>,
|
2019-09-06 14:21:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-10-20 16:31:19 +00:00
|
|
|
|
impl PhysicsMetrics {
|
|
|
|
|
pub fn new() -> Result<(Self, RegistryFn), prometheus::Error> {
|
|
|
|
|
let velocities_cache_len = IntGauge::with_opts(Opts::new(
|
|
|
|
|
"velocities_cache_len",
|
|
|
|
|
"shows the size of the velocities_cache in entries",
|
|
|
|
|
))?;
|
|
|
|
|
let entity_entity_collision_checks_count = IntCounter::with_opts(Opts::new(
|
|
|
|
|
"entity_entity_collision_checks_count",
|
|
|
|
|
"shows the number of collision checks",
|
|
|
|
|
))?;
|
|
|
|
|
let entity_entity_collisions_count = IntCounter::with_opts(Opts::new(
|
|
|
|
|
"entity_entity_collisions_count",
|
|
|
|
|
"shows the number of actual collisions detected",
|
|
|
|
|
))?;
|
|
|
|
|
|
|
|
|
|
let velocities_cache_len_clone = velocities_cache_len.clone();
|
|
|
|
|
let entity_entity_collision_checks_count_clone =
|
|
|
|
|
entity_entity_collision_checks_count.clone();
|
|
|
|
|
let entity_entity_collisions_count_clone = entity_entity_collisions_count.clone();
|
|
|
|
|
|
|
|
|
|
let f = |registry: &Registry| {
|
|
|
|
|
registry.register(Box::new(velocities_cache_len_clone))?;
|
|
|
|
|
registry.register(Box::new(entity_entity_collision_checks_count_clone))?;
|
|
|
|
|
registry.register(Box::new(entity_entity_collisions_count_clone))?;
|
|
|
|
|
Ok(())
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Ok((
|
|
|
|
|
Self {
|
|
|
|
|
velocities_cache_len,
|
|
|
|
|
entity_entity_collision_checks_count,
|
|
|
|
|
entity_entity_collisions_count,
|
|
|
|
|
},
|
|
|
|
|
Box::new(f),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-14 12:56:05 +00:00
|
|
|
|
impl StateTickMetrics {
|
|
|
|
|
pub fn new() -> Result<(Self, RegistryFn), prometheus::Error> {
|
|
|
|
|
let bucket = vec![
|
|
|
|
|
Duration::from_micros(1).as_secs_f64(),
|
|
|
|
|
Duration::from_micros(10).as_secs_f64(),
|
|
|
|
|
Duration::from_micros(100).as_secs_f64(),
|
|
|
|
|
Duration::from_micros(200).as_secs_f64(),
|
|
|
|
|
Duration::from_micros(400).as_secs_f64(),
|
|
|
|
|
Duration::from_millis(2).as_secs_f64(),
|
|
|
|
|
Duration::from_millis(5).as_secs_f64(),
|
|
|
|
|
Duration::from_millis(10).as_secs_f64(),
|
|
|
|
|
Duration::from_millis(20).as_secs_f64(),
|
|
|
|
|
Duration::from_millis(30).as_secs_f64(),
|
|
|
|
|
Duration::from_millis(50).as_secs_f64(),
|
|
|
|
|
Duration::from_millis(100).as_secs_f64(),
|
|
|
|
|
];
|
|
|
|
|
let state_tick_time_hist = HistogramVec::new(
|
|
|
|
|
HistogramOpts::new(
|
|
|
|
|
"state_tick_time_hist",
|
|
|
|
|
"shows the number of clients joined to the server",
|
|
|
|
|
)
|
|
|
|
|
.buckets(bucket),
|
|
|
|
|
&["system"],
|
|
|
|
|
)?;
|
|
|
|
|
let state_tick_time_count = IntCounterVec::new(
|
|
|
|
|
Opts::new(
|
|
|
|
|
"state_tick_time_count",
|
|
|
|
|
"shows the detailed time inside the `state_tick` for each system",
|
|
|
|
|
),
|
|
|
|
|
&["system"],
|
|
|
|
|
)?;
|
|
|
|
|
|
|
|
|
|
let state_tick_time_hist_clone = state_tick_time_hist.clone();
|
|
|
|
|
let state_tick_time_count_clone = state_tick_time_count.clone();
|
|
|
|
|
|
|
|
|
|
let f = |registry: &Registry| {
|
|
|
|
|
registry.register(Box::new(state_tick_time_hist_clone))?;
|
|
|
|
|
registry.register(Box::new(state_tick_time_count_clone))?;
|
|
|
|
|
Ok(())
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Ok((
|
|
|
|
|
Self {
|
|
|
|
|
state_tick_time_hist,
|
|
|
|
|
state_tick_time_count,
|
|
|
|
|
},
|
|
|
|
|
Box::new(f),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-13 16:26:50 +00:00
|
|
|
|
impl PlayerMetrics {
|
|
|
|
|
pub fn new() -> Result<(Self, RegistryFn), prometheus::Error> {
|
2020-09-16 22:19:48 +00:00
|
|
|
|
let clients_connected = IntCounter::with_opts(Opts::new(
|
|
|
|
|
"clients_connected",
|
|
|
|
|
"shows the number of clients joined to the server",
|
|
|
|
|
))?;
|
2020-09-13 16:26:50 +00:00
|
|
|
|
let players_connected = IntCounter::with_opts(Opts::new(
|
|
|
|
|
"players_connected",
|
2020-09-16 22:19:48 +00:00
|
|
|
|
"shows the number of players joined to the server. A player is a client, that \
|
|
|
|
|
registers itself. Bots are not players (but clients)",
|
2020-09-13 16:26:50 +00:00
|
|
|
|
))?;
|
2020-09-16 22:19:48 +00:00
|
|
|
|
let clients_disconnected = IntCounterVec::new(
|
2020-09-13 16:26:50 +00:00
|
|
|
|
Opts::new(
|
2020-09-16 22:19:48 +00:00
|
|
|
|
"clients_disconnected",
|
2020-09-13 16:26:50 +00:00
|
|
|
|
"shows the number of clients disconnected from the server and the reason",
|
|
|
|
|
),
|
|
|
|
|
&["reason"],
|
|
|
|
|
)?;
|
|
|
|
|
|
2020-09-16 22:19:48 +00:00
|
|
|
|
let clients_connected_clone = clients_connected.clone();
|
2020-09-13 16:26:50 +00:00
|
|
|
|
let players_connected_clone = players_connected.clone();
|
2020-09-16 22:19:48 +00:00
|
|
|
|
let clients_disconnected_clone = clients_disconnected.clone();
|
2020-09-13 16:26:50 +00:00
|
|
|
|
|
|
|
|
|
let f = |registry: &Registry| {
|
2020-09-16 22:19:48 +00:00
|
|
|
|
registry.register(Box::new(clients_connected_clone))?;
|
2020-09-13 16:26:50 +00:00
|
|
|
|
registry.register(Box::new(players_connected_clone))?;
|
2020-09-16 22:19:48 +00:00
|
|
|
|
registry.register(Box::new(clients_disconnected_clone))?;
|
2020-09-13 16:26:50 +00:00
|
|
|
|
Ok(())
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Ok((
|
|
|
|
|
Self {
|
2020-09-16 22:19:48 +00:00
|
|
|
|
clients_connected,
|
2020-09-13 16:26:50 +00:00
|
|
|
|
players_connected,
|
2020-09-16 22:19:48 +00:00
|
|
|
|
clients_disconnected,
|
2020-09-13 16:26:50 +00:00
|
|
|
|
},
|
|
|
|
|
Box::new(f),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl NetworkRequestMetrics {
|
|
|
|
|
pub fn new() -> Result<(Self, RegistryFn), prometheus::Error> {
|
|
|
|
|
let chunks_request_dropped = IntCounter::with_opts(Opts::new(
|
|
|
|
|
"chunks_request_dropped",
|
|
|
|
|
"number of all chunk request dropped, e.g because the player was to far away",
|
|
|
|
|
))?;
|
2020-09-14 12:56:05 +00:00
|
|
|
|
let chunks_served_from_memory = IntCounter::with_opts(Opts::new(
|
|
|
|
|
"chunks_served_from_memory",
|
2020-09-13 16:26:50 +00:00
|
|
|
|
"number of all requested chunks already generated and could be served out of cache",
|
|
|
|
|
))?;
|
|
|
|
|
let chunks_generation_triggered = IntCounter::with_opts(Opts::new(
|
|
|
|
|
"chunks_generation_triggered",
|
|
|
|
|
"number of all chunks that were requested and needs to be generated",
|
|
|
|
|
))?;
|
|
|
|
|
|
|
|
|
|
let chunks_request_dropped_clone = chunks_request_dropped.clone();
|
2020-09-14 12:56:05 +00:00
|
|
|
|
let chunks_served_from_memory_clone = chunks_served_from_memory.clone();
|
2020-09-13 16:26:50 +00:00
|
|
|
|
let chunks_generation_triggered_clone = chunks_generation_triggered.clone();
|
|
|
|
|
|
|
|
|
|
let f = |registry: &Registry| {
|
|
|
|
|
registry.register(Box::new(chunks_request_dropped_clone))?;
|
2020-09-14 12:56:05 +00:00
|
|
|
|
registry.register(Box::new(chunks_served_from_memory_clone))?;
|
2020-09-13 16:26:50 +00:00
|
|
|
|
registry.register(Box::new(chunks_generation_triggered_clone))?;
|
|
|
|
|
Ok(())
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Ok((
|
|
|
|
|
Self {
|
|
|
|
|
chunks_request_dropped,
|
2020-09-14 12:56:05 +00:00
|
|
|
|
chunks_served_from_memory,
|
2020-09-13 16:26:50 +00:00
|
|
|
|
chunks_generation_triggered,
|
|
|
|
|
},
|
|
|
|
|
Box::new(f),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ChunkGenMetrics {
|
|
|
|
|
pub fn new() -> Result<(Self, RegistryFn), prometheus::Error> {
|
|
|
|
|
let chunks_requested = IntCounter::with_opts(Opts::new(
|
|
|
|
|
"chunks_requested",
|
|
|
|
|
"number of all chunks requested on the server",
|
|
|
|
|
))?;
|
|
|
|
|
let chunks_served = IntCounter::with_opts(Opts::new(
|
|
|
|
|
"chunks_served",
|
|
|
|
|
"number of all requested chunks already served on the server",
|
|
|
|
|
))?;
|
|
|
|
|
let chunks_canceled = IntCounter::with_opts(Opts::new(
|
|
|
|
|
"chunks_canceled",
|
|
|
|
|
"number of all canceled chunks on the server",
|
|
|
|
|
))?;
|
|
|
|
|
|
|
|
|
|
let chunks_requested_clone = chunks_requested.clone();
|
|
|
|
|
let chunks_served_clone = chunks_served.clone();
|
|
|
|
|
let chunks_canceled_clone = chunks_canceled.clone();
|
|
|
|
|
|
|
|
|
|
let f = |registry: &Registry| {
|
|
|
|
|
registry.register(Box::new(chunks_requested_clone))?;
|
|
|
|
|
registry.register(Box::new(chunks_served_clone))?;
|
|
|
|
|
registry.register(Box::new(chunks_canceled_clone))?;
|
|
|
|
|
Ok(())
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Ok((
|
|
|
|
|
Self {
|
|
|
|
|
chunks_requested,
|
|
|
|
|
chunks_served,
|
|
|
|
|
chunks_canceled,
|
|
|
|
|
},
|
|
|
|
|
Box::new(f),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-19 17:08:57 +00:00
|
|
|
|
impl TickMetrics {
|
2020-09-13 16:26:50 +00:00
|
|
|
|
pub fn new(tick: Arc<AtomicU64>) -> Result<(Self, RegistryFn), Box<dyn Error>> {
|
|
|
|
|
let chonks_count = IntGauge::with_opts(Opts::new(
|
|
|
|
|
"chonks_count",
|
|
|
|
|
"number of all chonks currently active on the server",
|
|
|
|
|
))?;
|
|
|
|
|
let chunks_count = IntGauge::with_opts(Opts::new(
|
|
|
|
|
"chunks_count",
|
|
|
|
|
"number of all chunks currently active on the server",
|
2020-02-19 17:08:57 +00:00
|
|
|
|
))?;
|
2020-09-28 11:35:49 +00:00
|
|
|
|
let chunk_groups_count = IntGauge::with_opts(Opts::new(
|
|
|
|
|
"chunk_groups_count",
|
|
|
|
|
"number of 4×4×4 groups currently allocated by chunks on the server",
|
|
|
|
|
))?;
|
2020-02-19 17:08:57 +00:00
|
|
|
|
let entity_count = IntGauge::with_opts(Opts::new(
|
2019-09-07 13:10:57 +00:00
|
|
|
|
"entity_count",
|
|
|
|
|
"number of all entities currently active on the server",
|
2020-02-19 17:08:57 +00:00
|
|
|
|
))?;
|
2019-09-06 14:21:09 +00:00
|
|
|
|
let opts = Opts::new("veloren_build_info", "Build information")
|
2019-10-18 13:32:26 +00:00
|
|
|
|
.const_label("hash", &common::util::GIT_HASH)
|
2019-09-06 14:21:09 +00:00
|
|
|
|
.const_label("version", "");
|
2019-10-23 16:38:09 +00:00
|
|
|
|
let build_info = IntGauge::with_opts(opts)?;
|
2020-02-19 17:08:57 +00:00
|
|
|
|
let start_time = IntGauge::with_opts(Opts::new(
|
2019-09-10 13:22:34 +00:00
|
|
|
|
"veloren_start_time",
|
|
|
|
|
"start time of the server in seconds since EPOCH",
|
2020-02-19 17:08:57 +00:00
|
|
|
|
))?;
|
|
|
|
|
let time_of_day =
|
|
|
|
|
Gauge::with_opts(Opts::new("time_of_day", "ingame time in ingame-seconds"))?;
|
|
|
|
|
let light_count = IntGauge::with_opts(Opts::new(
|
2019-09-07 13:10:57 +00:00
|
|
|
|
"light_count",
|
|
|
|
|
"number of all lights currently active on the server",
|
2020-02-19 17:08:57 +00:00
|
|
|
|
))?;
|
2020-07-13 19:57:13 +00:00
|
|
|
|
let tick_time = IntGaugeVec::new(
|
2020-08-25 12:21:25 +00:00
|
|
|
|
Opts::new("tick_time", "time in ns required for a tick of the server"),
|
2019-09-07 13:10:57 +00:00
|
|
|
|
&["period"],
|
2020-07-13 19:57:13 +00:00
|
|
|
|
)?;
|
2019-09-06 14:21:09 +00:00
|
|
|
|
|
2019-09-10 13:22:34 +00:00
|
|
|
|
let since_the_epoch = SystemTime::now()
|
|
|
|
|
.duration_since(UNIX_EPOCH)
|
|
|
|
|
.expect("Time went backwards");
|
2019-10-23 16:38:09 +00:00
|
|
|
|
start_time.set(since_the_epoch.as_secs().try_into()?);
|
2019-09-10 13:22:34 +00:00
|
|
|
|
|
2020-09-13 16:26:50 +00:00
|
|
|
|
let chonks_count_clone = chonks_count.clone();
|
|
|
|
|
let chunks_count_clone = chunks_count.clone();
|
2020-09-28 11:35:49 +00:00
|
|
|
|
let chunk_groups_count_clone = chunk_groups_count.clone();
|
2020-09-13 16:26:50 +00:00
|
|
|
|
let entity_count_clone = entity_count.clone();
|
|
|
|
|
let build_info_clone = build_info.clone();
|
|
|
|
|
let start_time_clone = start_time.clone();
|
|
|
|
|
let time_of_day_clone = time_of_day.clone();
|
|
|
|
|
let light_count_clone = light_count.clone();
|
|
|
|
|
let tick_time_clone = tick_time.clone();
|
|
|
|
|
|
|
|
|
|
let f = |registry: &Registry| {
|
|
|
|
|
registry.register(Box::new(chonks_count_clone))?;
|
|
|
|
|
registry.register(Box::new(chunks_count_clone))?;
|
2020-09-28 11:35:49 +00:00
|
|
|
|
registry.register(Box::new(chunk_groups_count_clone))?;
|
2020-09-13 16:26:50 +00:00
|
|
|
|
registry.register(Box::new(entity_count_clone))?;
|
|
|
|
|
registry.register(Box::new(build_info_clone))?;
|
|
|
|
|
registry.register(Box::new(start_time_clone))?;
|
|
|
|
|
registry.register(Box::new(time_of_day_clone))?;
|
|
|
|
|
registry.register(Box::new(light_count_clone))?;
|
|
|
|
|
registry.register(Box::new(tick_time_clone))?;
|
|
|
|
|
Ok(())
|
|
|
|
|
};
|
2020-02-19 17:08:57 +00:00
|
|
|
|
|
2020-09-13 16:26:50 +00:00
|
|
|
|
Ok((
|
|
|
|
|
Self {
|
|
|
|
|
chonks_count,
|
|
|
|
|
chunks_count,
|
2020-09-28 11:35:49 +00:00
|
|
|
|
chunk_groups_count,
|
2020-09-13 16:26:50 +00:00
|
|
|
|
entity_count,
|
|
|
|
|
tick_time,
|
|
|
|
|
build_info,
|
|
|
|
|
start_time,
|
|
|
|
|
time_of_day,
|
|
|
|
|
light_count,
|
|
|
|
|
tick,
|
|
|
|
|
},
|
|
|
|
|
Box::new(f),
|
|
|
|
|
))
|
2020-08-18 17:03:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-19 17:08:57 +00:00
|
|
|
|
pub fn is_100th_tick(&self) -> bool { self.tick.load(Ordering::Relaxed).rem_euclid(100) == 0 }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ServerMetrics {
|
2020-06-10 19:47:36 +00:00
|
|
|
|
#[allow(clippy::new_without_default)] // TODO: Pending review in #587
|
2020-02-19 17:08:57 +00:00
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
let running = Arc::new(AtomicBool::new(false));
|
|
|
|
|
let tick = Arc::new(AtomicU64::new(0));
|
|
|
|
|
let registry = Some(Registry::new());
|
|
|
|
|
|
|
|
|
|
Self {
|
|
|
|
|
running,
|
|
|
|
|
handle: None,
|
|
|
|
|
registry,
|
|
|
|
|
tick,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
2020-09-27 16:20:40 +00:00
|
|
|
|
let running2 = Arc::clone(&self.running);
|
2020-02-19 17:08:57 +00:00
|
|
|
|
|
|
|
|
|
let registry = self
|
|
|
|
|
.registry
|
|
|
|
|
.take()
|
|
|
|
|
.expect("ServerMetrics must be already started");
|
2019-09-06 14:21:09 +00:00
|
|
|
|
|
2019-09-10 13:22:34 +00:00
|
|
|
|
//TODO: make this a job
|
2020-02-19 17:08:57 +00:00
|
|
|
|
self.handle = Some(thread::spawn(move || {
|
2020-06-01 00:13:35 +00:00
|
|
|
|
let server = tiny_http::Server::http(addr).unwrap();
|
|
|
|
|
const TIMEOUT: Duration = Duration::from_secs(1);
|
|
|
|
|
debug!("starting tiny_http server to serve metrics");
|
2019-09-20 04:41:44 +00:00
|
|
|
|
while running2.load(Ordering::Relaxed) {
|
2020-06-01 00:13:35 +00:00
|
|
|
|
let request = match server.recv_timeout(TIMEOUT) {
|
|
|
|
|
Ok(Some(rq)) => rq,
|
|
|
|
|
Ok(None) => continue,
|
|
|
|
|
Err(e) => {
|
2020-06-21 21:47:49 +00:00
|
|
|
|
error!(?e, "metrics http server error");
|
2020-06-01 00:13:35 +00:00
|
|
|
|
break;
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
let mf = registry.gather();
|
|
|
|
|
let encoder = TextEncoder::new();
|
|
|
|
|
let mut buffer = vec![];
|
|
|
|
|
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."),
|
|
|
|
|
);
|
|
|
|
|
if let Err(e) = request.respond(response) {
|
|
|
|
|
error!(
|
2020-06-21 21:47:49 +00:00
|
|
|
|
?e,
|
|
|
|
|
"The metrics HTTP server had encountered and error with answering",
|
2020-06-01 00:13:35 +00:00
|
|
|
|
);
|
|
|
|
|
}
|
2019-09-10 13:22:34 +00:00
|
|
|
|
}
|
2020-06-01 00:13:35 +00:00
|
|
|
|
debug!("stopping tiny_http server to serve metrics");
|
2019-09-10 13:22:34 +00:00
|
|
|
|
}));
|
2020-02-19 17:08:57 +00:00
|
|
|
|
Ok(())
|
2019-09-10 13:22:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-19 17:08:57 +00:00
|
|
|
|
pub fn tick(&self) -> u64 { self.tick.fetch_add(1, Ordering::Relaxed) + 1 }
|
|
|
|
|
|
2020-09-27 16:20:40 +00:00
|
|
|
|
pub fn tick_clone(&self) -> Arc<AtomicU64> { Arc::clone(&self.tick) }
|
2019-09-10 13:22:34 +00:00
|
|
|
|
}
|
2019-09-06 14:21:09 +00:00
|
|
|
|
|
2019-09-10 13:22:34 +00:00
|
|
|
|
impl Drop for ServerMetrics {
|
|
|
|
|
fn drop(&mut self) {
|
2019-09-20 04:41:44 +00:00
|
|
|
|
self.running.store(false, Ordering::Relaxed);
|
2019-09-10 13:22:34 +00:00
|
|
|
|
let handle = self.handle.take();
|
|
|
|
|
handle
|
2019-10-23 16:38:09 +00:00
|
|
|
|
.expect("ServerMetrics worker handle does not exist.")
|
2019-09-10 13:22:34 +00:00
|
|
|
|
.join()
|
|
|
|
|
.expect("Error shutting down prometheus metric exporter");
|
2019-09-06 14:21:09 +00:00
|
|
|
|
}
|
2019-09-07 13:10:57 +00:00
|
|
|
|
}
|