diff --git a/server/src/lib.rs b/server/src/lib.rs index 2a9e67c85f..e8886ba002 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -664,13 +664,18 @@ impl Server { .with_label_values(&["sync"]) .set((before_tick_7 - before_tick_6).as_nanos() as i64); self.metrics.player_online.set(self.clients.len() as i64); - let mut chonk_cnt = 0; - let chunk_cnt = self.state.terrain().iter().fold(0, |a, (_, c)| { - chonk_cnt += 1; - a + c.sub_chunks_len() - }); - self.metrics.chonks_count.set(chonk_cnt as i64); - self.metrics.chunks_count.set(chunk_cnt as i64); + self.metrics + .time_of_day + .set(self.state.ecs().read_resource::().0); + if self.metrics.is_100th_tick() { + let mut chonk_cnt = 0; + let chunk_cnt = self.state.terrain().iter().fold(0, |a, (_, c)| { + chonk_cnt += 1; + a + c.sub_chunks_len() + }); + self.metrics.chonks_count.set(chonk_cnt as i64); + self.metrics.chunks_count.set(chunk_cnt as i64); + } //self.metrics.entity_count.set(self.state.); self.metrics .tick_time diff --git a/server/src/metrics.rs b/server/src/metrics.rs index 07f4d3a83d..8abbee9194 100644 --- a/server/src/metrics.rs +++ b/server/src/metrics.rs @@ -1,11 +1,18 @@ extern crate prometheus; extern crate prometheus_static_metric; extern crate rouille; -use prometheus::{Encoder, IntGauge, IntGaugeVec, Opts, Registry, TextEncoder}; -use rouille::router; -use std::net::{IpAddr, Ipv4Addr, SocketAddr}; -use std::thread; -use std::thread::JoinHandle; +use prometheus::{Encoder, Gauge, IntGauge, IntGaugeVec, Opts, Registry, TextEncoder}; +use rouille::{router, Server}; +use std::{ + convert::TryInto, + net::{IpAddr, Ipv4Addr, SocketAddr}, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, + thread, + time::{SystemTime, UNIX_EPOCH}, +}; pub struct ServerMetrics { pub chonks_count: IntGauge, @@ -14,9 +21,12 @@ pub struct ServerMetrics { pub entity_count: IntGauge, pub tick_time: IntGaugeVec, pub build_info: IntGauge, + pub start_time: IntGauge, + pub time_of_day: Gauge, pub light_count: IntGauge, - pub registry: Registry, - pub handle: Option>, + pub thread_running: Arc, + pub handle: Option>, + pub every_100th: i8, } impl ServerMetrics { @@ -35,6 +45,13 @@ impl ServerMetrics { .const_label("hash", common::util::GIT_HASH) .const_label("version", ""); let build_info = IntGauge::with_opts(opts).unwrap(); + let opts = Opts::new( + "veloren_start_time", + "start time of the server in seconds since EPOCH", + ); + let start_time = IntGauge::with_opts(opts).unwrap(); + let opts = Opts::new("time_of_day", "ingame time in ingame-seconds"); + let time_of_day = Gauge::with_opts(opts).unwrap(); let opts = Opts::new( "light_count", "number of all lights currently active on the server", @@ -57,52 +74,81 @@ impl ServerMetrics { .unwrap(); let tick_time = IntGaugeVec::from(vec); + let since_the_epoch = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Time went backwards"); + start_time.set(since_the_epoch.as_secs().try_into().unwrap()); + let registry = Registry::new(); //registry.register(Box::new(chonks_count.clone())).unwrap(); registry.register(Box::new(player_online.clone())).unwrap(); registry.register(Box::new(entity_count.clone())).unwrap(); registry.register(Box::new(build_info.clone())).unwrap(); + registry.register(Box::new(start_time.clone())).unwrap(); + registry.register(Box::new(time_of_day.clone())).unwrap(); //registry.register(Box::new(light_count.clone())).unwrap(); registry.register(Box::new(chonks_count.clone())).unwrap(); registry.register(Box::new(chunks_count.clone())).unwrap(); registry.register(Box::new(tick_time.clone())).unwrap(); - prometheus::register(Box::new(player_online.clone())).unwrap(); - prometheus::register(Box::new(entity_count.clone())).unwrap(); - prometheus::register(Box::new(build_info.clone())).unwrap(); - //prometheus::register(Box::new(light_count.clone())).unwrap(); - prometheus::register(Box::new(chonks_count.clone())).unwrap(); - prometheus::register(Box::new(chunks_count.clone())).unwrap(); - prometheus::register(Box::new(tick_time.clone())).unwrap(); - let mut metrics = Self { + let thread_running = Arc::new(AtomicBool::new(true)); + let thread_running2 = thread_running.clone(); + + //TODO: make this a job + let handle = Some(thread::spawn(move || { + let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 14005); + let server = Server::new(addr, move |request| { + router!(request, + (GET) (/metrics) => { + let encoder = TextEncoder::new(); + let mut buffer = vec![]; + let mf = registry.gather(); + encoder.encode(&mf, &mut buffer).unwrap(); + rouille::Response::text(String::from_utf8(buffer).unwrap()) + }, + _ => rouille::Response::empty_404() + ) + }) + .expect("Failed to start server"); + while thread_running2.load(Ordering::Relaxed) { + server.poll(); + } + })); + + Self { chonks_count, chunks_count, player_online, entity_count, tick_time, build_info, + start_time, + time_of_day, light_count, - registry, - handle: None, - }; + thread_running, + handle, + every_100th: 0, + } + } - let handle = thread::spawn(|| { - let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 14005); - rouille::start_server(addr, move |request| { - router!(request, - (GET) (/metrics) => { - let encoder = TextEncoder::new(); - let mut buffer = vec![]; - let mf = prometheus::gather(); - encoder.encode(&mf, &mut buffer).unwrap(); - rouille::Response::text(String::from_utf8(buffer).unwrap()) - }, - _ => rouille::Response::empty_404() - ) - }); - }); - metrics.handle = Some(handle); - - metrics + pub fn is_100th_tick(&mut self) -> bool { + self.every_100th += 1; + if self.every_100th == 100 { + self.every_100th = 0; + true + } else { + false + } + } +} + +impl Drop for ServerMetrics { + fn drop(&mut self) { + self.thread_running.store(false, Ordering::Relaxed); + let handle = self.handle.take(); + handle + .unwrap() + .join() + .expect("Error shutting down prometheus metric exporter"); } }