Skip to content

Commit

Permalink
Add more memory related data REST API (#20)
Browse files Browse the repository at this point in the history
* Added memory_usage and cpu loadavg in index_stats html page and v1 stats API
  • Loading branch information
ChellappanRajan authored Oct 15, 2022
1 parent 6e37bd8 commit 2f47e35
Show file tree
Hide file tree
Showing 9 changed files with 425 additions and 26 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,4 @@ systemstat = "0.2.0"

nats = "0.23.0" #https://github.com/nats-io/nats.rs
kafka = "0.9" #https://github.com/kafka-rust/kafka-rust

4 changes: 2 additions & 2 deletions Dockerfile.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ COPY . .

RUN cargo install --path .

FROM gcr.io/distroless/cc-debian10
FROM gcr.io/distroless/cc-debian11

COPY --from=build /usr/local/cargo/bin/x-server-stats /usr/local/bin/x-server-stats

Expand All @@ -24,4 +24,4 @@ ENV BASE_ADDR=http://0.0.0.0:8082

EXPOSE 8082

CMD ["./usr/local/bin/x-server-stats"]
CMD ["./usr/local/bin/x-server-stats"]
150 changes: 135 additions & 15 deletions src/handlers/handlers.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,36 @@
use crate::stats::{Loadavg, MemoryRef, PlatformMemoryDef, StatsResponse};
use crate::utils::{get_empty_memory_usage, get_load};

use crate::Stats;
use actix_web::body::BoxBody;
use actix_web::http::header::ContentType;
use actix_web::http::StatusCode;
use actix_web::{get, Error, HttpResponse, Responder};
use actix_web_lab::__reexports::serde_json;
use askama::Template;
use core::fmt;
use minify::html::minify;

use crate::stats::StatsResponse;
use crate::Stats;
use std::fmt::Display;

extern crate minify;

extern crate systemstat;
use std::thread;
use std::time::Duration;
use systemstat::platform::PlatformImpl;
use systemstat::{Platform, System};
use systemstat::{Memory, Platform, System};

impl Display for Loadavg {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Load avg: ")
}
}

impl Display for MemoryRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.platform_memory)
}
}

#[derive(Template)] // this will generate the code...
#[template(path = "index.html")] // using the template in this path, relative
Expand All @@ -42,6 +57,106 @@ pub async fn get_stats_from_linux(sys: PlatformImpl) -> Stats {
println!("\nMeasuring CPU load...");
thread::sleep(Duration::from_secs(1));
let cpu = cpu.done().unwrap();

let load_avg = match sys.load_average() {
Ok(load) => Loadavg {
one: load.one,
five: load.five,
fifteen: load.fifteen,
},
Err(_) => get_load(0.0, 0.0, 0.0),
};

#[cfg(target_os = "macos")]
let memory_details = match sys.memory() {
Ok(mem) => {
let platform_memory = PlatformMemoryDef {
total: mem.total.to_string(),
active: mem.platform_memory.active.to_string(),
inactive: mem.platform_memory.inactive.to_string(),
wired: mem.platform_memory.wired.to_string(),
free: mem.platform_memory.free.to_string(),
purgeable: mem.platform_memory.purgeable.to_string(),
speculative: mem.platform_memory.speculative.to_string(),
compressor: mem.platform_memory.compressor.to_string(),
throttled: mem.platform_memory.throttled.to_string(),
external: mem.platform_memory.external.to_string(),
internal: mem.platform_memory.internal.to_string(),
uncompressed_in_compressor: mem
.platform_memory
.uncompressed_in_compressor
.to_string(),
};
MemoryRef {
total: mem.total.to_string(),
free: mem.free.to_string(),
platform_memory,
}
}
Err(_) => get_empty_memory_usage(),
};

#[cfg(target_os = "linux")]
let memory_details = match sys.memory() {
Ok(mem) => {
let platform_memory = PlatformMemoryDef {
active: check_whether_key(&mem, "Active"),
active_anon: check_whether_key(&mem, "Active(anon)"),
active_file: check_whether_key(&mem, "Active(file)"),
anon_huge_pages: check_whether_key(&mem, "AnonHugePages"),
anon_pages: check_whether_key(&mem, "AnonPages"),
bounce: check_whether_key(&mem, "Bounce"),
buffers: check_whether_key(&mem, "Buffers"),
cached: check_whether_key(&mem, "Cached"),
commit_limit: check_whether_key(&mem, "CommitLimit"),
committed_as: check_whether_key(&mem, "Committed_AS"),
direct_map1g: check_whether_key(&mem, "DirectMap1G"),
direct_map2m: check_whether_key(&mem, "DirectMap2M"),
direct_map4k: check_whether_key(&mem, "DirectMap4k"),
dirty: check_whether_key(&mem, "Dirty"),
file_huge_pages: check_whether_key(&mem, "FileHugePages"),
file_pmd_mapped: check_whether_key(&mem, "FilePmdMapped"),
hardware_corrupted: check_whether_key(&mem, "HardwareCorrupted"),
hugepagesize: check_whether_key(&mem, "Hugepagesize"),
hugetlb: check_whether_key(&mem, "Hugetlb"),
inactive: check_whether_key(&mem, "Inactive"),
inactive_anon: check_whether_key(&mem, "Inactive(anon)"),
inactive_file: check_whether_key(&mem, "Inactive(file)"),
kreclaimable: check_whether_key(&mem, "KReclaimable"),
kernel_stack: check_whether_key(&mem, "KernelStack"),
mapped: check_whether_key(&mem, "Mapped"),
mem_available: check_whether_key(&mem, "MemAvailable"),
mem_free: check_whether_key(&mem, "MemFree"),
mem_total: check_whether_key(&mem, "MemTotal"),
mlocked: check_whether_key(&mem, "Mlocked"),
nfs_unstable: check_whether_key(&mem, "NFS_Unstable"),
page_tables: check_whether_key(&mem, "PageTables"),
percpu: check_whether_key(&mem, "Percpu"),
sreclaimable: check_whether_key(&mem, "SReclaimable"),
sunreclaim: check_whether_key(&mem, "SUnreclaim"),
shmem: check_whether_key(&mem, "Shmem"),
shmem_huge_pages: check_whether_key(&mem, "ShmemHugePages"),
shmem_pmd_mapped: check_whether_key(&mem, "ShmemPmdMapped"),
slab: check_whether_key(&mem, "Slab"),
swap_cached: check_whether_key(&mem, "SwapCached"),
swap_free: check_whether_key(&mem, "SwapFree"),
swap_total: check_whether_key(&mem, "SwapTotal"),
unevictable: check_whether_key(&mem, "Unevictable"),
vmalloc_chunk: check_whether_key(&mem, "VmallocChunk"),
vmalloc_total: check_whether_key(&mem, "VmallocTotal"),
vmalloc_used: check_whether_key(&mem, "VmallocUsed"),
writeback: check_whether_key(&mem, "Writeback"),
writeback_tmp: check_whether_key(&mem, "WritebackTmp"),
};
MemoryRef {
total: mem.total.to_string(),
free: mem.free.to_string(),
platform_memory,
}
}
Err(_) => get_empty_memory_usage(),
};

println!(
"CPU load: {}% user, {}% nice, {}% system, {}% intr, {}% idle ",
cpu.user * 100.0,
Expand All @@ -60,29 +175,23 @@ pub async fn get_stats_from_linux(sys: PlatformImpl) -> Stats {
cpu.idle * 100.0
);

let stats = Stats {
loadavg: "1.0".to_string(),
return Stats {
loadavg: load_avg,
cpu_usage,
memory_usage: "3.0".to_string(),
memory_usage: memory_details,
};

return stats;
}
Err(x) => println!("\nCPU load: error: {}", x),
}

Stats {
loadavg: "Error".to_string(),
loadavg: get_load(0.0, 0.0, 0.0),
cpu_usage: "Error".to_string(),
memory_usage: "Error".to_string(),
memory_usage: get_empty_memory_usage(),
}
}

#[get("")]
pub async fn index_page() -> Result<HttpResponse, Error> {
// parameter for this method - req: &HttpRequest
// println!("{:?}", req);

let sys = System::new();

match sys.cpu_temp() {
Expand Down Expand Up @@ -121,3 +230,14 @@ async fn status_get_api() -> impl Responder {
.content_type(ContentType::json())
.body(response)
}

//https://www.anycodings.com/1questions/2410879/using-serdejson-to-serialise-maps-with-non-string-keys

#[cfg(target_os = "linux")]
pub fn check_whether_key(mem: &Memory, key: &str) -> String {
let d = match mem.platform_memory.meminfo.get(key) {
Some(active) => active.to_string(),
_ => "".to_string(),
};
return d;
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
mod config;
mod handlers;
mod stats;
mod utils;

use std::env;

Expand Down
2 changes: 1 addition & 1 deletion src/stats/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ mod model;
mod routes;

pub use model::*;
pub use routes::*;
pub use routes::*;
148 changes: 141 additions & 7 deletions src/stats/model.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,152 @@
use serde::Serializer;
use std::fmt;
use std::marker::PhantomData;
use std::str;

use serde::{Deserialize, Serialize};
use tokio_pg_mapper_derive::PostgresMapper;
// use serde_with::{serde_as, DeserializeAs, SerializeAs};

use serde::de::{Deserializer, MapAccess, Visitor};
use serde::ser::SerializeMap;
use systemstat::{ByteSize, Memory, PlatformMemory};

extern crate chrono;

#[derive(Deserialize, PostgresMapper, Serialize, Clone, Debug)]
#[pg_mapper(table = "stats")]
// #[cfg(target_os = "linux")]
pub use std::collections::BTreeMap;
// pub use std::collections::BTreeMap as MyMap;

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct Stats {
pub loadavg: String,
pub loadavg: Loadavg,
pub cpu_usage: String,
pub memory_usage: String,
// pub current_system_time: NaiveDateTime,
pub memory_usage: MemoryRef,
}

#[derive(Serialize, Deserialize)]
#[derive(Serialize, Clone, Deserialize)]
pub struct StatsResponse {
pub result: bool,
pub data: Stats,
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct Loadavg {
pub one: f32,
pub five: f32,
pub fifteen: f32,
}

#[derive(Deserialize, Serialize, Clone, Debug)]
#[cfg(target_os = "macos")]
pub struct PlatformMemoryDef {
pub total: String,
pub active: String,
pub inactive: String,
pub wired: String,
pub free: String,
pub purgeable: String,
pub speculative: String,
pub compressor: String,
pub throttled: String,
pub external: String,
pub internal: String,
pub uncompressed_in_compressor: String,
}

#[derive(Deserialize, Serialize, Clone, Debug)]
#[cfg(target_os = "linux")]
pub struct PlatformMemoryDef {
pub active: String,

pub active_anon: String,

pub active_file: String,

pub anon_huge_pages: String,

pub anon_pages: String,

pub bounce: String,

pub buffers: String,
pub cached: String,

pub commit_limit: String,

pub committed_as: String,

pub direct_map1g: String,

pub direct_map2m: String,

pub direct_map4k: String,

pub dirty: String,

pub file_huge_pages: String,

pub file_pmd_mapped: String,

pub hardware_corrupted: String,

pub hugepagesize: String,

pub hugetlb: String,

pub inactive: String,

pub inactive_anon: String,

pub inactive_file: String,

pub kreclaimable: String,

pub kernel_stack: String,

pub mapped: String,

pub mem_available: String,

pub mem_free: String,

pub mem_total: String,

pub mlocked: String,

pub nfs_unstable: String,

pub page_tables: String,

pub percpu: String,

pub sreclaimable: String,

pub sunreclaim: String,

pub shmem: String,

pub shmem_huge_pages: String,

pub shmem_pmd_mapped: String,

pub slab: String,

pub swap_cached: String,

pub swap_free: String,
pub swap_total: String,

pub unevictable: String,
pub vmalloc_chunk: String,
pub vmalloc_total: String,
pub vmalloc_used: String,
pub writeback: String,
pub writeback_tmp: String,
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct MemoryRef {
pub total: String,
pub free: String,
pub platform_memory: PlatformMemoryDef,
}
3 changes: 3 additions & 0 deletions src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod utils;

pub use utils::*;
Loading

0 comments on commit 2f47e35

Please sign in to comment.