mirror of
https://github.com/sched-ext/scx.git
synced 2024-11-28 21:50:23 +00:00
scx_stats: s/scx_stat/scx_stats/
Use plural form which is more widespread and also used in scheduler implementations. No functional changes.
This commit is contained in:
parent
6e466d18df
commit
8aae9a5de2
@ -1,3 +1,3 @@
|
||||
subdir('scx_utils')
|
||||
subdir('scx_stat')
|
||||
subdir('scx_stats')
|
||||
subdir('scx_rustland_core')
|
||||
|
@ -1,13 +0,0 @@
|
||||
pub use serde_json;
|
||||
|
||||
mod stat;
|
||||
pub use stat::{
|
||||
ScxStatAttr, ScxStatAttrs, ScxStatData, ScxStatField, ScxStatKind, ScxStatMeta, ScxStatMetaAux,
|
||||
StatMeta,
|
||||
};
|
||||
|
||||
mod server;
|
||||
pub use server::{ScxStatErrno, ScxStatOutput, ScxStatRequest, ScxStatResponse, ScxStatServer};
|
||||
|
||||
mod client;
|
||||
pub use client::ScxStatClient;
|
@ -1,6 +1,6 @@
|
||||
workspace = { members = ["scx_stat_derive"] }
|
||||
workspace = { members = ["scx_stats_derive"] }
|
||||
[package]
|
||||
name = "scx_stat"
|
||||
name = "scx_stats"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
@ -14,4 +14,4 @@ serde_json = "1.0"
|
||||
syn = { version = "2.0", features = ["extra-traits", "full"] }
|
||||
|
||||
[dev-dependencies]
|
||||
scx_stat_derive = { path = "scx_stat_derive", version = "0.1.0" }
|
||||
scx_stats_derive = { path = "scx_stats_derive", version = "0.1.0" }
|
@ -1,14 +1,14 @@
|
||||
use scx_stat::{ScxStatClient, ScxStatMeta};
|
||||
use scx_stat_derive::Stat;
|
||||
use scx_stats::{ScxStatsClient, ScxStatsMeta};
|
||||
use scx_stats_derive::Stats;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::BTreeMap;
|
||||
use std::env::args;
|
||||
|
||||
// DomainStat and ClusterStat definitions must match the ones in server.rs.
|
||||
//
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Stat)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Stats)]
|
||||
#[stat(desc = "domain statistics")]
|
||||
struct DomainStat {
|
||||
struct DomainStats {
|
||||
dom_name: String,
|
||||
#[stat(desc = "domain last updated at")]
|
||||
pub dom_at: u64,
|
||||
@ -18,38 +18,38 @@ struct DomainStat {
|
||||
dom_f_cnt: f64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Stat)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Stats)]
|
||||
#[stat(desc = "cluster statistics")]
|
||||
struct ClusterStat {
|
||||
struct ClusterStats {
|
||||
cls_name: String,
|
||||
#[stat(desc = "last updated at")]
|
||||
cls_at: u64,
|
||||
#[stat(desc = "domain statistics")]
|
||||
doms_dict: BTreeMap<usize, DomainStat>,
|
||||
doms_array: Vec<DomainStat>,
|
||||
doms_dict: BTreeMap<usize, DomainStats>,
|
||||
doms_array: Vec<DomainStats>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
std::assert_eq!(args().len(), 2, "Usage: client UNIX_SOCKET_PATH");
|
||||
let path = args().nth(1).unwrap();
|
||||
|
||||
let mut client = ScxStatClient::new().set_path(path).connect().unwrap();
|
||||
let mut client = ScxStatsClient::new().set_path(path).connect().unwrap();
|
||||
|
||||
println!("===== Requesting \"stat_meta\":");
|
||||
let resp = client.request::<Vec<ScxStatMeta>>("stat_meta", vec![]);
|
||||
let resp = client.request::<Vec<ScxStatsMeta>>("stat_meta", vec![]);
|
||||
println!("{:#?}", &resp);
|
||||
|
||||
println!("\n===== Requesting \"stat\" without arguments:");
|
||||
let resp = client.request::<ClusterStat>("stat", vec![]);
|
||||
let resp = client.request::<ClusterStats>("stat", vec![]);
|
||||
println!("{:#?}", &resp);
|
||||
|
||||
println!("\n===== Requesting \"stat\" with \"target\"=\"non-existent\":");
|
||||
let resp =
|
||||
client.request::<ClusterStat>("stat", vec![("target".into(), "non-existent".into())]);
|
||||
client.request::<ClusterStats>("stat", vec![("target".into(), "non-existent".into())]);
|
||||
println!("{:#?}", &resp);
|
||||
|
||||
println!("\n===== Requesting \"stat\" with \"target\"=\"all\":");
|
||||
let resp = client.request::<ClusterStat>("stat", vec![("target".into(), "all".into())]);
|
||||
let resp = client.request::<ClusterStats>("stat", vec![("target".into(), "all".into())]);
|
||||
println!("{:#?}", &resp);
|
||||
|
||||
println!("\n===== Requesting \"stat_meta\" but receiving with serde_json::Value:");
|
@ -1,5 +1,5 @@
|
||||
use scx_stat::{ScxStatOutput, ScxStatServer, StatMeta};
|
||||
use scx_stat_derive::Stat;
|
||||
use scx_stats::{ScxStatsOutput, ScxStatsServer, StatsMeta};
|
||||
use scx_stats_derive::Stats;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::BTreeMap;
|
||||
use std::env::args;
|
||||
@ -7,9 +7,9 @@ use std::io::Read;
|
||||
|
||||
// DomainStat and ClusterStat definitions must match the ones in client.rs.
|
||||
//
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Stat)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Stats)]
|
||||
#[stat(desc = "domain statistics")]
|
||||
struct DomainStat {
|
||||
struct DomainStats {
|
||||
dom_name: String,
|
||||
#[stat(desc = "domain last updated at")]
|
||||
pub dom_at: u64,
|
||||
@ -19,25 +19,25 @@ struct DomainStat {
|
||||
dom_f_cnt: f64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Stat)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Stats)]
|
||||
#[stat(desc = "cluster statistics")]
|
||||
struct ClusterStat {
|
||||
struct ClusterStats {
|
||||
cls_name: String,
|
||||
#[stat(desc = "last updated at")]
|
||||
cls_at: u64,
|
||||
#[stat(desc = "domain statistics")]
|
||||
doms_dict: BTreeMap<usize, DomainStat>,
|
||||
doms_array: Vec<DomainStat>,
|
||||
doms_dict: BTreeMap<usize, DomainStats>,
|
||||
doms_array: Vec<DomainStats>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let stat = ClusterStat {
|
||||
let stat = ClusterStats {
|
||||
cls_name: "test cluster".into(),
|
||||
cls_at: 12345,
|
||||
doms_dict: BTreeMap::from([
|
||||
(
|
||||
0,
|
||||
DomainStat {
|
||||
DomainStats {
|
||||
dom_name: "domain 0".into(),
|
||||
dom_at: 1234,
|
||||
dom_i_cnt: -1234,
|
||||
@ -47,7 +47,7 @@ fn main() {
|
||||
),
|
||||
(
|
||||
3,
|
||||
DomainStat {
|
||||
DomainStats {
|
||||
dom_name: "domain 3".into(),
|
||||
dom_at: 5678,
|
||||
dom_i_cnt: -5678,
|
||||
@ -57,14 +57,14 @@ fn main() {
|
||||
),
|
||||
]),
|
||||
doms_array: vec![
|
||||
DomainStat {
|
||||
DomainStats {
|
||||
dom_name: "domain 5".into(),
|
||||
dom_at: 5555,
|
||||
dom_i_cnt: -5555,
|
||||
dom_u_cnt: 5555,
|
||||
dom_f_cnt: 5.555,
|
||||
},
|
||||
DomainStat {
|
||||
DomainStats {
|
||||
dom_name: "domain 7".into(),
|
||||
dom_at: 7777,
|
||||
dom_i_cnt: -7777,
|
||||
@ -77,10 +77,10 @@ fn main() {
|
||||
std::assert_eq!(args().len(), 2, "Usage: server UNIX_SOCKET_PATH");
|
||||
let path = args().nth(1).unwrap();
|
||||
|
||||
ScxStatServer::new()
|
||||
ScxStatsServer::new()
|
||||
.set_path(&path)
|
||||
.add_stat_meta(ClusterStat::stat_meta())
|
||||
.add_stat_meta(DomainStat::stat_meta())
|
||||
.add_stat_meta(ClusterStats::stat_meta())
|
||||
.add_stat_meta(DomainStats::stat_meta())
|
||||
.add_stat("all", Box::new(move |_| stat.output()))
|
||||
.launch()
|
||||
.unwrap();
|
@ -1,4 +1,4 @@
|
||||
custom_target('scx_stat',
|
||||
custom_target('scx_stats',
|
||||
output: '@PLAINNAME@.__PHONY__',
|
||||
input: 'Cargo.toml',
|
||||
command: [cargo, 'build', '--manifest-path=@INPUT@', '--target-dir=@OUTDIR@',
|
@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "scx_stat_derive"
|
||||
name = "scx_stats_derive"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
@ -9,6 +9,6 @@ proc-macro = true
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0"
|
||||
quote = "1.0"
|
||||
scx_stat = { path = "..", version = "0.1.0" }
|
||||
scx_stats = { path = "..", version = "0.1.0" }
|
||||
serde_json = "1.0"
|
||||
syn = { version = "2.0", features = ["extra-traits", "full"] }
|
@ -1,26 +1,26 @@
|
||||
use quote::{format_ident, quote, quote_spanned};
|
||||
use scx_stat::{ScxStatData, ScxStatKind, ScxStatMetaAux};
|
||||
use scx_stats::{ScxStatsData, ScxStatsKind, ScxStatsMetaAux};
|
||||
use syn::parse_macro_input;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
#[proc_macro_derive(Stat, attributes(stat))]
|
||||
#[proc_macro_derive(Stats, attributes(stat))]
|
||||
pub fn stat(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let stat_aux = parse_macro_input!(input as ScxStatMetaAux);
|
||||
let stat_aux = parse_macro_input!(input as ScxStatsMetaAux);
|
||||
let (meta, ident, paths) = (stat_aux.meta, stat_aux.ident, stat_aux.paths);
|
||||
|
||||
let mut output = proc_macro2::TokenStream::new();
|
||||
|
||||
for (idx, field) in meta.fields.iter().enumerate() {
|
||||
match &field.data {
|
||||
ScxStatData::Datum(datum)
|
||||
| ScxStatData::Array(datum)
|
||||
| ScxStatData::Dict { key: _, datum } => {
|
||||
if let ScxStatKind::Struct(name) = &datum {
|
||||
ScxStatsData::Datum(datum)
|
||||
| ScxStatsData::Array(datum)
|
||||
| ScxStatsData::Dict { key: _, datum } => {
|
||||
if let ScxStatsKind::Struct(name) = &datum {
|
||||
let path = &paths[name.as_str()];
|
||||
let assert_id = format_ident!("_AssertScxStatMeta_{}", idx);
|
||||
let assert_id = format_ident!("_AssertScxStatsMeta_{}", idx);
|
||||
#[rustfmt::skip]
|
||||
let assert = quote_spanned! {path.span()=>
|
||||
struct #assert_id where #path: scx_stat::StatMeta;
|
||||
struct #assert_id where #path: scx_stats::StatsMeta;
|
||||
};
|
||||
output.extend(assert.into_iter());
|
||||
}
|
||||
@ -31,10 +31,10 @@ pub fn stat(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let body = serde_json::to_string(&meta).unwrap();
|
||||
let trait_body = quote! {
|
||||
#[rustfmt::skip]
|
||||
impl scx_stat::StatMeta for #ident {
|
||||
fn stat_meta() -> scx_stat::ScxStatMeta {
|
||||
impl scx_stats::StatsMeta for #ident {
|
||||
fn stat_meta() -> scx_stats::ScxStatsMeta {
|
||||
let body = #body;
|
||||
scx_stat::serde_json::from_str(body).unwrap()
|
||||
scx_stats::serde_json::from_str(body).unwrap()
|
||||
}
|
||||
}
|
||||
};
|
@ -1,11 +1,11 @@
|
||||
use crate::{ScxStatErrno, ScxStatRequest, ScxStatResponse};
|
||||
use crate::{ScxStatsErrno, ScxStatsRequest, ScxStatsResponse};
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use serde::Deserialize;
|
||||
use std::io::{BufRead, BufReader, Write};
|
||||
use std::os::unix::net::UnixStream;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub struct ScxStatClient {
|
||||
pub struct ScxStatsClient {
|
||||
base_path: PathBuf,
|
||||
sched_path: PathBuf,
|
||||
stat_path: PathBuf,
|
||||
@ -15,7 +15,7 @@ pub struct ScxStatClient {
|
||||
reader: Option<BufReader<UnixStream>>,
|
||||
}
|
||||
|
||||
impl ScxStatClient {
|
||||
impl ScxStatsClient {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
base_path: PathBuf::from("/var/run/scx"),
|
||||
@ -60,7 +60,7 @@ impl ScxStatClient {
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn send_request<T>(&mut self, req: &ScxStatRequest) -> Result<T>
|
||||
pub fn send_request<T>(&mut self, req: &ScxStatsRequest) -> Result<T>
|
||||
where
|
||||
T: for<'a> Deserialize<'a>,
|
||||
{
|
||||
@ -73,7 +73,7 @@ impl ScxStatClient {
|
||||
|
||||
let mut line = String::new();
|
||||
self.reader.as_mut().unwrap().read_line(&mut line)?;
|
||||
let mut resp: ScxStatResponse = serde_json::from_str(&line)?;
|
||||
let mut resp: ScxStatsResponse = serde_json::from_str(&line)?;
|
||||
|
||||
let (errno, resp) = (
|
||||
resp.errno,
|
||||
@ -81,7 +81,7 @@ impl ScxStatClient {
|
||||
);
|
||||
|
||||
if errno != 0 {
|
||||
Err(anyhow!("{}", &resp).context(ScxStatErrno(errno)))?;
|
||||
Err(anyhow!("{}", &resp).context(ScxStatsErrno(errno)))?;
|
||||
}
|
||||
|
||||
Ok(serde_json::from_value(resp)?)
|
||||
@ -91,6 +91,6 @@ impl ScxStatClient {
|
||||
where
|
||||
T: for<'a> Deserialize<'a>,
|
||||
{
|
||||
self.send_request(&ScxStatRequest::new(req, args))
|
||||
self.send_request(&ScxStatsRequest::new(req, args))
|
||||
}
|
||||
}
|
15
rust/scx_stats/src/lib.rs
Normal file
15
rust/scx_stats/src/lib.rs
Normal file
@ -0,0 +1,15 @@
|
||||
pub use serde_json;
|
||||
|
||||
mod stats;
|
||||
pub use stats::{
|
||||
ScxStatsAttr, ScxStatsAttrs, ScxStatsData, ScxStatsField, ScxStatsKind, ScxStatsMeta,
|
||||
ScxStatsMetaAux, StatsMeta,
|
||||
};
|
||||
|
||||
mod server;
|
||||
pub use server::{
|
||||
ScxStatsErrno, ScxStatsOutput, ScxStatsRequest, ScxStatsResponse, ScxStatsServer,
|
||||
};
|
||||
|
||||
mod client;
|
||||
pub use client::ScxStatsClient;
|
@ -1,4 +1,4 @@
|
||||
use crate::{ScxStatMeta, StatMeta};
|
||||
use crate::{ScxStatsMeta, StatsMeta};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use log::warn;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -15,13 +15,13 @@ type StatMap = BTreeMap<
|
||||
>;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct ScxStatRequest {
|
||||
pub struct ScxStatsRequest {
|
||||
pub req: String,
|
||||
#[serde(default)]
|
||||
pub args: BTreeMap<String, String>,
|
||||
}
|
||||
|
||||
impl ScxStatRequest {
|
||||
impl ScxStatsRequest {
|
||||
pub fn new(req: &str, args: Vec<(String, String)>) -> Self {
|
||||
Self {
|
||||
req: req.to_string(),
|
||||
@ -31,48 +31,48 @@ impl ScxStatRequest {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct ScxStatResponse {
|
||||
pub struct ScxStatsResponse {
|
||||
pub errno: i32,
|
||||
pub args: BTreeMap<String, serde_json::Value>,
|
||||
}
|
||||
|
||||
pub struct ScxStatErrno(pub i32);
|
||||
pub struct ScxStatsErrno(pub i32);
|
||||
|
||||
impl std::fmt::Display for ScxStatErrno {
|
||||
impl std::fmt::Display for ScxStatsErrno {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{}", std::io::Error::from_raw_os_error(self.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for ScxStatErrno {
|
||||
impl std::fmt::Debug for ScxStatsErrno {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", std::io::Error::from_raw_os_error(self.0))
|
||||
}
|
||||
}
|
||||
|
||||
struct ScxStatServerData {
|
||||
stat_meta: Vec<ScxStatMeta>,
|
||||
struct ScxStatsServerData {
|
||||
stat_meta: Vec<ScxStatsMeta>,
|
||||
stat: StatMap,
|
||||
}
|
||||
|
||||
struct ScxStatServerInner {
|
||||
struct ScxStatsServerInner {
|
||||
listener: UnixListener,
|
||||
data: Arc<Mutex<ScxStatServerData>>,
|
||||
data: Arc<Mutex<ScxStatsServerData>>,
|
||||
}
|
||||
|
||||
impl ScxStatServerInner {
|
||||
fn new(listener: UnixListener, stat_meta: Vec<ScxStatMeta>, stat: StatMap) -> Self {
|
||||
impl ScxStatsServerInner {
|
||||
fn new(listener: UnixListener, stat_meta: Vec<ScxStatsMeta>, stat: StatMap) -> Self {
|
||||
Self {
|
||||
listener,
|
||||
data: Arc::new(Mutex::new(ScxStatServerData { stat_meta, stat })),
|
||||
data: Arc::new(Mutex::new(ScxStatsServerData { stat_meta, stat })),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_resp<T>(errno: i32, resp: &T) -> Result<ScxStatResponse>
|
||||
fn build_resp<T>(errno: i32, resp: &T) -> Result<ScxStatsResponse>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
Ok(ScxStatResponse {
|
||||
Ok(ScxStatsResponse {
|
||||
errno,
|
||||
args: [("resp".into(), serde_json::to_value(resp)?)]
|
||||
.into_iter()
|
||||
@ -82,9 +82,9 @@ impl ScxStatServerInner {
|
||||
|
||||
fn handle_request(
|
||||
line: String,
|
||||
data: &Arc<Mutex<ScxStatServerData>>,
|
||||
) -> Result<ScxStatResponse> {
|
||||
let req: ScxStatRequest = serde_json::from_str(&line)?;
|
||||
data: &Arc<Mutex<ScxStatsServerData>>,
|
||||
) -> Result<ScxStatsResponse> {
|
||||
let req: ScxStatsRequest = serde_json::from_str(&line)?;
|
||||
|
||||
match req.req.as_str() {
|
||||
"stat" => {
|
||||
@ -96,7 +96,7 @@ impl ScxStatServerInner {
|
||||
let handler = match data.lock().unwrap().stat.get(target) {
|
||||
Some(v) => v.clone(),
|
||||
None => Err(anyhow!("unknown stat target {:?}", req)
|
||||
.context(ScxStatErrno(libc::EINVAL)))?,
|
||||
.context(ScxStatsErrno(libc::EINVAL)))?,
|
||||
};
|
||||
|
||||
let resp = handler.lock().unwrap()(&req.args)?;
|
||||
@ -104,11 +104,11 @@ impl ScxStatServerInner {
|
||||
Self::build_resp(0, &resp)
|
||||
}
|
||||
"stat_meta" => Ok(Self::build_resp(0, &data.lock().unwrap().stat_meta)?),
|
||||
req => Err(anyhow!("unknown command {:?}", req).context(ScxStatErrno(libc::EINVAL)))?,
|
||||
req => Err(anyhow!("unknown command {:?}", req).context(ScxStatsErrno(libc::EINVAL)))?,
|
||||
}
|
||||
}
|
||||
|
||||
fn serve(mut stream: UnixStream, data: Arc<Mutex<ScxStatServerData>>) -> Result<()> {
|
||||
fn serve(mut stream: UnixStream, data: Arc<Mutex<ScxStatsServerData>>) -> Result<()> {
|
||||
let mut reader = BufReader::new(stream.try_clone()?);
|
||||
|
||||
loop {
|
||||
@ -121,7 +121,7 @@ impl ScxStatServerInner {
|
||||
let resp = match Self::handle_request(line, &data) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
let errno = match e.downcast_ref::<ScxStatErrno>() {
|
||||
let errno = match e.downcast_ref::<ScxStatsErrno>() {
|
||||
Some(e) if e.0 != 0 => e.0,
|
||||
_ => libc::EINVAL,
|
||||
};
|
||||
@ -153,17 +153,17 @@ impl ScxStatServerInner {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ScxStatServer {
|
||||
pub struct ScxStatsServer {
|
||||
base_path: PathBuf,
|
||||
sched_path: PathBuf,
|
||||
stat_path: PathBuf,
|
||||
path: Option<PathBuf>,
|
||||
|
||||
stat_meta_holder: Vec<ScxStatMeta>,
|
||||
stat_meta_holder: Vec<ScxStatsMeta>,
|
||||
stat_holder: StatMap,
|
||||
}
|
||||
|
||||
impl ScxStatServer {
|
||||
impl ScxStatsServer {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
base_path: PathBuf::from("/var/run/scx"),
|
||||
@ -176,7 +176,7 @@ impl ScxStatServer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_stat_meta(mut self, meta: ScxStatMeta) -> Self {
|
||||
pub fn add_stat_meta(mut self, meta: ScxStatsMeta) -> Self {
|
||||
self.stat_meta_holder.push(meta);
|
||||
self
|
||||
}
|
||||
@ -236,20 +236,20 @@ impl ScxStatServer {
|
||||
std::mem::swap(&mut stat_meta, &mut self.stat_meta_holder);
|
||||
std::mem::swap(&mut stat, &mut self.stat_holder);
|
||||
|
||||
let inner = ScxStatServerInner::new(listener, stat_meta, stat);
|
||||
let inner = ScxStatsServerInner::new(listener, stat_meta, stat);
|
||||
|
||||
spawn(move || inner.listen());
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ScxStatOutput {
|
||||
pub trait ScxStatsOutput {
|
||||
fn output(&self) -> Result<serde_json::Value>;
|
||||
}
|
||||
|
||||
impl<T> ScxStatOutput for T
|
||||
impl<T> ScxStatsOutput for T
|
||||
where
|
||||
T: StatMeta + Serialize,
|
||||
T: StatsMeta + Serialize,
|
||||
{
|
||||
fn output(&self) -> Result<serde_json::Value> {
|
||||
Ok(serde_json::to_value(self)?)
|
@ -9,7 +9,7 @@ use syn::{
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum ScxStatKind {
|
||||
pub enum ScxStatsKind {
|
||||
I64,
|
||||
U64,
|
||||
Float,
|
||||
@ -17,7 +17,7 @@ pub enum ScxStatKind {
|
||||
Struct(String),
|
||||
}
|
||||
|
||||
impl ScxStatKind {
|
||||
impl ScxStatsKind {
|
||||
pub fn new(ty: &Type, paths: &mut BTreeMap<String, Path>) -> syn::Result<Self> {
|
||||
match ty {
|
||||
Type::Reference(reference) => return Self::new(&reference.elem, paths),
|
||||
@ -37,7 +37,7 @@ impl ScxStatKind {
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Err(Error::new(ty.span(), "ScxStat: Unsupported element type"))
|
||||
Err(Error::new(ty.span(), "ScxStats: Unsupported element type"))
|
||||
}
|
||||
|
||||
pub fn can_be_dict_key(&self) -> bool {
|
||||
@ -49,19 +49,19 @@ impl ScxStatKind {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum ScxStatData {
|
||||
pub enum ScxStatsData {
|
||||
#[serde(rename = "datum")]
|
||||
Datum(ScxStatKind),
|
||||
Datum(ScxStatsKind),
|
||||
#[serde(rename = "array")]
|
||||
Array(ScxStatKind),
|
||||
Array(ScxStatsKind),
|
||||
#[serde(rename = "dict")]
|
||||
Dict {
|
||||
key: ScxStatKind,
|
||||
datum: ScxStatKind,
|
||||
key: ScxStatsKind,
|
||||
datum: ScxStatsKind,
|
||||
},
|
||||
}
|
||||
|
||||
impl ScxStatData {
|
||||
impl ScxStatsData {
|
||||
fn new_array(path: &Path, paths: &mut BTreeMap<String, Path>) -> syn::Result<Option<Self>> {
|
||||
if path.leading_colon.is_some() {
|
||||
return Ok(None);
|
||||
@ -88,7 +88,7 @@ impl ScxStatData {
|
||||
}
|
||||
|
||||
match &args[0] {
|
||||
GenericArgument::Type(ty) => Ok(Some(Self::Array(ScxStatKind::new(&ty, paths)?))),
|
||||
GenericArgument::Type(ty) => Ok(Some(Self::Array(ScxStatsKind::new(&ty, paths)?))),
|
||||
_ => Ok(None),
|
||||
}
|
||||
} else {
|
||||
@ -123,8 +123,8 @@ impl ScxStatData {
|
||||
|
||||
match (&args[0], &args[1]) {
|
||||
(GenericArgument::Type(ty0), GenericArgument::Type(ty1)) => {
|
||||
let kind0 = ScxStatKind::new(&ty0, paths)?;
|
||||
let kind1 = ScxStatKind::new(&ty1, paths)?;
|
||||
let kind0 = ScxStatsKind::new(&ty0, paths)?;
|
||||
let kind1 = ScxStatsKind::new(&ty1, paths)?;
|
||||
|
||||
if kind0.can_be_dict_key() {
|
||||
Ok(Some(Self::Dict {
|
||||
@ -143,8 +143,8 @@ impl ScxStatData {
|
||||
}
|
||||
|
||||
pub fn new(ty: &Type, paths: &mut BTreeMap<String, Path>) -> syn::Result<Self> {
|
||||
let kind = ScxStatKind::new(ty, paths)?;
|
||||
if let ScxStatKind::Struct(_) = &kind {
|
||||
let kind = ScxStatsKind::new(ty, paths)?;
|
||||
if let ScxStatsKind::Struct(_) = &kind {
|
||||
if let Type::Path(path) = ty {
|
||||
if let Some(ar) = Self::new_array(&path.path, paths)? {
|
||||
return Ok(ar);
|
||||
@ -159,11 +159,11 @@ impl ScxStatData {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum ScxStatAttr {
|
||||
pub enum ScxStatsAttr {
|
||||
Desc(String),
|
||||
}
|
||||
|
||||
impl Parse for ScxStatAttr {
|
||||
impl Parse for ScxStatsAttr {
|
||||
fn parse(input: &ParseBuffer) -> syn::Result<Self> {
|
||||
let ident = input.parse::<Ident>()?;
|
||||
match ident.to_string().as_str() {
|
||||
@ -177,19 +177,19 @@ impl Parse for ScxStatAttr {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct ScxStatAttrs {
|
||||
pub struct ScxStatsAttrs {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub desc: Option<String>,
|
||||
}
|
||||
|
||||
impl ScxStatAttrs {
|
||||
impl ScxStatsAttrs {
|
||||
pub fn new(attrs: &[Attribute]) -> syn::Result<Self> {
|
||||
let mut desc: Option<String> = None;
|
||||
|
||||
for attr in attrs {
|
||||
if attr.path().is_ident("stat") {
|
||||
match attr.parse_args::<ScxStatAttr>()? {
|
||||
ScxStatAttr::Desc(v) => desc = Some(v),
|
||||
match attr.parse_args::<ScxStatsAttr>()? {
|
||||
ScxStatsAttr::Desc(v) => desc = Some(v),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -199,54 +199,54 @@ impl ScxStatAttrs {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct ScxStatField {
|
||||
pub struct ScxStatsField {
|
||||
pub name: String,
|
||||
#[serde(flatten)]
|
||||
pub data: ScxStatData,
|
||||
pub data: ScxStatsData,
|
||||
#[serde(flatten)]
|
||||
pub attrs: ScxStatAttrs,
|
||||
pub attrs: ScxStatsAttrs,
|
||||
}
|
||||
|
||||
impl ScxStatField {
|
||||
impl ScxStatsField {
|
||||
pub fn new(field: &Field, paths: &mut BTreeMap<String, Path>) -> syn::Result<Self> {
|
||||
Ok(Self {
|
||||
name: field.ident.as_ref().unwrap().to_string(),
|
||||
data: ScxStatData::new(&field.ty, paths)?,
|
||||
attrs: ScxStatAttrs::new(&field.attrs)?,
|
||||
data: ScxStatsData::new(&field.ty, paths)?,
|
||||
attrs: ScxStatsAttrs::new(&field.attrs)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct ScxStatMeta {
|
||||
pub struct ScxStatsMeta {
|
||||
pub name: String,
|
||||
pub desc: Option<String>,
|
||||
pub fields: Vec<ScxStatField>,
|
||||
pub fields: Vec<ScxStatsField>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ScxStatMetaAux {
|
||||
pub meta: ScxStatMeta,
|
||||
pub struct ScxStatsMetaAux {
|
||||
pub meta: ScxStatsMeta,
|
||||
pub ident: Ident,
|
||||
pub paths: BTreeMap<String, Path>,
|
||||
}
|
||||
|
||||
impl Parse for ScxStatMetaAux {
|
||||
impl Parse for ScxStatsMetaAux {
|
||||
fn parse(input: &ParseBuffer) -> syn::Result<Self> {
|
||||
let mut paths = BTreeMap::new();
|
||||
let mut fields = vec![];
|
||||
|
||||
let item_struct: ItemStruct = input.parse()?;
|
||||
let attrs = ScxStatAttrs::new(&item_struct.attrs)?;
|
||||
let attrs = ScxStatsAttrs::new(&item_struct.attrs)?;
|
||||
|
||||
if let Fields::Named(named_fields) = &item_struct.fields {
|
||||
for field in named_fields.named.iter() {
|
||||
fields.push(ScxStatField::new(field, &mut paths)?);
|
||||
fields.push(ScxStatsField::new(field, &mut paths)?);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
meta: ScxStatMeta {
|
||||
meta: ScxStatsMeta {
|
||||
name: item_struct.ident.to_string(),
|
||||
desc: attrs.desc,
|
||||
fields,
|
||||
@ -257,6 +257,6 @@ impl Parse for ScxStatMetaAux {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait StatMeta {
|
||||
fn stat_meta() -> ScxStatMeta;
|
||||
pub trait StatsMeta {
|
||||
fn stat_meta() -> ScxStatsMeta;
|
||||
}
|
@ -16,8 +16,8 @@ lazy_static = "1.4"
|
||||
libbpf-rs = "0.24.1"
|
||||
libc = "0.2.137"
|
||||
log = "0.4.17"
|
||||
scx_stat = { path = "../../../rust/scx_stat", version = "0.1.0" }
|
||||
scx_stat_derive = { path = "../../../rust/scx_stat/scx_stat_derive", version = "0.1.0" }
|
||||
scx_stats = { path = "../../../rust/scx_stats", version = "0.1.0" }
|
||||
scx_stats_derive = { path = "../../../rust/scx_stats/scx_stats_derive", version = "0.1.0" }
|
||||
scx_utils = { path = "../../../rust/scx_utils", version = "1.0.2" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
@ -37,10 +37,10 @@ use log::debug;
|
||||
use log::info;
|
||||
use log::trace;
|
||||
use log::warn;
|
||||
use scx_stat::ScxStatOutput;
|
||||
use scx_stat::ScxStatServer;
|
||||
use scx_stat::StatMeta;
|
||||
use scx_stat_derive::Stat;
|
||||
use scx_stats::ScxStatsOutput;
|
||||
use scx_stats::ScxStatsServer;
|
||||
use scx_stats::StatsMeta;
|
||||
use scx_stats_derive::Stats;
|
||||
use scx_utils::compat;
|
||||
use scx_utils::init_libbpf_logging;
|
||||
use scx_utils::ravg::ravg_read;
|
||||
@ -1219,7 +1219,7 @@ impl Layer {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, Stat)]
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, Stats)]
|
||||
struct LayerStats {
|
||||
#[stat(desc = "CPU utilization of the layer (100% means one CPU was fully occupied)")]
|
||||
util: f64,
|
||||
@ -1295,7 +1295,7 @@ struct LayerStats {
|
||||
max_nr_cpus: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, Stat)]
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, Stats)]
|
||||
struct SysStats {
|
||||
#[stat(desc = "Update interval")]
|
||||
intv: f64,
|
||||
@ -1592,7 +1592,7 @@ impl<'a, 'b> Scheduler<'a, 'b> {
|
||||
sys_stats: sys_stats.clone(),
|
||||
};
|
||||
|
||||
ScxStatServer::new()
|
||||
ScxStatsServer::new()
|
||||
.add_stat_meta(LayerStats::stat_meta())
|
||||
.add_stat_meta(SysStats::stat_meta())
|
||||
.add_stat("all", Box::new(move |_| sys_stats.lock().unwrap().output()))
|
||||
|
@ -2,13 +2,13 @@ use crate::SysStats;
|
||||
use anyhow::Result;
|
||||
use log::info;
|
||||
use log::warn;
|
||||
use scx_stat::ScxStatClient;
|
||||
use scx_stats::ScxStatsClient;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
fn print_sys_stat(s: &SysStats) {
|
||||
fn print_sys_stats(s: &SysStats) {
|
||||
let fmt_pct = |v: f64| {
|
||||
if v >= 99.995 {
|
||||
format!("{:5.1}", v)
|
||||
@ -135,10 +135,10 @@ fn print_sys_stat(s: &SysStats) {
|
||||
}
|
||||
|
||||
pub fn monitor(shutdown: Arc<AtomicBool>) -> Result<()> {
|
||||
let mut client = ScxStatClient::new().connect()?;
|
||||
let mut client = ScxStatsClient::new().connect()?;
|
||||
while !shutdown.load(Ordering::Relaxed) {
|
||||
let sst = client.request::<SysStats>("stat", vec![])?;
|
||||
print_sys_stat(&sst);
|
||||
print_sys_stats(&sst);
|
||||
std::thread::sleep(Duration::from_secs_f64(sst.intv));
|
||||
}
|
||||
Ok(())
|
||||
|
Loading…
Reference in New Issue
Block a user