Fix panic if starting singleplayer twice without closing the game

reduce costs for metrics by checking chunks only every 100th tick
add metrics for "server start time" and ingame "time of day"
This commit is contained in:
Marcel Märtens 2019-09-10 15:22:34 +02:00
parent bb93585499
commit 02fe9adfb7
2 changed files with 94 additions and 43 deletions

View File

@ -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::<TimeOfDay>().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

View File

@ -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<JoinHandle<()>>,
pub thread_running: Arc<AtomicBool>,
pub handle: Option<thread::JoinHandle<()>>,
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");
}
}