~starkingdoms/starkingdoms

a032d20ee4fdccaa715bbde2cb73b318222ad6e1 — c0repwn3r 2 years ago ca28644
metrics
M Cargo.lock => Cargo.lock +81 -6
@@ 428,7 428,7 @@ dependencies = [
 "log",
 "parking",
 "polling",
 "rustix",
 "rustix 0.37.20",
 "slab",
 "socket2",
 "waker-fn",


@@ 1774,6 1774,12 @@ checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"

[[package]]
name = "linux-raw-sys"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"

[[package]]
name = "linux-raw-sys"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"


@@ 2194,7 2200,7 @@ dependencies = [
 "redox_syscall 0.3.5",
 "smallvec",
 "thread-id",
 "windows-targets",
 "windows-targets 0.48.0",
]

[[package]]


@@ 2415,6 2421,36 @@ dependencies = [
]

[[package]]
name = "procfs"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1de8dacb0873f77e6aefc6d71e044761fcc68060290f5b1089fcdf84626bb69"
dependencies = [
 "bitflags",
 "byteorder",
 "hex",
 "lazy_static",
 "rustix 0.36.15",
]

[[package]]
name = "prometheus"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c"
dependencies = [
 "cfg-if",
 "fnv",
 "lazy_static",
 "libc",
 "memchr",
 "parking_lot 0.12.1",
 "procfs",
 "protobuf 2.28.0",
 "thiserror",
]

[[package]]
name = "protobuf"
version = "2.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 2791,6 2827,20 @@ dependencies = [

[[package]]
name = "rustix"
version = "0.36.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c37f1bd5ef1b5422177b7646cba67430579cfe2ace80f284fee876bca52ad941"
dependencies = [
 "bitflags",
 "errno",
 "io-lifetimes",
 "libc",
 "linux-raw-sys 0.1.4",
 "windows-sys 0.45.0",
]

[[package]]
name = "rustix"
version = "0.37.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0"


@@ 2799,7 2849,7 @@ dependencies = [
 "errno",
 "io-lifetimes",
 "libc",
 "linux-raw-sys",
 "linux-raw-sys 0.3.8",
 "windows-sys 0.48.0",
]



@@ 3436,6 3486,7 @@ dependencies = [
 "log",
 "nalgebra",
 "parking_lot 0.12.1",
 "prometheus",
 "protobuf 3.2.0",
 "rand",
 "rapier2d-f64",


@@ 3525,7 3576,7 @@ dependencies = [
 "cfg-if",
 "fastrand",
 "redox_syscall 0.3.5",
 "rustix",
 "rustix 0.37.20",
 "windows-sys 0.48.0",
]



@@ 4207,7 4258,7 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
dependencies = [
 "windows-targets",
 "windows-targets 0.48.0",
]

[[package]]


@@ 4227,11 4278,35 @@ dependencies = [

[[package]]
name = "windows-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
 "windows-targets 0.42.2",
]

[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
 "windows-targets",
 "windows-targets 0.48.0",
]

[[package]]
name = "windows-targets"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
dependencies = [
 "windows_aarch64_gnullvm 0.42.2",
 "windows_aarch64_msvc 0.42.2",
 "windows_i686_gnu 0.42.2",
 "windows_i686_msvc 0.42.2",
 "windows_x86_64_gnu 0.42.2",
 "windows_x86_64_gnullvm 0.42.2",
 "windows_x86_64_msvc 0.42.2",
]

[[package]]

M assets/dist/spritesheet-125.json => assets/dist/spritesheet-125.json +4 -4
@@ 63,7 63,7 @@
      "pivot": { "x": 32, "y": 32 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 64, "h": 64 }
    },
    "autoplr_error.png": {
    "hearty.png": {
      "frame": { "x": 0, "y": 1216, "w": 64, "h": 64 },
      "rotated": false,
      "trimmed": false,


@@ 81,7 81,7 @@
      "pivot": { "x": 32, "y": 32 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 64, "h": 64 }
    },
    "hearty.png": {
    "autoplr_error.png": {
      "frame": { "x": 0, "y": 1344, "w": 64, "h": 64 },
      "rotated": false,
      "trimmed": false,


@@ 144,7 144,7 @@
      "pivot": { "x": 32, "y": 32 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 64, "h": 64 }
    },
    "autoplr_on.png": {
    "powerhub_on.png": {
      "frame": { "x": 0, "y": 1792, "w": 64, "h": 64 },
      "rotated": false,
      "trimmed": false,


@@ 153,7 153,7 @@
      "pivot": { "x": 32, "y": 32 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 64, "h": 64 }
    },
    "powerhub_on.png": {
    "autoplr_on.png": {
      "frame": { "x": 0, "y": 1856, "w": 64, "h": 64 },
      "rotated": false,
      "trimmed": false,

M assets/dist/spritesheet-125.png => assets/dist/spritesheet-125.png +0 -0
M assets/dist/spritesheet-375.json => assets/dist/spritesheet-375.json +5 -5
@@ 63,7 63,7 @@
      "pivot": { "x": 96, "y": 96 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 192, "h": 192 }
    },
    "autoplr_cfg.png": {
    "hearty.png": {
      "frame": { "x": 0, "y": 3648, "w": 192, "h": 192 },
      "rotated": false,
      "trimmed": false,


@@ 72,7 72,7 @@
      "pivot": { "x": 96, "y": 96 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 192, "h": 192 }
    },
    "autoplr_error.png": {
    "autoplr_cfg.png": {
      "frame": { "x": 0, "y": 3840, "w": 192, "h": 192 },
      "rotated": false,
      "trimmed": false,


@@ 81,7 81,7 @@
      "pivot": { "x": 96, "y": 96 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 192, "h": 192 }
    },
    "hearty.png": {
    "autoplr_error.png": {
      "frame": { "x": 0, "y": 4032, "w": 192, "h": 192 },
      "rotated": false,
      "trimmed": false,


@@ 135,7 135,7 @@
      "pivot": { "x": 96, "y": 96 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 192, "h": 192 }
    },
    "powerhub_on.png": {
    "hub_on.png": {
      "frame": { "x": 0, "y": 5184, "w": 192, "h": 192 },
      "rotated": false,
      "trimmed": false,


@@ 144,7 144,7 @@
      "pivot": { "x": 96, "y": 96 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 192, "h": 192 }
    },
    "hub_on.png": {
    "powerhub_on.png": {
      "frame": { "x": 0, "y": 5376, "w": 192, "h": 192 },
      "rotated": false,
      "trimmed": false,

M assets/dist/spritesheet-375.png => assets/dist/spritesheet-375.png +0 -0
M assets/dist/spritesheet-full.json => assets/dist/spritesheet-full.json +3 -3
@@ 63,7 63,7 @@
      "pivot": { "x": 256, "y": 256 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 512, "h": 512 }
    },
    "autoplr_error.png": {
    "hearty.png": {
      "frame": { "x": 512, "y": 6144, "w": 512, "h": 512 },
      "rotated": false,
      "trimmed": false,


@@ 72,7 72,7 @@
      "pivot": { "x": 256, "y": 256 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 512, "h": 512 }
    },
    "hearty.png": {
    "autoplr_cfg.png": {
      "frame": { "x": 512, "y": 6656, "w": 512, "h": 512 },
      "rotated": false,
      "trimmed": false,


@@ 81,7 81,7 @@
      "pivot": { "x": 256, "y": 256 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 512, "h": 512 }
    },
    "autoplr_cfg.png": {
    "autoplr_error.png": {
      "frame": { "x": 512, "y": 7168, "w": 512, "h": 512 },
      "rotated": false,
      "trimmed": false,

M assets/dist/spritesheet-full.png => assets/dist/spritesheet-full.png +0 -0
M server/Cargo.toml => server/Cargo.toml +2 -0
@@ 32,5 32,7 @@ protobuf = "3.2.0"

parking_lot = { version = "0.12.1", features = ["deadlock_detection"] }

prometheus = { version = "0.13", features = ["process"] }

[build-dependencies]
cargo_metadata = "0.15"

M server/src/entity.rs => server/src/entity.rs +9 -1
@@ 13,7 13,8 @@ use crate::{

pub type EntityId = u32;
pub type Entities = HashMap<EntityId, Entity>;
static mut ENTITY_ID_COUNT: AtomicU32 = AtomicU32::new(0);
pub static mut ENTITY_ID_COUNT: AtomicU32 = AtomicU32::new(0);

pub fn get_entity_id() -> EntityId {
    let last_entity_id = unsafe { &ENTITY_ID_COUNT };
    let id = last_entity_id.fetch_add(1, std::sync::atomic::Ordering::AcqRel);


@@ 21,6 22,13 @@ pub fn get_entity_id() -> EntityId {
    id
}

pub fn get_last_entity_id() -> EntityId {
    let last_entity_id = unsafe { &ENTITY_ID_COUNT };
    let id = last_entity_id.fetch_add(0, std::sync::atomic::Ordering::AcqRel);
    assert!(id <= 4_294_967_290, "No remaining entity ids");
    id
}

#[derive(Default)]
pub struct EntityHandler {
    pub entities: Entities,

M server/src/main.rs => server/src/main.rs +59 -1
@@ 35,6 35,7 @@ use std::collections::HashMap;
use std::net::SocketAddr;
use std::thread;
use std::time::Duration;
use prometheus::{Gauge, register_gauge, opts, labels, TextEncoder, Counter, register_counter};
use crate::tcp_handler::handle_request;

pub mod handler;


@@ 75,6 76,59 @@ lazy_static! {
        ccd_solver: CCDSolver::new(),
    }));
    static ref ENTITIES: Arc<RwLock<EntityHandler>> = Arc::new(RwLock::new(EntityHandler::new()));

    // Prometheus stuff //

    static ref ENCODER: TextEncoder = TextEncoder::new();

    static ref BUILD_INFO_GAGUE: Gauge = register_gauge!(
        opts!("starkingdoms_build_info",
            "A constant gague with value 1 containing build information in the labels.",
            labels! {
                "version_name" => env!("STK_VERSION_NAME"),
                "version" => env!("STK_VERSION"),
                "protocol" => stringify!(PROTOCOL_VERSION),
                "channel" => env!("STK_CHANNEL"),
                "build" => env!("STK_BUILD"),
                "server_description" => env!("STK_SLP_DESCRIPTION")
            }
        )
    ).unwrap();

    static ref ONLINE_PLAYERS_GAGUE: Gauge = register_gauge!(
        opts!(
            "starkingdoms_online_players",
            "Number of players currently online"
        )
    ).unwrap();

    static ref CMGR_HANDLERS_GAUGE: Gauge = register_gauge!(
        opts!(
            "starkingdoms_cmgr_handlers",
            "Number of active handlers in the client manager"
        )
    ).unwrap();

    static ref CMGR_USERNAMES_GAUGE: Gauge = register_gauge!(
        opts!(
            "starkingdoms_cmgr_usernames",
            "Number of active usernames in the client manager"
        )
    ).unwrap();

    static ref ENTITIES_GAUGE: Gauge = register_gauge!(
        opts!(
            "starkingdoms_entities",
            "Number of entities in the entity manager"
        )
    ).unwrap();

    static ref ENTITY_ID_COUNTER: Counter = register_counter!(
        opts!(
            "starkingdoms_entity_id",
            "Number of entities ever created in the entity manager"
        )
    ).unwrap();
}

pub const PANIC_ON_DEADLOCK: bool = true;


@@ 93,7 147,11 @@ async fn main() {
        env!("STK_BUILD")
    );

    info!("{}", std::mem::size_of::<Entity>());
    // Initialize metrics //

    BUILD_INFO_GAGUE.inc(); // Create the build info metric

    // All done with metrics //

    if std::env::var("STK_API_KEY").is_err() {
        error!(

M server/src/tcp_handler.rs => server/src/tcp_handler.rs +43 -3
@@ 6,11 6,11 @@ use async_std::net::TcpStream;
use async_std::sync::RwLock;
use log::{error, info, warn};
use starkingdoms_protocol::PROTOCOL_VERSION;
use crate::entity::{Entity, EntityHandler};
use crate::entity::{Entity, ENTITY_ID_COUNT, EntityHandler, get_last_entity_id};
use crate::manager::{ClientHandler, ClientManager, PhysicsData};
use crate::{CMGR, ServerPingResponse, ServerPingResponseVersion};
use crate::{CMGR, CMGR_HANDLERS_GAUGE, CMGR_USERNAMES_GAUGE, ENCODER, ENTITIES, ENTITIES_GAUGE, ENTITY_ID_COUNTER, ONLINE_PLAYERS_GAGUE, ServerPingResponse, ServerPingResponseVersion};
use crate::handler::handle_client;
use futures::StreamExt;
use futures::{StreamExt};

pub async fn handle_request(
    conn: TcpStream,


@@ 71,6 71,46 @@ async fn _handle_request(
            ping_resp.len()
        );
        return Ok(());
    } else if peek_buf == *b"GET /stat" {
        info!("[{}] incoming metrics request", remote_addr);

        // These blocks are separated on purpose to prevent deadlocks.
        // DO NOT COMBINE THEM.

        #[allow(clippy::cast_precision_loss)] {
            ONLINE_PLAYERS_GAGUE.set(CMGR.usernames.read().await.len() as f64);
        }
        #[allow(clippy::cast_precision_loss)] {
            CMGR_USERNAMES_GAUGE.set(CMGR.usernames.read().await.len() as f64);
            CMGR_HANDLERS_GAUGE.set(CMGR.handlers.read().await.len() as f64);
            ENTITIES_GAUGE.set(ENTITIES.read().await.entities.len() as f64);
        }
        #[allow(clippy::cast_precision_loss)] {
            let current = ENTITY_ID_COUNTER.get();
            let target = f64::from(get_last_entity_id());
            let diff = target - current;
            ENTITY_ID_COUNTER.inc_by(diff);
        }

        let stats = prometheus::gather();

        let text = ENCODER.encode_to_string(&stats)?;

        let resp_str = format!(
            "HTTP/1.0 200 OK\nAccess-Control-Allow-Origin: *\nContent-Length: {}\n\n{}",
            text.len(),
            text
        );

        conn.write_all(resp_str.as_bytes()).await?;

        info!(
            "[{}] sent stats response (200 OK {} bytes)",
            remote_addr,
            text.len()
        );

        return Ok(());
    }
    info!("[{}] incoming websocket connection", remote_addr);