Implement net stats

This commit is contained in:
Sofia 2026-07-16 05:50:20 +03:00
parent a849904535
commit 82d3a22193
9 changed files with 131 additions and 6 deletions

View File

@ -12,3 +12,13 @@ mesh = SubResource("BoxMesh_m77kh")
[node name="directional_light_3d" type="DirectionalLight3D" parent="." unique_id=75522463]
transform = Transform3D(0.61237246, -0.5, 0.61237246, 0.3535534, 0.8660254, 0.3535534, -0.7071068, 0, 0.7071068, 0, 1, 2)
[node name="netstats" type="NetStatsLabel" parent="." unique_id=1366169487]
anchors_preset = 12
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_top = -144.0
grow_horizontal = 2
grow_vertical = 0
vertical_alignment = 2

View File

@ -2,7 +2,7 @@ use std::net::SocketAddr;
use godot::prelude::*;
pub mod network_manager;
pub mod net;
pub mod ui;
struct MyExtension;

2
rust/src/net/mod.rs Normal file
View File

@ -0,0 +1,2 @@
pub mod net_stats;
pub mod network_manager;

57
rust/src/net/net_stats.rs Normal file
View File

@ -0,0 +1,57 @@
use std::time::Instant;
use godot::prelude::*;
use teanet::stats::NetStats;
#[derive(GodotClass)]
#[class(base=Object, singleton)]
pub struct Stats {
pub statistics: Statistics,
last_update: Instant,
base: Base<Object>,
}
#[godot_api]
impl IObject for Stats {
fn init(base: Base<Object>) -> Self {
Stats {
statistics: Default::default(),
last_update: Instant::now(),
base,
}
}
}
impl Stats {
pub fn update_stats(&mut self, stats: NetStats) {
let now = Instant::now();
let tx_diff =
stats.bytes_tx.max(self.statistics.total_bytes_tx) - self.statistics.total_bytes_tx;
let rx_diff =
stats.bytes_rx.max(self.statistics.total_bytes_rx) - self.statistics.total_bytes_rx;
self.statistics.total_bytes_rx = stats.bytes_rx;
self.statistics.total_bytes_tx = stats.bytes_tx;
self.statistics.packet_loss =
1. - ((stats.messages_received as f64) / (stats.messages_expected as f64));
let duration = now - self.last_update;
let tx_bps = tx_diff as f64 / duration.as_secs_f64();
let rx_bps = rx_diff as f64 / duration.as_secs_f64();
self.statistics.tx_bps = tx_bps as usize;
self.statistics.rx_bps = rx_bps as usize;
self.last_update = now;
}
}
#[derive(Default)]
pub struct Statistics {
pub total_bytes_tx: usize,
pub total_bytes_rx: usize,
pub tx_bps: usize,
pub rx_bps: usize,
pub packet_loss: f64,
}

View File

@ -7,7 +7,10 @@ use godot::{prelude::*, tools::get_autoload_by_name};
use serde::{Deserialize, Serialize};
use teanet::{Peer, PeerConfig};
use crate::ui::cli::{CLI_GLOBAL_NAME, CliColor, CommandLinePanel};
use crate::{
net::net_stats::Stats,
ui::cli::{CLI_GLOBAL_NAME, CliColor, CommandLinePanel},
};
#[derive(GodotClass)]
#[class(base=Node)]
@ -15,6 +18,7 @@ pub struct NetworkManager {
peer: Option<PeerKind>,
last_hello: Instant,
last_netstat_update: Instant,
base: Base<Node>,
}
@ -25,8 +29,11 @@ pub const NETWORK_SINGLETON_NAME: &str = "NetworkManagerGlob";
impl INode for NetworkManager {
fn init(base: Base<Node>) -> Self {
NetworkManager {
last_hello: Instant::now(),
peer: None,
last_hello: Instant::now(),
last_netstat_update: Instant::now(),
base,
}
}
@ -52,10 +59,18 @@ impl INode for NetworkManager {
if let Some(peer) = &mut self.peer {
let mut cli = get_autoload_by_name::<CommandLinePanel>(CLI_GLOBAL_NAME);
let now = Instant::now();
if now - self.last_netstat_update > Duration::from_millis(1000) {
Stats::singleton().bind_mut().update_stats(match peer {
PeerKind::Client(peer, _) => peer.statistics(),
PeerKind::Server(peer, _) => peer.statistics(),
});
self.last_netstat_update = now;
}
match peer {
PeerKind::Client(..) => {}
PeerKind::Server(peer, _) => {
let now = Instant::now();
if now - self.last_hello > Duration::from_millis(2000) {
self.last_hello = now;
peer.broadcast_reliable(Package::Hello);

View File

@ -7,7 +7,7 @@ use godot::classes::{Engine, IPanel, Panel, RichTextLabel, ScrollContainer, Text
use godot::prelude::*;
use godot::tools::get_autoload_by_name;
use crate::network_manager::{NETWORK_SINGLETON_NAME, NetworkManager};
use crate::net::network_manager::{NETWORK_SINGLETON_NAME, NetworkManager};
pub enum CliColor {
Command,

View File

@ -1 +1,2 @@
pub mod cli;
pub mod net_stats;

40
rust/src/ui/net_stats.rs Normal file
View File

@ -0,0 +1,40 @@
use godot::{
classes::{ILabel, Label},
prelude::*,
};
use crate::net::net_stats::Stats;
#[derive(GodotClass)]
#[class(base=Label)]
pub struct NetStatsLabel {
since_update: f64,
base: Base<Label>,
}
#[godot_api]
impl ILabel for NetStatsLabel {
fn init(base: Base<Self::Base>) -> Self {
NetStatsLabel {
since_update: 0.,
base,
}
}
fn process(&mut self, delta: f64) {
self.since_update += delta;
if self.since_update > 0.1 {
self.since_update = 0.;
let stats = Stats::singleton();
let statistics = &stats.bind().statistics;
self.base_mut().set_text(&format!(
"TX: {} ({} bps)\nRX: {} ({} bps)\nPacket Loss: {:.2}%",
statistics.total_bytes_tx,
statistics.tx_bps,
statistics.total_bytes_rx,
statistics.rx_bps,
statistics.packet_loss * 100.
));
}
}
}

@ -1 +1 @@
Subproject commit 44122d77d6382043be85ff0a72398748b9ab3493
Subproject commit 3551d0e50b598e96fb3ffbb5cce5ad5792f891ae