Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
log: New crate for logger implementations
✓ CI success Adrian Duke committed 3 days ago
commit 94e577cf034b238697c4e11a5bcc156e79207f9c
parent 5eae519b5464ec9ae664df96140d61d5fc426fc3
1 passed (1 total) View logs
20 files changed +237 -191
modified Cargo.lock
@@ -2981,8 +2981,6 @@ dependencies = [
 "amplify",
 "base64 0.21.7",
 "bytesize",
-
 "chrono",
-
 "colored",
 "crossbeam-channel",
 "cyphernet",
 "dunce",
@@ -3038,6 +3036,7 @@ dependencies = [
 "radicle-cob",
 "radicle-crypto",
 "radicle-localtime",
+
 "radicle-log",
 "radicle-node",
 "radicle-surf",
 "radicle-term",
@@ -3073,6 +3072,8 @@ dependencies = [
 "log",
 "pretty_assertions",
 "radicle",
+
 "radicle-log",
+
 "radicle-term",
 "shlex",
 "snapbox",
 "thiserror 2.0.18",
@@ -3209,6 +3210,18 @@ dependencies = [
]

[[package]]
+
name = "radicle-log"
+
version = "0.1.0"
+
dependencies = [
+
 "chrono",
+
 "colored",
+
 "log",
+
 "radicle-localtime",
+
 "radicle-term",
+
 "regex",
+
]
+

+
[[package]]
name = "radicle-node"
version = "0.19.0"
dependencies = [
@@ -3228,6 +3241,7 @@ dependencies = [
 "radicle-crypto",
 "radicle-fetch",
 "radicle-localtime",
+
 "radicle-log",
 "radicle-protocol",
 "radicle-signals",
 "radicle-systemd",
@@ -3289,6 +3303,7 @@ dependencies = [
 "log",
 "radicle",
 "radicle-cli",
+
 "radicle-log",
 "thiserror 2.0.18",
]

modified Cargo.toml
@@ -57,6 +57,7 @@ radicle-fetch = { version = "0.19", path = "crates/radicle-fetch" }
radicle-git-metadata = { version = "0.2.0", path = "crates/radicle-git-metadata", default-features = false }
radicle-git-ref-format = { version = "0.1.0", path = "crates/radicle-git-ref-format", default-features = false }
radicle-localtime = { version = "0.1", path = "crates/radicle-localtime" }
+
radicle-log = { version = "0.1", path = "crates/radicle-log" }
radicle-node = { version = "0.19", path = "crates/radicle-node" }
radicle-oid = { version = "0.1.0", path = "crates/radicle-oid", default-features = false }
radicle-protocol = { version = "0.7", path = "crates/radicle-protocol" }
modified crates/radicle-cli-test/Cargo.toml
@@ -15,7 +15,9 @@ rust-version.workspace = true
escargot = "0.5.7"
log = { workspace = true, features = ["std"] }
pretty_assertions = { workspace = true }
-
radicle = { workspace = true, features = ["logger", "test"]}
+
radicle = { workspace = true, features = ["test"] }
+
radicle-log = { workspace = true, features = ["test"] }
+
radicle-term = { workspace = true }
snapbox = { workspace = true }
thiserror = { workspace = true, default-features = true }

modified crates/radicle-cli-test/src/lib.rs
@@ -186,8 +186,9 @@ impl TestFormula {
        // We don't need to re-build every time the `build` function is called. Once is enough.
        BUILD.call_once(|| {
            use escargot::format::Message;
-
            use radicle::logger::env_level;
-
            use radicle::logger::test::Logger;
+
            use radicle_log::env_level;
+
            use radicle_log::test::Logger;
+
            use radicle_term::Paint;

            let level = env_level().unwrap_or(log::Level::Debug);
            let logger = Box::new(Logger::new(level));
@@ -195,6 +196,14 @@ impl TestFormula {
            log::set_boxed_logger(logger).expect("no other logger should have been set already");
            log::set_max_level(level.to_level_filter());

+
            // `NO_COLOR` is supported by [`radicle-term::Paint`] - however when using `force()` we
+
            // override it. Because `cargo nextest` runs tests in a PTY and [`radicle-term::Paint`]
+
            // detects that (disabling colours), we need to use `force()` to ensure colours are painted.
+
            match env::var("NO_COLOR") {
+
                Err(_) => Paint::force(true),
+
                Ok(_) => log::info!(target: "test", "NO_COLOR detected, disabling colours."),
+
            }
+

            for (package, binary) in binaries {
                log::debug!(target: "test", "Building binaries for package `{package}`..");

modified crates/radicle-cli/Cargo.toml
@@ -29,12 +29,13 @@ humantime.workspace = true
itertools.workspace = true
log = { workspace = true, features = ["std"] }
nonempty = { workspace = true }
-
radicle = { workspace = true, features = ["logger", "schemars"] }
+
radicle = { workspace = true, features = ["schemars"] }
radicle-cob = { workspace = true }
radicle-crypto = { workspace = true }
radicle-localtime = { workspace = true }
radicle-surf = { workspace = true }
radicle-term = { workspace = true }
+
radicle-log = { workspace = true }
schemars = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
@@ -69,6 +70,7 @@ radicle = { workspace = true, features = ["test"] }
radicle-cli-test = { workspace = true }
radicle-localtime = { workspace = true }
radicle-node = { workspace = true, features = ["test"] }
+
radicle-log = { workspace = true, features = ["test"] }

[lints]
workspace = true
modified crates/radicle-cli/src/main.rs
@@ -137,8 +137,8 @@ fn main() {
        }));
    }

-
    if let Some(lvl) = radicle::logger::env_level() {
-
        let logger = Box::new(radicle::logger::Logger::new());
+
    if let Some(lvl) = radicle_log::env_level() {
+
        let logger = Box::new(radicle_log::Logger::new());
        log::set_boxed_logger(logger).expect("no other logger should have been set already");
        log::set_max_level(lvl.to_level_filter());
    }
modified crates/radicle-cli/tests/commands.rs
@@ -7,7 +7,7 @@ use radicle::prelude::RepoId;
use radicle::profile::Home;

#[allow(unused_imports)]
-
use radicle_node::test::logger;
+
use radicle_log::test::Logger;

mod util;
use util::environment::Environment;
added crates/radicle-log/Cargo.toml
@@ -0,0 +1,20 @@
+
[package]
+
name = "radicle-log"
+
description = "Radicle loggers"
+
homepage.workspace = true
+
repository.workspace = true
+
license.workspace = true
+
version = "0.1.0"
+
edition.workspace = true
+
rust-version.workspace = true
+

+
[features]
+
test = []
+

+
[dependencies]
+
chrono = { workspace = true, features = ["clock"] }
+
colored = { workspace = true }
+
radicle-localtime = { workspace = true, features = ["serde"] }
+
log = { version = "0.4", features = ["std"] }
+
radicle-term = { workspace = true }
+
regex = "1"
added crates/radicle-log/src/lib.rs
@@ -0,0 +1,103 @@
+
//! Logging module.
+
//!
+
//! For test logging see [`mod@test`].
+

+
#[cfg(feature = "test")]
+
pub mod test;
+

+
use std::io::{self, Write};
+

+
use chrono::prelude::*;
+
use colored::*;
+
use log::{Level, Log, Metadata, Record};
+

+
/// A logger that logs to `stdout`.
+
pub struct Logger;
+

+
impl Logger {
+
    pub fn new() -> Self {
+
        Self
+
    }
+
}
+

+
impl Default for Logger {
+
    fn default() -> Self {
+
        Self::new()
+
    }
+
}
+

+
impl Log for Logger {
+
    fn enabled(&self, metadata: &Metadata) -> bool {
+
        metadata.level() <= log::max_level()
+
    }
+

+
    fn log(&self, record: &Record) {
+
        if self.enabled(record.metadata()) {
+
            let target = record.target();
+

+
            let message = format!(
+
                "{:<5} {:<8} {}",
+
                record.level(),
+
                target.cyan(),
+
                record.args()
+
            );
+

+
            let message = format!(
+
                "{} {}",
+
                Local::now().to_rfc3339_opts(SecondsFormat::Millis, true),
+
                message,
+
            );
+

+
            let message = match record.level() {
+
                Level::Error => message.red(),
+
                Level::Warn => message.yellow(),
+
                Level::Info => message.normal(),
+
                Level::Debug => message.dimmed(),
+
                Level::Trace => message.white().dimmed(),
+
            };
+
            writeln!(&mut io::stdout(), "{message}").expect("write shouldn't fail");
+
        }
+
    }
+

+
    fn flush(&self) {}
+
}
+

+
/// A logger that logs to `stderr`.
+
pub struct StderrLogger;
+

+
impl StderrLogger {
+
    pub fn new() -> Self {
+
        Self
+
    }
+
}
+

+
impl Default for StderrLogger {
+
    fn default() -> Self {
+
        Self::new()
+
    }
+
}
+

+
impl Log for StderrLogger {
+
    fn enabled(&self, metadata: &Metadata) -> bool {
+
        metadata.level() <= log::max_level()
+
    }
+

+
    fn log(&self, record: &Record) {
+
        let message = format!(
+
            "{:<5} {:<8} {}",
+
            record.level(),
+
            record.target(),
+
            record.args()
+
        );
+
        writeln!(&mut io::stderr(), "{message}").expect("write shouldn't fail");
+
    }
+

+
    fn flush(&self) {}
+
}
+

+
/// Get the level set by the environment variable `RUST_LOG`, if
+
/// present.
+
pub fn env_level() -> Option<Level> {
+
    let level = std::env::var("RUST_LOG").ok()?;
+
    level.parse().ok()
+
}
added crates/radicle-log/src/test.rs
@@ -0,0 +1,65 @@
+
use log::*;
+
use radicle_localtime::LocalTime;
+

+
pub struct Logger {
+
    level: Level,
+
}
+

+
impl Logger {
+
    pub fn new(level: Level) -> Self {
+
        Self { level }
+
    }
+
}
+

+
impl Log for Logger {
+
    fn enabled(&self, metadata: &Metadata) -> bool {
+
        metadata.level() <= self.level
+
    }
+

+
    fn log(&self, record: &Record) {
+
        use colored::Colorize;
+
        let time = LocalTime::now().as_secs();
+

+
        match record.target() {
+
            "test" => {
+
                println!(
+
                    "{time} {} {}",
+
                    "test:".cyan(),
+
                    record.args().to_string().cyan()
+
                )
+
            }
+
            "sim" => {
+
                println!(
+
                    "{time} {}  {}",
+
                    "sim:".bold(),
+
                    record.args().to_string().bold()
+
                )
+
            }
+
            target => {
+
                if self.enabled(record.metadata()) {
+
                    let current = std::thread::current();
+
                    let msg = format!("{:>10} {}", format!("{target}:"), record.args());
+
                    let time = LocalTime::now().as_secs();
+
                    let s = if let Some(name) = current.name() {
+
                        format!("{time} {name:<16} {msg}")
+
                    } else {
+
                        format!("{time} {msg}")
+
                    };
+
                    match record.level() {
+
                        log::Level::Warn => {
+
                            println!("{}", s.yellow());
+
                        }
+
                        log::Level::Error => {
+
                            println!("{}", s.red());
+
                        }
+
                        _ => {
+
                            println!("{}", s.dimmed());
+
                        }
+
                    }
+
                }
+
            }
+
        }
+
    }
+

+
    fn flush(&self) {}
+
}
modified crates/radicle-node/Cargo.toml
@@ -28,11 +28,12 @@ lexopt = { workspace = true }
log = { workspace = true, features = ["kv", "std"] }
mio = { version = "1", features = ["net", "os-poll"] }
qcheck = { workspace = true, optional = true }
-
radicle = { workspace = true, features = ["logger"] }
+
radicle = { workspace = true }
radicle-fetch = { workspace = true }
radicle-localtime = { workspace = true }
radicle-protocol = { workspace = true }
radicle-signals = { workspace = true }
+
radicle-log = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true, features = ["preserve_order"] }
snapbox = { workspace = true, optional = true }
@@ -53,6 +54,7 @@ mio = { version = "1", features = ["os-ext"] }
qcheck = { workspace = true }
qcheck-macros = { workspace = true }
radicle = { workspace = true, features = ["test"] }
+
radicle-log = { workspace = true, features = ["test"] }
radicle-protocol = { workspace = true, features = ["test"] }
radicle-crypto = { workspace = true, features = ["test", "cyphernet"] }
snapbox = { workspace = true }
modified crates/radicle-node/src/main.rs
@@ -404,7 +404,7 @@ fn initialize_logging(options: &LogOptions) -> Result<(), Box<dyn std::error::Er
                const SYSLOG_IDENTIFIER: &str = "radicle-node";
                logger::<&str, &str, _>(SYSLOG_IDENTIFIER.to_string(), []).map_err(Box::new)?
            }
-
            Logger::Radicle => Box::new(radicle::logger::Logger::new()),
+
            Logger::Radicle => Box::new(radicle_log::Logger::new()),
        }
    };

modified crates/radicle-node/src/test.rs
@@ -5,5 +5,5 @@ pub mod peer;
pub mod simulator;

pub use radicle::assert_matches;
-
pub use radicle::logger::test as logger;
pub use radicle::test::*;
+
pub use radicle_log::test as logger;
modified crates/radicle-protocol/Cargo.toml
@@ -22,7 +22,7 @@ fastrand = { workspace = true }
log = { workspace = true, features = ["std"] }
nonempty = { workspace = true, features = ["serialize"] }
qcheck = { workspace = true, optional = true }
-
radicle = { workspace = true, features = ["logger"] }
+
radicle = { workspace = true }
radicle-core = { workspace = true }
radicle-fetch = { workspace = true }
radicle-localtime = { workspace = true }
@@ -36,4 +36,4 @@ pastey = "0.2"
qcheck = { workspace = true }
qcheck-macros = { workspace = true }
radicle = { workspace = true, features = ["test"] }
-
radicle-crypto = { workspace = true, features = ["test", "cyphernet"] }

\ No newline at end of file
+
radicle-crypto = { workspace = true, features = ["test", "cyphernet"] }
modified crates/radicle-remote-helper/Cargo.toml
@@ -18,4 +18,5 @@ dunce = { workspace = true }
log = { workspace = true }
radicle = { workspace = true }
radicle-cli = { workspace = true }
-
thiserror = { workspace = true, default-features = true }

\ No newline at end of file
+
radicle-log = { workspace = true }
+
thiserror = { workspace = true, default-features = true }
modified crates/radicle-remote-helper/src/main.rs
@@ -51,8 +51,8 @@ const VERSION: Version = Version {
fn main() {
    let mut args = env::args();

-
    if let Some(lvl) = radicle::logger::env_level() {
-
        let logger = radicle::logger::StderrLogger::new();
+
    if let Some(lvl) = radicle_log::env_level() {
+
        let logger = radicle_log::StderrLogger::new();
        log::set_boxed_logger(Box::new(logger))
            .expect("no other logger should have been set already");
        log::set_max_level(lvl.to_level_filter());
modified crates/radicle/Cargo.toml
@@ -15,7 +15,6 @@ default = []
gix = ["radicle-oid/gix"]
i2p = ["cyphernet/i2p"]
test = ["tempfile", "qcheck", "radicle-crypto/test", "radicle-cob/test"]
-
logger = ["colored", "chrono"]
qcheck = [
  "radicle-core/qcheck",
  "radicle-oid/qcheck",
@@ -34,8 +33,6 @@ tor = ["cyphernet/tor"]
amplify = { workspace = true, features = ["std"] }
base64 = "0.21.3"
bytesize = { version = "2", features = ["serde"] }
-
chrono = { workspace = true, features = ["clock"], optional = true }
-
colored = { workspace = true, optional = true }
crossbeam-channel = { workspace = true }
cyphernet = { workspace = true, features = ["dns", "p2p-ed25519"] }
dunce = { workspace = true }
modified crates/radicle/src/lib.rs
@@ -17,8 +17,6 @@ pub mod explorer;
pub mod git;
pub mod identity;
pub mod io;
-
#[cfg(feature = "logger")]
-
pub mod logger;
pub mod node;
pub mod profile;
pub mod rad;
deleted crates/radicle/src/logger.rs
@@ -1,104 +0,0 @@
-
//! Logging module.
-
//!
-
//! For test logging see [`mod@test`].
-

-
#[cfg(feature = "test")]
-
pub mod test;
-

-
use std::io;
-
use std::io::Write;
-

-
use chrono::prelude::*;
-
use colored::*;
-
use log::{Level, Log, Metadata, Record};
-

-
/// A logger that logs to `stdout`.
-
pub struct Logger;
-

-
impl Logger {
-
    pub fn new() -> Self {
-
        Self
-
    }
-
}
-

-
impl Default for Logger {
-
    fn default() -> Self {
-
        Self::new()
-
    }
-
}
-

-
impl Log for Logger {
-
    fn enabled(&self, metadata: &Metadata) -> bool {
-
        metadata.level() <= log::max_level()
-
    }
-

-
    fn log(&self, record: &Record) {
-
        if self.enabled(record.metadata()) {
-
            let target = record.target();
-

-
            let message = format!(
-
                "{:<5} {:<8} {}",
-
                record.level(),
-
                target.cyan(),
-
                record.args()
-
            );
-

-
            let message = format!(
-
                "{} {}",
-
                Local::now().to_rfc3339_opts(SecondsFormat::Millis, true),
-
                message,
-
            );
-

-
            let message = match record.level() {
-
                Level::Error => message.red(),
-
                Level::Warn => message.yellow(),
-
                Level::Info => message.normal(),
-
                Level::Debug => message.dimmed(),
-
                Level::Trace => message.white().dimmed(),
-
            };
-
            writeln!(&mut io::stdout(), "{message}").expect("write shouldn't fail");
-
        }
-
    }
-

-
    fn flush(&self) {}
-
}
-

-
/// A logger that logs to `stderr`.
-
pub struct StderrLogger;
-

-
impl StderrLogger {
-
    pub fn new() -> Self {
-
        Self
-
    }
-
}
-

-
impl Default for StderrLogger {
-
    fn default() -> Self {
-
        Self::new()
-
    }
-
}
-

-
impl Log for StderrLogger {
-
    fn enabled(&self, metadata: &Metadata) -> bool {
-
        metadata.level() <= log::max_level()
-
    }
-

-
    fn log(&self, record: &Record) {
-
        let message = format!(
-
            "{:<5} {:<8} {}",
-
            record.level(),
-
            record.target(),
-
            record.args()
-
        );
-
        writeln!(&mut io::stderr(), "{message}").expect("write shouldn't fail");
-
    }
-

-
    fn flush(&self) {}
-
}
-

-
/// Get the level set by the environment variable `RUST_LOG`, if
-
/// present.
-
pub fn env_level() -> Option<Level> {
-
    let level = std::env::var("RUST_LOG").ok()?;
-
    level.parse().ok()
-
}
deleted crates/radicle/src/logger/test.rs
@@ -1,65 +0,0 @@
-
use localtime::LocalTime;
-
use log::*;
-

-
pub struct Logger {
-
    level: Level,
-
}
-

-
impl Logger {
-
    pub fn new(level: Level) -> Self {
-
        Self { level }
-
    }
-
}
-

-
impl Log for Logger {
-
    fn enabled(&self, metadata: &Metadata) -> bool {
-
        metadata.level() <= self.level
-
    }
-

-
    fn log(&self, record: &Record) {
-
        use colored::Colorize;
-
        let time = LocalTime::now().as_secs();
-

-
        match record.target() {
-
            "test" => {
-
                println!(
-
                    "{time} {} {}",
-
                    "test:".cyan(),
-
                    record.args().to_string().cyan()
-
                )
-
            }
-
            "sim" => {
-
                println!(
-
                    "{time} {}  {}",
-
                    "sim:".bold(),
-
                    record.args().to_string().bold()
-
                )
-
            }
-
            target => {
-
                if self.enabled(record.metadata()) {
-
                    let current = std::thread::current();
-
                    let msg = format!("{:>10} {}", format!("{target}:"), record.args());
-
                    let time = LocalTime::now().as_secs();
-
                    let s = if let Some(name) = current.name() {
-
                        format!("{time} {name:<16} {msg}")
-
                    } else {
-
                        format!("{time} {msg}")
-
                    };
-
                    match record.level() {
-
                        log::Level::Warn => {
-
                            println!("{}", s.yellow());
-
                        }
-
                        log::Level::Error => {
-
                            println!("{}", s.red());
-
                        }
-
                        _ => {
-
                            println!("{}", s.dimmed());
-
                        }
-
                    }
-
                }
-
            }
-
        }
-
    }
-

-
    fn flush(&self) {}
-
}