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:
Tejun Heo 2024-08-15 05:31:34 -10:00
parent 6e466d18df
commit 8aae9a5de2
15 changed files with 150 additions and 148 deletions

View File

@ -1,3 +1,3 @@
subdir('scx_utils')
subdir('scx_stat')
subdir('scx_stats')
subdir('scx_rustland_core')

View File

@ -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;

View File

@ -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" }

View File

@ -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:");

View File

@ -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();

View File

@ -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@',

View File

@ -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"] }

View File

@ -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()
}
}
};

View File

@ -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
View 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;

View File

@ -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)?)

View File

@ -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;
}

View File

@ -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"

View File

@ -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()))

View File

@ -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(())