Skip to main content

scx_eevdf/
console.rs

1// SPDX-License-Identifier: GPL-2.0
2//
3// Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES.
4
5// This software may be used and distributed according to the terms of the
6// GNU General Public License version 2.
7
8//! The console style shared by the startup report, the stats blocks and the
9//! status lines: a header line of `|`-separated fields, then aligned rows.
10//! Every line goes through the logger at info level, so it carries the same
11//! time stamp and prefix as any other message, in plain ASCII, appended and
12//! never redrawn.
13
14use log::info;
15
16/// One line of output, through the logger.
17pub fn emit(line: &str) {
18    info!("{line}");
19}
20
21/// The header line: the scheduler name and version, then the caller's
22/// fields.
23pub fn header(fields: &[String]) -> String {
24    let mut parts = vec![format!(
25        "{} {}",
26        crate::SCHEDULER_NAME,
27        env!("CARGO_PKG_VERSION")
28    )];
29    parts.extend(fields.iter().cloned());
30    parts.join(" | ")
31}
32
33/// The running kernel's release string, what uname -r prints.
34pub fn kernel_release() -> String {
35    let mut uts: libc::utsname = unsafe { std::mem::zeroed() };
36    if unsafe { libc::uname(&mut uts) } != 0 {
37        return "unknown".to_string();
38    }
39    unsafe { std::ffi::CStr::from_ptr(uts.release.as_ptr()) }
40        .to_string_lossy()
41        .into_owned()
42}
43
44/// One status line: the scheduler is attached and running, or it has
45/// stopped and why.
46pub fn status(msg: &str) {
47    emit(&format!("{} {}", crate::SCHEDULER_NAME, msg));
48}
49
50/// A block of aligned `key  value` rows under a header, printed once.
51pub struct Report {
52    fields: Vec<String>,
53    rows: Vec<(String, String)>,
54}
55
56impl Report {
57    pub fn new() -> Self {
58        Self {
59            fields: Vec::new(),
60            rows: Vec::new(),
61        }
62    }
63
64    /// A header field, after the name and version.
65    pub fn field(&mut self, s: impl Into<String>) {
66        self.fields.push(s.into());
67    }
68
69    pub fn row(&mut self, key: impl Into<String>, value: impl std::fmt::Display) {
70        self.rows.push((key.into(), value.to_string()));
71    }
72
73    pub fn print(&self) {
74        emit(&header(&self.fields));
75        let width = self.rows.iter().map(|(k, _)| k.len()).max().unwrap_or(0);
76        for (key, value) in &self.rows {
77            emit(&format!("{key:<width$}  {value}"));
78        }
79    }
80}