From df71da8b38f6bb21b7741da9e231b56af677e95d Mon Sep 17 00:00:00 2001 From: Artem Shein Date: Wed, 4 Feb 2026 13:22:27 +0100 Subject: [PATCH] score-log integration --- BUILD | 2 - Cargo.lock | 118 +------ Cargo.toml | 5 - MODULE.bazel | 6 + examples/rust/cycle-benchmark/BUILD.bazel | 6 +- examples/rust/cycle-benchmark/Cargo.toml | 2 - examples/rust/cycle-benchmark/src/config.rs | 4 +- examples/rust/mini-adas/BUILD.bazel | 22 +- examples/rust/mini-adas/Cargo.toml | 2 - .../mini-adas/src/activities/components.rs | 13 +- .../rust/mini-adas/src/activities/messages.rs | 15 +- .../mini-adas/src/bin/adas_deserializer.rs | 14 +- .../rust/mini-adas/src/bin/adas_primary.rs | 16 +- .../rust/mini-adas/src/bin/adas_recorder.rs | 11 +- .../rust/mini-adas/src/bin/adas_secondary.rs | 30 +- src/feo-com/BUILD.bazel | 2 +- src/feo-com/Cargo.toml | 1 - src/feo-com/src/interface.rs | 33 +- src/feo-com/src/linux_shm/mod.rs | 52 +-- src/feo-log/BUILD.bazel | 75 ---- src/feo-log/Cargo.toml | 11 - src/feo-log/examples/hello.cc | 71 ---- src/feo-log/examples/hello.rs | 42 --- src/feo-log/include/log.h | 57 --- src/feo-log/src/ffi.rs | 106 ------ src/feo-log/src/lib.rs | 25 -- src/feo-log/src/log.cc | 52 --- src/feo-logger/BUILD.bazel | 70 ---- src/feo-logger/Cargo.toml | 11 - src/feo-logger/README.md | 12 - src/feo-logger/include/logger.h | 28 -- src/feo-logger/src/console.rs | 25 -- src/feo-logger/src/ffi.rs | 28 -- src/feo-logger/src/fmt.rs | 161 --------- src/feo-logger/src/lib.rs | 112 ------ src/feo-logger/src/logd.rs | 102 ------ src/feo-logger/src/logger.cc | 26 -- src/feo-logger/src/record.rs | 334 ------------------ src/feo-logger/src/thread.rs | 21 -- src/feo-time/BUILD.bazel | 14 +- src/feo-time/Cargo.toml | 5 +- src/feo-time/examples/time_speedrun.rs | 43 ++- src/feo-time/src/lib.rs | 141 +++++++- src/feo-tracer/BUILD.bazel | 8 +- src/feo-tracer/Cargo.toml | 3 - src/feo-tracer/src/io.rs | 25 +- src/feo-tracer/src/main.rs | 22 +- src/feo-tracer/src/perfetto.rs | 8 +- src/feo-tracer/src/progress.rs | 5 - src/feo-tracing/BUILD.bazel | 4 +- src/feo-tracing/Cargo.toml | 1 - src/feo-tracing/src/lib.rs | 1 + src/feo-tracing/src/subscriber.rs | 122 ++++++- src/feo/BUILD.bazel | 6 +- src/feo/Cargo.toml | 4 - src/feo/src/agent/direct/primary.rs | 14 +- src/feo/src/agent/direct/primary_mpsc.rs | 10 +- src/feo/src/agent/direct/recorder.rs | 2 +- src/feo/src/agent/direct/secondary.rs | 11 +- src/feo/src/agent/relayed/primary.rs | 4 +- src/feo/src/agent/relayed/recorder.rs | 2 +- src/feo/src/agent/relayed/secondary.rs | 4 +- src/feo/src/debug_fmt.rs | 49 +++ src/feo/src/error.rs | 12 +- src/feo/src/ids.rs | 14 +- src/feo/src/lib.rs | 1 + src/feo/src/recording/recorder.rs | 19 +- src/feo/src/recording/registry.rs | 5 +- src/feo/src/recording/transcoder.rs | 10 +- src/feo/src/scheduler.rs | 51 ++- src/feo/src/signalling/common/interface.rs | 2 +- .../src/signalling/common/mpsc/endpoint.rs | 22 +- .../src/signalling/common/mpsc/primitives.rs | 4 +- src/feo/src/signalling/common/mpsc/worker.rs | 2 +- src/feo/src/signalling/common/signals.rs | 3 +- .../src/signalling/common/socket/client.rs | 22 +- .../signalling/common/socket/connection.rs | 4 +- src/feo/src/signalling/common/socket/mod.rs | 3 +- .../src/signalling/common/socket/server.rs | 15 +- .../src/signalling/direct/mpsc/scheduler.rs | 2 +- src/feo/src/signalling/direct/recorder.rs | 6 +- src/feo/src/signalling/direct/scheduler.rs | 21 +- src/feo/src/signalling/direct/worker.rs | 2 +- .../signalling/relayed/connectors/recorder.rs | 2 +- .../signalling/relayed/connectors/relays.rs | 24 +- .../relayed/connectors/scheduler.rs | 4 +- .../relayed/connectors/secondary.rs | 2 +- src/feo/src/signalling/relayed/interface.rs | 13 +- .../src/signalling/relayed/mpsc/endpoint.rs | 2 +- .../signalling/relayed/sockets/endpoint.rs | 20 +- .../src/signalling/relayed/sockets_mpsc.rs | 2 +- src/feo/src/timestamp.rs | 21 +- src/feo/src/topicspec.rs | 6 +- src/feo/src/worker/mod.rs | 12 +- src/logd/BUILD.bazel | 56 --- src/logd/Cargo.toml | 20 -- src/logd/examples/client_packet.rs | 46 --- src/logd/examples/client_stream.rs | 42 --- src/logd/src/input.rs | 141 -------- src/logd/src/lib.rs | 54 --- src/logd/src/main.rs | 32 -- tests/rust/feo_tests/test_agent/BUILD | 4 +- tests/rust/feo_tests/test_agent/Cargo.toml | 2 - .../feo_tests/test_agent/src/activities.rs | 9 +- tests/rust/feo_tests/test_agent/src/config.rs | 2 +- tests/rust/feo_tests/test_agent/src/main.rs | 11 +- .../rust/feo_tests/test_agent/src/primary.rs | 4 +- .../rust/feo_tests/test_agent/src/scenario.rs | 3 +- .../feo_tests/test_agent/src/secondary.rs | 4 +- 109 files changed, 767 insertions(+), 2222 deletions(-) delete mode 100644 src/feo-log/BUILD.bazel delete mode 100644 src/feo-log/Cargo.toml delete mode 100644 src/feo-log/examples/hello.cc delete mode 100644 src/feo-log/examples/hello.rs delete mode 100644 src/feo-log/include/log.h delete mode 100644 src/feo-log/src/ffi.rs delete mode 100644 src/feo-log/src/lib.rs delete mode 100644 src/feo-log/src/log.cc delete mode 100644 src/feo-logger/BUILD.bazel delete mode 100644 src/feo-logger/Cargo.toml delete mode 100644 src/feo-logger/README.md delete mode 100644 src/feo-logger/include/logger.h delete mode 100644 src/feo-logger/src/console.rs delete mode 100644 src/feo-logger/src/ffi.rs delete mode 100644 src/feo-logger/src/fmt.rs delete mode 100644 src/feo-logger/src/lib.rs delete mode 100644 src/feo-logger/src/logd.rs delete mode 100644 src/feo-logger/src/logger.cc delete mode 100644 src/feo-logger/src/record.rs delete mode 100644 src/feo-logger/src/thread.rs create mode 100644 src/feo/src/debug_fmt.rs delete mode 100644 src/logd/BUILD.bazel delete mode 100644 src/logd/Cargo.toml delete mode 100644 src/logd/examples/client_packet.rs delete mode 100644 src/logd/examples/client_stream.rs delete mode 100644 src/logd/src/input.rs delete mode 100644 src/logd/src/lib.rs delete mode 100644 src/logd/src/main.rs diff --git a/BUILD b/BUILD index 8e7515e..35ba7be 100644 --- a/BUILD +++ b/BUILD @@ -80,9 +80,7 @@ exports_files([ test_suite( name = "unit_tests", tests = [ - "//src/feo-logger:libfeo_logger_rust_test", "//src/feo-time:libfeo_time_cc_test", "//src/feo-time:libfeo_time_test", - "//src/logd:liblogd_test", ], ) diff --git a/Cargo.lock b/Cargo.lock index 6d7bd0e..b645ab2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -105,28 +105,6 @@ dependencies = [ "serde", ] -[[package]] -name = "async-stream" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "atomic-polyfill" version = "1.0.3" @@ -358,8 +336,6 @@ name = "cycle-benchmark" version = "0.1.0" dependencies = [ "feo", - "feo-log", - "feo-logger", "feo-time", "feo-tracing", "postcard", @@ -473,8 +449,6 @@ version = "0.0.1" dependencies = [ "ctrlc", "feo-com", - "feo-log", - "feo-logger", "feo-time", "feo-tracing", "libc 1.0.0-alpha.1", @@ -487,7 +461,6 @@ dependencies = [ name = "feo-com" version = "0.1.0" dependencies = [ - "feo-log", "iceoryx2", "nix", "rand", @@ -504,31 +477,11 @@ dependencies = [ name = "feo-cpp-macros" version = "0.1.0" -[[package]] -name = "feo-log" -version = "0.1.0" -dependencies = [ - "feo-logger", - "log", -] - -[[package]] -name = "feo-logger" -version = "0.1.0" -dependencies = [ - "console", - "feo-log", - "feo-time", - "libc 1.0.0-alpha.1", - "time", -] - [[package]] name = "feo-time" version = "0.1.0" dependencies = [ - "feo-log", - "feo-logger", + "serde", "time", ] @@ -538,13 +491,10 @@ version = "0.1.0" dependencies = [ "anyhow", "argh", - "feo-log", - "feo-logger", "feo-tracing", "futures", "human_bytes", "indicatif", - "indicatif-log-bridge", "perfetto-model", "postcard", "prost", @@ -556,7 +506,6 @@ dependencies = [ name = "feo-tracing" version = "0.1.0" dependencies = [ - "feo-log", "libc 1.0.0-alpha.1", "postcard", "serde", @@ -564,15 +513,6 @@ dependencies = [ "tracing-subscriber", ] -[[package]] -name = "filedesc" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4960c866d9cf4c48f64f11ef0020c98900d0cb32e9b019c000ed838470daa1d" -dependencies = [ - "libc 0.2.177", -] - [[package]] name = "find-msvc-tools" version = "0.1.4" @@ -955,16 +895,6 @@ dependencies = [ "web-time", ] -[[package]] -name = "indicatif-log-bridge" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63703cf9069b85dbe6fe26e1c5230d013dee99d3559cd3d02ba39e099ef7ab02" -dependencies = [ - "indicatif", - "log", -] - [[package]] name = "integration_test" version = "0.1.0" @@ -1120,24 +1050,6 @@ version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" -[[package]] -name = "logd" -version = "0.1.0" -dependencies = [ - "anyhow", - "async-stream", - "bytes", - "env_logger", - "feo-log", - "feo-logger", - "feo-time", - "futures", - "socket2", - "tokio", - "tokio-seqpacket", - "tokio-util", -] - [[package]] name = "memchr" version = "2.7.6" @@ -1152,8 +1064,6 @@ dependencies = [ "feo-com", "feo-cpp-build", "feo-cpp-macros", - "feo-log", - "feo-logger", "feo-time", "feo-tracing", "postcard", @@ -1733,8 +1643,6 @@ dependencies = [ "feo", "feo-com", "feo-cpp-macros", - "feo-log", - "feo-logger", "feo-time", "feo-tracing", "ipc-channel", @@ -1826,30 +1734,6 @@ dependencies = [ "syn", ] -[[package]] -name = "tokio-seqpacket" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eb09d9a154bede1fafb3a9b13f4347de87e1ec07fa6fb42f52041800f18fe06" -dependencies = [ - "filedesc", - "libc 0.2.177", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - [[package]] name = "toml" version = "0.8.23" diff --git a/Cargo.toml b/Cargo.toml index cad3808..9ffb1b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,12 +6,9 @@ members = [ "feo-com", "feo-cpp-build", "feo-cpp-macros", - "feo-log", - "feo-logger", "feo-time", "feo-tracer", "feo-tracing", - "logd", "perfetto-model", "tests/rust/feo_tests/test_agent", "tests/rust/feo_tests", @@ -35,8 +32,6 @@ feo = { path = "feo", default-features = false } feo-com = { path = "feo-com" } feo-cpp-build = { path = "feo-cpp-build" } feo-cpp-macros = { path = "feo-cpp-macros" } -feo-log = { path = "feo-log" } -feo-logger = { path = "feo-logger" } feo-time = { path = "feo-time" } feo-tracing = { path = "feo-tracing" } ctrlc = { version = "3.4.4", features = ["termination"] } diff --git a/MODULE.bazel b/MODULE.bazel index 652dc26..7aed7aa 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -22,6 +22,12 @@ bazel_dep(name = "score_bazel_platforms", version = "0.0.4") # SCORE bazel module dependencies bazel_dep(name = "score_tooling", version = "1.1.0") bazel_dep(name = "score_crates", version = "0.0.6") +bazel_dep(name = "score_baselibs_rust", version = "0.1.0") +git_override( + module_name = "score_baselibs_rust", + commit = "1b9f2786cd746ae9745dd2e81bf9073b4185a5e2", + remote = "https://github.com/eclipse-score/baselibs_rust.git", +) # Rust rules for Bazel bazel_dep(name = "rules_rust", version = "0.67.0") diff --git a/examples/rust/cycle-benchmark/BUILD.bazel b/examples/rust/cycle-benchmark/BUILD.bazel index 5a72843..5e1bae2 100644 --- a/examples/rust/cycle-benchmark/BUILD.bazel +++ b/examples/rust/cycle-benchmark/BUILD.bazel @@ -31,10 +31,9 @@ rust_library( deps = [ "//src/feo:libfeo_recording_rust", "//src/feo-com:libfeo_com_rust", - "//src/feo-log:libfeo_log_rust", - "//src/feo-logger:libfeo_logger_rust", "//src/feo-time:libfeo_time_rust", "//src/feo-tracing:libfeo_tracing_rust", + "@score_baselibs_rust//src/log/score_log", "@score_crates//:postcard", "@score_crates//:serde", "@score_crates//:serde_json", @@ -56,9 +55,8 @@ rust_binary( deps = [ ":libcycle_benchmark_rust", "//src/feo:libfeo_recording_rust", - "//src/feo-log:libfeo_log_rust", - "//src/feo-logger:libfeo_logger_rust", "//src/feo-time:libfeo_time_rust", "//src/feo-tracing:libfeo_tracing_rust", + "@score_baselibs_rust//src/log/score_log", ], ) diff --git a/examples/rust/cycle-benchmark/Cargo.toml b/examples/rust/cycle-benchmark/Cargo.toml index b6df939..e640476 100644 --- a/examples/rust/cycle-benchmark/Cargo.toml +++ b/examples/rust/cycle-benchmark/Cargo.toml @@ -10,8 +10,6 @@ required-features = [] [dependencies] feo = { workspace = true } -feo-log = { workspace = true } -feo-logger = { workspace = true } feo-time = { workspace = true } feo-tracing = { workspace = true } tracing = { workspace = true } diff --git a/examples/rust/cycle-benchmark/src/config.rs b/examples/rust/cycle-benchmark/src/config.rs index 2eb4cf4..18c91df 100644 --- a/examples/rust/cycle-benchmark/src/config.rs +++ b/examples/rust/cycle-benchmark/src/config.rs @@ -16,7 +16,7 @@ use crate::composites::{composite_builder, find_composites}; use core::net::{IpAddr, Ipv4Addr, SocketAddr}; use feo::activity::ActivityIdAndBuilder; use feo::ids::{ActivityId, AgentId, WorkerId}; -use feo_log::info; +use score_log::info; use serde::Deserialize; use serde_json; use std::collections::{HashMap, HashSet}; @@ -252,7 +252,7 @@ fn application_config() -> ApplicationConfig { .join(CONFIG_PATH) .canonicalize() .unwrap(); - info!("Reading configuration from {}", config_file.display()); + info!("Reading configuration from {}", format!("{config_file:?}")); let file = File::open(config_file).unwrap_or_else(|e| panic!("failed to open config file: {e}")); let reader = BufReader::new(file); diff --git a/examples/rust/mini-adas/BUILD.bazel b/examples/rust/mini-adas/BUILD.bazel index dab8742..ecfd3ae 100644 --- a/examples/rust/mini-adas/BUILD.bazel +++ b/examples/rust/mini-adas/BUILD.bazel @@ -37,10 +37,9 @@ rust_library( "//src/feo:libfeo_rust", "//src/feo-com:libfeo_com_rust", "//src/feo-cpp-build:libfeo_cpp_build_rust", - "//src/feo-log:libfeo_log_rust", - "//src/feo-logger:libfeo_logger_rust", "//src/feo-time:libfeo_time_rust", "//src/feo-tracing:libfeo_tracing_rust", + "@score_baselibs_rust//src/log/score_log", "@score_crates//:tracing", ], ) @@ -70,10 +69,9 @@ rust_library( "//src/feo:libfeo_recording_rust", "//src/feo-com:libfeo_com_rust", "//src/feo-cpp-build:libfeo_cpp_build_rust", - "//src/feo-log:libfeo_log_rust", - "//src/feo-logger:libfeo_logger_rust", "//src/feo-time:libfeo_time_rust", "//src/feo-tracing:libfeo_tracing_rust", + "@score_baselibs_rust//src/log/score_log", "@score_crates//:postcard", "@score_crates//:serde", "@score_crates//:tracing", @@ -95,10 +93,10 @@ rust_binary( deps = [ ":libmini_adas_rust", "//src/feo:libfeo_rust", - "//src/feo-log:libfeo_log_rust", - "//src/feo-logger:libfeo_logger_rust", "//src/feo-time:libfeo_time_rust", "//src/feo-tracing:libfeo_tracing_rust", + "@score_baselibs_rust//src/log/score_log", + "@score_baselibs_rust//src/log/stdout_logger", ], ) @@ -117,10 +115,10 @@ rust_binary( deps = [ ":libmini_adas_rust", "//src/feo:libfeo_rust", - "//src/feo-log:libfeo_log_rust", - "//src/feo-logger:libfeo_logger_rust", "//src/feo-time:libfeo_time_rust", "//src/feo-tracing:libfeo_tracing_rust", + "@score_baselibs_rust//src/log/score_log", + "@score_baselibs_rust//src/log/stdout_logger", ], ) @@ -137,10 +135,10 @@ rust_binary( deps = [ ":libmini_adas_recording_rust", "//src/feo:libfeo_recording_rust", - "//src/feo-log:libfeo_log_rust", - "//src/feo-logger:libfeo_logger_rust", "//src/feo-time:libfeo_time_rust", "//src/feo-tracing:libfeo_tracing_rust", + "@score_baselibs_rust//src/log/score_log", + "@score_baselibs_rust//src/log/stdout_logger", ], ) @@ -154,9 +152,9 @@ rust_binary( deps = [ ":libmini_adas_recording_rust", "//src/feo:libfeo_recording_rust", - "//src/feo-log:libfeo_log_rust", - "//src/feo-logger:libfeo_logger_rust", "//src/feo-tracing:libfeo_tracing_rust", + "@score_baselibs_rust//src/log/score_log", + "@score_baselibs_rust//src/log/stdout_logger", "@score_crates//:postcard", "@score_crates//:serde", ], diff --git a/examples/rust/mini-adas/Cargo.toml b/examples/rust/mini-adas/Cargo.toml index ca69e8c..1fffed0 100644 --- a/examples/rust/mini-adas/Cargo.toml +++ b/examples/rust/mini-adas/Cargo.toml @@ -16,8 +16,6 @@ required-features = ["recording"] [dependencies] feo = { workspace = true } feo-com = { workspace = true } -feo-log = { workspace = true } -feo-logger = { workspace = true } feo-cpp-macros = { workspace = true } feo-time = { workspace = true } feo-tracing = { workspace = true } diff --git a/examples/rust/mini-adas/src/activities/components.rs b/examples/rust/mini-adas/src/activities/components.rs index e500e98..175d378 100644 --- a/examples/rust/mini-adas/src/activities/components.rs +++ b/examples/rust/mini-adas/src/activities/components.rs @@ -25,8 +25,9 @@ use feo_com::interface::{ActivityInput, ActivityOutput}; use feo_com::iox2::{Iox2Input, Iox2Output}; #[cfg(feature = "com_linux_shm")] use feo_com::linux_shm::{LinuxShmInput, LinuxShmOutput}; -use feo_log::debug; use feo_tracing::instrument; +use score_log::debug; +use score_log::fmt::ScoreDebug; use std::hash::RandomState; use std::thread; const SLEEP_RANGE: Range = 10..45; @@ -93,7 +94,7 @@ impl Activity for Camera { if let Ok(camera) = self.output_image.write_uninit() { let image = self.get_image(); - debug!("Sending image: {image:?}"); + debug!("Sending image: {:?}", image); let camera = camera.write_payload(image); camera.send().unwrap(); } @@ -162,7 +163,7 @@ impl Activity for Radar { if let Ok(radar) = self.output_scan.write_uninit() { let scan = self.get_scan(); - debug!("Sending scan: {scan:?}"); + debug!("Sending scan: {}", scan); let radar = radar.write_payload(scan); radar.send().unwrap(); } @@ -254,7 +255,7 @@ impl Activity for NeuralNet { Self::infer(camera.deref(), radar.deref(), scene.deref_mut()); // Safety: `Scene` has `repr(C)` and was fully initialized by `Self::infer` above. let scene = unsafe { scene.assume_init() }; - debug!("Sending Scene {:?}", scene.deref()); + debug!("Sending Scene {}", scene.deref()); scene.send().unwrap(); } Ok(()) @@ -502,7 +503,7 @@ impl Activity for SteeringController { /// Create an activity input. fn activity_input(topic: &str) -> Box> where - T: fmt::Debug + 'static, + T: fmt::Debug + ScoreDebug + 'static, { #[cfg(feature = "com_iox2")] return Box::new(Iox2Input::new(topic)); @@ -513,7 +514,7 @@ where /// Create an activity output. fn activity_output(topic: &str) -> Box> where - T: fmt::Debug + 'static, + T: fmt::Debug + ScoreDebug + 'static, { #[cfg(feature = "com_iox2")] return Box::new(Iox2Output::new(topic)); diff --git a/examples/rust/mini-adas/src/activities/messages.rs b/examples/rust/mini-adas/src/activities/messages.rs index 76e4752..d96d848 100644 --- a/examples/rust/mini-adas/src/activities/messages.rs +++ b/examples/rust/mini-adas/src/activities/messages.rs @@ -21,6 +21,9 @@ use feo::{recording::registry::TypeRegistry, register_type, register_types}; #[cfg(feature = "recording")] use postcard::experimental::max_size::MaxSize; #[cfg(feature = "recording")] +use score_log::fmt::ScoreDebug; +use score_log::ScoreDebug; +#[cfg(feature = "recording")] use serde::{Deserialize, Serialize}; /// Camera image @@ -30,7 +33,7 @@ use serde::{Deserialize, Serialize}; /// Given that we do not have a real neural network, /// we already include information to be dummy inferred. #[cfg_attr(feature = "recording", derive(Serialize, Deserialize, MaxSize))] -#[derive(Debug, Default)] +#[derive(Debug, Default, ScoreDebug)] #[repr(C)] pub struct CameraImage { pub num_people: usize, @@ -44,7 +47,7 @@ pub struct CameraImage { /// from a real radar scan. In this example, /// the message type already carries the information to be dummy extracted. #[cfg_attr(feature = "recording", derive(Serialize, Deserialize, MaxSize))] -#[derive(Debug, Default)] +#[derive(Debug, Default, ScoreDebug)] #[repr(C)] pub struct RadarScan { pub distance_obstacle: f64, @@ -56,7 +59,7 @@ pub struct RadarScan { /// The scene is the result of fusing the camera image and the radar scan /// with a neural network. In our example, we just extract the information. #[cfg_attr(feature = "recording", derive(Serialize, Deserialize, MaxSize))] -#[derive(Debug, Default)] +#[derive(Debug, Default, ScoreDebug)] #[repr(C)] pub struct Scene { pub num_people: usize, @@ -70,7 +73,7 @@ pub struct Scene { /// /// This is an instruction whether to engage the brakes and at which level. #[cfg_attr(feature = "recording", derive(Serialize, Deserialize, MaxSize))] -#[derive(Debug, Default)] +#[derive(Debug, Default, ScoreDebug)] #[repr(C)] pub struct BrakeInstruction { pub active: bool, @@ -81,7 +84,7 @@ pub struct BrakeInstruction { /// /// This carries the angle of steering. #[cfg_attr(feature = "recording", derive(Serialize, Deserialize, MaxSize))] -#[derive(Debug, Default)] +#[derive(Debug, Default, ScoreDebug)] #[repr(C)] pub struct Steering { pub angle: f64, @@ -101,7 +104,7 @@ pub fn type_registry() -> TypeRegistry { fn activity_input(topic: &str) -> Box> where - T: fmt::Debug + 'static, + T: fmt::Debug + ScoreDebug + 'static, { #[cfg(feature = "com_iox2")] return Box::new(Iox2Input::new(topic)); diff --git a/examples/rust/mini-adas/src/bin/adas_deserializer.rs b/examples/rust/mini-adas/src/bin/adas_deserializer.rs index 8f91f39..17e5c8a 100644 --- a/examples/rust/mini-adas/src/bin/adas_deserializer.rs +++ b/examples/rust/mini-adas/src/bin/adas_deserializer.rs @@ -12,13 +12,20 @@ ********************************************************************************/ use feo::recording::recorder::{DataDescriptionRecord, Record}; -use feo_log::info; use mini_adas::activities::messages; +use score_log::{info, LevelFilter}; use serde::Deserialize; use std::io::Read; +use stdout_logger::StdoutLoggerBuilder; fn main() { - feo_logger::init(feo_log::LevelFilter::Trace, true, false); + StdoutLoggerBuilder::new() + .context("adas-deserializer") + .show_module(true) + .show_file(true) + .show_line(true) + .log_level(LevelFilter::Trace) + .set_as_default_logger(); let mut serialized_data = Vec::new(); std::fs::File::open("rec.bin") @@ -27,7 +34,8 @@ fn main() { .read_to_end(&mut serialized_data) .expect("failed to read recording"); - info!("Read file with {} bytes", serialized_data.len()); + let serialized_data_len = serialized_data.len(); + info!("Read file with {} bytes", serialized_data_len); let mut remaining_bytes = serialized_data.as_slice(); while !remaining_bytes.is_empty() { let (record, remaining) = postcard::take_from_bytes(remaining_bytes).expect("deserializing failed"); diff --git a/examples/rust/mini-adas/src/bin/adas_primary.rs b/examples/rust/mini-adas/src/bin/adas_primary.rs index d3498cc..3eef811 100644 --- a/examples/rust/mini-adas/src/bin/adas_primary.rs +++ b/examples/rust/mini-adas/src/bin/adas_primary.rs @@ -13,21 +13,27 @@ use feo::agent::com_init::initialize_com_primary; use feo::ids::AgentId; -use feo_log::{info, LevelFilter}; use feo_time::Duration; use mini_adas::config::{agent_assignments_ids, topic_dependencies, COM_BACKEND, MAX_ADDITIONAL_SUBSCRIBERS}; +use score_log::{error, info, LevelFilter}; use std::collections::HashSet; +use stdout_logger::StdoutLoggerBuilder; const AGENT_ID: AgentId = AgentId::new(100); const DEFAULT_FEO_CYCLE_TIME: Duration = Duration::from_secs(5); fn main() { - feo_logger::init(LevelFilter::Debug, true, true); - feo_tracing::init(feo_tracing::LevelFilter::TRACE); + StdoutLoggerBuilder::new() + .context("adas-primary") + .show_module(false) + .show_file(false) + .show_line(false) + .log_level(LevelFilter::Trace) + .set_as_default_logger(); let params = Params::from_args(); - info!("Starting primary agent {AGENT_ID}"); + info!("Starting primary agent {}", AGENT_ID); let config = cfg::make_config(params); @@ -43,7 +49,7 @@ fn main() { // Setup and run primary cfg::Primary::new(config) .unwrap_or_else(|err| { - feo_log::error!("Failed to initialize primary agent: {err:?}"); + error!("Failed to initialize primary agent: {:?}", err); std::process::exit(1); }) .run() diff --git a/examples/rust/mini-adas/src/bin/adas_recorder.rs b/examples/rust/mini-adas/src/bin/adas_recorder.rs index 0c72975..8cc6cc0 100644 --- a/examples/rust/mini-adas/src/bin/adas_recorder.rs +++ b/examples/rust/mini-adas/src/bin/adas_recorder.rs @@ -13,8 +13,8 @@ use feo::ids::AgentId; use feo::recording::recorder::RecordingRules; -use feo_log::{debug, LevelFilter}; use mini_adas::activities::messages::{self, BrakeInstruction, CameraImage, RadarScan, Scene, Steering}; +use score_log::{debug, LevelFilter}; use feo::agent::com_init::initialize_com_recorder; use feo::topicspec::TopicSpecification; @@ -23,9 +23,16 @@ use mini_adas::config::{ TOPIC_INFERRED_SCENE, TOPIC_RADAR_FRONT, }; use std::collections::HashMap; +use stdout_logger::StdoutLoggerBuilder; fn main() { - feo_logger::init(LevelFilter::Trace, true, true); + StdoutLoggerBuilder::new() + .context("adas-recorder") + .show_module(true) + .show_file(true) + .show_line(true) + .log_level(LevelFilter::Trace) + .set_as_default_logger(); let params = Params::from_args(); diff --git a/examples/rust/mini-adas/src/bin/adas_secondary.rs b/examples/rust/mini-adas/src/bin/adas_secondary.rs index ad0339c..e5cf324 100644 --- a/examples/rust/mini-adas/src/bin/adas_secondary.rs +++ b/examples/rust/mini-adas/src/bin/adas_secondary.rs @@ -11,14 +11,16 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +use score_log::{info, LevelFilter}; +use stdout_logger::StdoutLoggerBuilder; + #[cfg(any(feature = "signalling_direct_tcp", feature = "signalling_direct_unix"))] fn main() { - use core::time::Duration; use feo::agent::com_init::initialize_com_secondary; use feo::agent::direct::secondary::{Secondary, SecondaryConfig}; use feo::agent::NodeAddress; use feo::ids::ActivityId; - use feo_log::{info, LevelFilter}; + use feo_time::Duration; #[cfg(feature = "signalling_direct_unix")] use mini_adas::config::socket_paths; #[cfg(feature = "signalling_direct_tcp")] @@ -28,7 +30,8 @@ fn main() { use params::Params; use std::collections::HashSet; - feo_logger::init(LevelFilter::Debug, true, true); + init_logging(); + feo_tracing::init(feo_tracing::LevelFilter::TRACE); let params = Params::from_args(); @@ -62,19 +65,19 @@ fn main() { #[cfg(feature = "signalling_relayed_tcp")] fn main() { - use core::time::Duration; use feo::agent::com_init::initialize_com_secondary; use feo::agent::relayed::secondary::{Secondary, SecondaryConfig}; use feo::agent::NodeAddress; use feo::ids::ActivityId; - use feo_log::{info, LevelFilter}; + use feo_time::Duration; use mini_adas::config::{agent_assignments, topic_dependencies}; use mini_adas::config::{agent_assignments_ids, COM_BACKEND}; use mini_adas::config::{BIND_ADDR, BIND_ADDR2}; use params::Params; use std::collections::HashSet; - feo_logger::init(LevelFilter::Debug, true, true); + init_logging(); + feo_tracing::init(feo_tracing::LevelFilter::TRACE); let params = Params::from_args(); @@ -106,19 +109,18 @@ fn main() { #[cfg(feature = "signalling_relayed_unix")] fn main() { - use core::time::Duration; use feo::agent::com_init::initialize_com_secondary; use feo::agent::relayed::secondary::{Secondary, SecondaryConfig}; use feo::agent::NodeAddress; use feo::ids::ActivityId; - use feo_log::{info, LevelFilter}; + use feo_time::Duration; use mini_adas::config::socket_paths; use mini_adas::config::{agent_assignments, topic_dependencies}; use mini_adas::config::{agent_assignments_ids, COM_BACKEND}; use params::Params; use std::collections::HashSet; - feo_logger::init(LevelFilter::Debug, true, true); + init_logging(); feo_tracing::init(feo_tracing::LevelFilter::TRACE); let params = Params::from_args(); @@ -186,3 +188,13 @@ mod params { } } } + +fn init_logging() { + StdoutLoggerBuilder::new() + .context("adas-secondary") + .show_module(false) + .show_file(false) + .show_line(false) + .log_level(LevelFilter::Trace) + .set_as_default_logger(); +} diff --git a/src/feo-com/BUILD.bazel b/src/feo-com/BUILD.bazel index cee6959..729dca0 100644 --- a/src/feo-com/BUILD.bazel +++ b/src/feo-com/BUILD.bazel @@ -33,12 +33,12 @@ rust_library( crate_name = "feo_com", visibility = ["//visibility:public"], deps = [ - "//src/feo-log:libfeo_log_rust", # all_crate_deps only contains optional dependencies which are default-activated, # so we add all optional dependencies here to be independent of cargo default features # Disabled due to compilation error of iceoryx2 # "@score_crates//:iceoryx2", "@score_crates//:nix", "@score_crates//:rand", + "@score_baselibs_rust//src/log/score_log", ], ) diff --git a/src/feo-com/Cargo.toml b/src/feo-com/Cargo.toml index e9b3bce..d6e27bb 100644 --- a/src/feo-com/Cargo.toml +++ b/src/feo-com/Cargo.toml @@ -4,7 +4,6 @@ version = "0.1.0" edition = "2024" [dependencies] -feo-log = { workspace = true } iceoryx2 = { workspace = true, optional = true } nix = { workspace = true, optional = true } rand = { workspace = true, optional = true } diff --git a/src/feo-com/src/interface.rs b/src/feo-com/src/interface.rs index 5f23107..595bca1 100644 --- a/src/feo-com/src/interface.rs +++ b/src/feo-com/src/interface.rs @@ -39,6 +39,7 @@ use core::any::Any; use core::fmt; use core::mem::MaybeUninit; use core::ops::{Deref, DerefMut}; +use score_log::fmt::ScoreDebug; pub type Topic<'a> = &'a str; @@ -61,7 +62,7 @@ pub enum Error { /// A trait for structs which can provide handles to input buffers pub trait ActivityInput: fmt::Debug where - T: fmt::Debug, + T: fmt::Debug + ScoreDebug, { /// Get a handle to an input buffer fn read(&self) -> Result, Error>; @@ -74,7 +75,7 @@ where /// It is an enum so that it has a size known at compile-time. pub enum InputGuard where - T: fmt::Debug, + T: fmt::Debug + ScoreDebug, { #[cfg(feature = "ipc_iceoryx2")] Iox2(Iox2InputGuard), @@ -84,7 +85,7 @@ where impl Deref for InputGuard where - T: fmt::Debug, + T: fmt::Debug + ScoreDebug, { type Target = T; @@ -101,7 +102,7 @@ where /// A trait for structs which can provide handles to uninitialized output buffers pub trait ActivityOutput: fmt::Debug where - T: fmt::Debug, + T: fmt::Debug + ScoreDebug, { /// Get a handle to an uninitialized output buffer fn write_uninit(&mut self) -> Result, Error>; @@ -110,7 +111,7 @@ where /// A trait for structs which can provide handles to default-initialized output buffers pub trait ActivityOutputDefault: fmt::Debug where - T: fmt::Debug + Default, + T: fmt::Debug + ScoreDebug + Default, { /// Get a handle to a default initialized output buffer fn write_init(&mut self) -> Result, Error>; @@ -137,7 +138,7 @@ where /// For the buffer to be receivable as input, it has to be [Self::send], /// consuming the handle. #[must_use = "buffer has to be sent to be observable"] -pub enum OutputGuard { +pub enum OutputGuard { #[cfg(feature = "ipc_iceoryx2")] Iox2(Iox2OutputGuard), #[cfg(feature = "ipc_linux_shm")] @@ -146,7 +147,7 @@ pub enum OutputGuard { impl OutputGuard where - T: fmt::Debug, + T: fmt::Debug + ScoreDebug, { /// Send this buffer pub fn send(self) -> Result<(), Error> { @@ -161,7 +162,7 @@ where impl Deref for OutputGuard where - T: fmt::Debug, + T: fmt::Debug + ScoreDebug, { type Target = T; @@ -177,7 +178,7 @@ where impl DerefMut for OutputGuard where - T: fmt::Debug + Default, + T: fmt::Debug + ScoreDebug + Default, { fn deref_mut(&mut self) -> &mut Self::Target { match self { @@ -205,7 +206,7 @@ where /// - Writing directly to the uninitialized memory and call [Self::assume_init]. /// This is `unsafe` and the caller has to ensure that the buffer is initialized /// to a valid value before calling [Self::assume_init]. -pub enum OutputUninitGuard { +pub enum OutputUninitGuard { #[cfg(feature = "ipc_iceoryx2")] Iox2(Iox2OutputUninitGuard), #[cfg(feature = "ipc_linux_shm")] @@ -214,7 +215,7 @@ pub enum OutputUninitGuard { impl OutputUninitGuard where - T: fmt::Debug, + T: fmt::Debug + ScoreDebug, { /// Assume the backing buffer is initialized /// @@ -244,7 +245,7 @@ where impl OutputUninitGuard where - T: fmt::Debug + Default, + T: fmt::Debug + ScoreDebug + Default, { /// Initialize the uninitialized buffer with its [Default] trait pub fn init(self) -> OutputGuard { @@ -259,7 +260,7 @@ where impl Deref for OutputUninitGuard where - T: fmt::Debug, + T: fmt::Debug + ScoreDebug, { type Target = MaybeUninit; @@ -275,7 +276,7 @@ where impl DerefMut for OutputUninitGuard where - T: fmt::Debug, + T: fmt::Debug + ScoreDebug, { fn deref_mut(&mut self) -> &mut Self::Target { match self { @@ -337,7 +338,7 @@ impl<'a> ComBackendTopicSecondaryInitialization<'a> { } } -pub fn init_topic_primary( +pub fn init_topic_primary( params: &ComBackendTopicPrimaryInitialization, ) -> TopicHandle { match params.backend { @@ -362,7 +363,7 @@ pub fn init_topic_primary( } } -pub fn init_topic_secondary( +pub fn init_topic_secondary( params: &ComBackendTopicSecondaryInitialization, ) -> TopicHandle { match params.backend { diff --git a/src/feo-com/src/linux_shm/mod.rs b/src/feo-com/src/linux_shm/mod.rs index a8e28e9..a4b3767 100644 --- a/src/feo-com/src/linux_shm/mod.rs +++ b/src/feo-com/src/linux_shm/mod.rs @@ -51,11 +51,12 @@ use core::mem::{size_of, MaybeUninit}; use core::ops::{Deref, DerefMut}; use core::slice::from_raw_parts; use core::sync::atomic::Ordering; -use feo_log::{debug, error, info}; use nix::fcntl::OFlag; use nix::sys::mman::{mmap, shm_open, MapFlags, ProtFlags}; use nix::sys::stat::Mode; use nix::unistd; +use score_log::fmt::ScoreDebug; +use score_log::{debug, error, info}; use std::collections::HashMap; use std::io::{read_to_string, Write}; use std::net::Shutdown; @@ -120,7 +121,7 @@ impl ComRuntime { fn service_main(mut requests_to_serve: usize) { let _ = std::fs::remove_file(SOCKET); let listener = UnixListener::bind(SOCKET).unwrap_or_else(|e| panic!("can't bind socket at {SOCKET}: {e}")); - debug!("Listening for {requests_to_serve} topic mapping requests..."); + debug!("Listening for {} topic mapping requests...", requests_to_serve); loop { if requests_to_serve < 1 { break; @@ -132,7 +133,8 @@ impl ComRuntime { } }, Err(e) => { - error!("socket connection failed: {e}"); + // Allocates, but only used during init + error!("socket connection failed: {}", format!("{e:?}")); }, } } @@ -150,12 +152,16 @@ impl ComRuntime { Some(mapping) => { match stream.write_all(format!("ok\n{}\n{}", mapping.ptr.size, &mapping.mapping_id).as_bytes()) { Ok(_) => result = true, - Err(e) => error!("socket write failed: {e}"), + Err(e) => { + // Allocates, but only used during init + error!("socket write failed: {}", format!("{e:?}")) + }, } }, None => { if let Err(e) = stream.write_all(b"error\ntopic not found") { - error!("socket write failed: {e}"); + // Allocates, but only used during init + error!("socket write failed: {}", format!("{e:?}")); } }, } @@ -198,7 +204,7 @@ impl ComRuntime { also_map: bool, ) { let size = size_of::(); - info!("Initializing topic {topic} (LinuxShm, {size} bytes)..."); + info!("Initializing topic {} (LinuxShm, {} bytes)...", topic, size); let mapping_id = Self::unique_mapping_id(); let native_mapping = shm_open( mapping_id.as_str(), @@ -293,7 +299,7 @@ impl ComRuntime { } // Initialize the topic and register it in the global COM runtime -pub fn init_topic( +pub fn init_topic( topic: Topic, mapping_mode: MappingMode, agent_role: TopicInitializationAgentRole, @@ -302,9 +308,9 @@ pub fn init_topic( TopicHandle::from(Box::new(())) } -pub struct LinuxShmInputGuard(MappedPtrReadGuard); +pub struct LinuxShmInputGuard(MappedPtrReadGuard); -impl Deref for LinuxShmInputGuard { +impl Deref for LinuxShmInputGuard { type Target = T; fn deref(&self) -> &Self::Target { @@ -312,13 +318,13 @@ impl Deref for LinuxShmInputGuard { } } -pub struct LinuxShmOutputGuard { +pub struct LinuxShmOutputGuard { ptr: MappedPtrWriteGuard, } impl LinuxShmOutputGuard where - T: Debug, + T: Debug + ScoreDebug, { pub(crate) fn send(self) -> Result<(), Error> { self.ptr.send(); @@ -326,7 +332,7 @@ where } } -impl Deref for LinuxShmOutputGuard { +impl Deref for LinuxShmOutputGuard { type Target = T; fn deref(&self) -> &Self::Target { @@ -334,17 +340,17 @@ impl Deref for LinuxShmOutputGuard { } } -impl DerefMut for LinuxShmOutputGuard { +impl DerefMut for LinuxShmOutputGuard { fn deref_mut(&mut self) -> &mut Self::Target { DerefMut::deref_mut(&mut self.ptr) } } -pub struct LinuxShmOutputUninitGuard(MappedPtrWriteGuard); +pub struct LinuxShmOutputUninitGuard(MappedPtrWriteGuard); impl LinuxShmOutputUninitGuard where - T: Debug, + T: Debug + ScoreDebug, { // Value is initialized when allocated pub(crate) fn assume_init(self) -> LinuxShmOutputGuard { @@ -360,7 +366,7 @@ where impl LinuxShmOutputUninitGuard where - T: Debug + Default, + T: Debug + ScoreDebug + Default, { // Overwrites with [Default::default] pub(crate) fn init(mut self) -> LinuxShmOutputGuard { @@ -369,7 +375,7 @@ where } } -impl Deref for LinuxShmOutputUninitGuard { +impl Deref for LinuxShmOutputUninitGuard { type Target = MaybeUninit; fn deref(&self) -> &Self::Target { @@ -379,7 +385,7 @@ impl Deref for LinuxShmOutputUninitGuard { } } -impl DerefMut for LinuxShmOutputUninitGuard { +impl DerefMut for LinuxShmOutputUninitGuard { fn deref_mut(&mut self) -> &mut Self::Target { // Safety: MaybeUninit is guaranteed to have the same size, alignment, and ABI as T (according to Rust docs) // T is guarantied to be initialized @@ -393,7 +399,7 @@ pub struct LinuxShmInput { _type: PhantomData, } -impl LinuxShmInput { +impl LinuxShmInput { pub fn new(topic: Topic) -> Self { Self { ptr: ComRuntime::global_runtime().topic_mapping::(topic, MappingMode::Read), @@ -404,7 +410,7 @@ impl LinuxShmInput { impl ActivityInput for LinuxShmInput where - T: Debug + 'static, + T: Debug + ScoreDebug + 'static, { fn read(&self) -> Result, Error> { Ok(InputGuard::LinuxShm(LinuxShmInputGuard(self.ptr.get()))) @@ -417,7 +423,7 @@ pub struct LinuxShmOutput { _type: PhantomData, } -impl LinuxShmOutput { +impl LinuxShmOutput { pub fn new(topic: Topic) -> Self { Self { ptr: ComRuntime::global_runtime().topic_mapping::(topic, MappingMode::Write), @@ -428,7 +434,7 @@ impl LinuxShmOutput { impl ActivityOutput for LinuxShmOutput where - T: Debug + 'static, + T: Debug + ScoreDebug + 'static, { // Initialized when allocated fn write_uninit(&mut self) -> Result, Error> { @@ -440,7 +446,7 @@ where impl ActivityOutputDefault for LinuxShmOutput where - T: Debug + Default + 'static, + T: Debug + ScoreDebug + Default + 'static, { // Overwrites with [Default::default] fn write_init(&mut self) -> Result, Error> { diff --git a/src/feo-log/BUILD.bazel b/src/feo-log/BUILD.bazel deleted file mode 100644 index 5d96a4f..0000000 --- a/src/feo-log/BUILD.bazel +++ /dev/null @@ -1,75 +0,0 @@ -# ******************************************************************************* -# Copyright (c) 2025 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License Version 2.0 which is available at -# https://www.apache.org/licenses/LICENSE-2.0 -# -# SPDX-License-Identifier: Apache-2.0 -# ******************************************************************************* - -load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") -load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library", "rust_static_library") - -rust_library( - name = "libfeo_log_rust", - srcs = [ - "src/lib.rs", - ], - crate_name = "feo_log", - visibility = ["//visibility:public"], - deps = [ - "@score_crates//:log", - ], -) - -# FFI wrapper -rust_static_library( - name = "libfeo_log_ffi_rust", - srcs = [ - "src/ffi.rs", - ], - deps = [ - "@score_crates//:log", - ], -) - -cc_library( - name = "libfeo_log_cpp", - srcs = [ - "include/log.h", - "src/log.cc", - ], - hdrs = [ - "include/log.h", - ], - includes = ["include"], - linkstatic = True, - visibility = ["//visibility:public"], - deps = [":libfeo_log_ffi_rust"], -) - -rust_binary( - name = "feo_log_example_rust", - srcs = [ - "examples/hello.rs", - ], - deps = [ - ":libfeo_log_rust", - "//src/feo-logger:libfeo_logger_rust", - ], -) - -cc_binary( - name = "feo_log_example_cpp", - srcs = [ - "examples/hello.cc", - ], - deps = [ - ":libfeo_log_cpp", - "//src/feo-logger:libfeo_logger_cpp", - ], -) diff --git a/src/feo-log/Cargo.toml b/src/feo-log/Cargo.toml deleted file mode 100644 index fed0460..0000000 --- a/src/feo-log/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "feo-log" -version = "0.1.0" -edition = "2024" - -[dependencies] -# The `std` feature is currently required for the `set_boxed_logger` call. -log = { workspace = true, features = ["std"] } - -[dev-dependencies] -feo-logger = { workspace = true } diff --git a/src/feo-log/examples/hello.cc b/src/feo-log/examples/hello.cc deleted file mode 100644 index 2d8e976..0000000 --- a/src/feo-log/examples/hello.cc +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -#include -#include -#include - -#include -#include - -using namespace feo::log; - -// Tag for the log messages -static const char* TAG = "hello::main"; - -// Sleep for a random amount of time -void sleep(int max_ms); - -void log() {} - -// Log messages in a loop, demonstrating the different log levels -void do_it(int i) { - for (;;) { - trace(TAG, "Hello %d!", i); - sleep(500); - debug(TAG, "Hello %d!", i); - sleep(500); - info(TAG, "Hello %d!", i); - sleep(500); - warn(TAG, "Hello %d!", i); - sleep(500); - error(TAG, "Hello %d!", i); - sleep(2000); - } -} - -int main(int argc, char* argv[]) { - // Initialize the logger with the maximum log level set to TRACE - // Log to the console *and* the system log - feo::logger::init(TRACE, true, true); - - // Do a trace log - trace(TAG, "Hi - very spammy trace log. You won't see that again"); - - // Adjust the maximum log level - feo::log::set_max_level(LevelFilter::DEBUG); - - // Spawn threads that randomly log messages - auto a = std::thread(do_it, 1); - auto b = std::thread(do_it, 2); - - // Wait for the threads to finish - a.join(); - b.join(); - - return 0; -} - -void sleep(int max_ms) { - std::this_thread::sleep_for(std::chrono::milliseconds(std::rand() % max_ms)); -} diff --git a/src/feo-log/examples/hello.rs b/src/feo-log/examples/hello.rs deleted file mode 100644 index 3e9c201..0000000 --- a/src/feo-log/examples/hello.rs +++ /dev/null @@ -1,42 +0,0 @@ -// ******************************************************************************* -// Copyright (c) 2025 Contributors to the Eclipse Foundation -// -// See the NOTICE file(s) distributed with this work for additional -// information regarding copyright ownership. -// -// This program and the accompanying materials are made available under the -// terms of the Apache License Version 2.0 which is available at -// -// -// SPDX-License-Identifier: Apache-2.0 -// ******************************************************************************* - -use core::time; -use feo_log::{error, log, warn, Level, LevelFilter}; -use std::thread; - -fn main() { - feo_logger::init(LevelFilter::Trace, true, true); - - // Logs a static string on level `trace`. - log!(Level::Trace, "Kick it"); - - // Logs on level `debug` with `target` set to "hello". - log!( - target: "hello", - Level::Debug, - "You wake up late for school, man you don't want to go" - ); - - // Logs a format string on level `info`. - log!(Level::Info, "You ask your mom, please? but she still says, {}!", "No"); - - // Logs a static string on level `warn`. - warn!("You missed two classes"); - - loop { - // Logs a static string on level `error`. - error!("And no homework"); - thread::sleep(time::Duration::from_secs(1)); - } -} diff --git a/src/feo-log/include/log.h b/src/feo-log/include/log.h deleted file mode 100644 index 24e34b5..0000000 --- a/src/feo-log/include/log.h +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -// Logging API - -#ifndef __FEO_LOG_H__ -#define __FEO_LOG_H__ - -// Log a message on the trace level -#define trace(tag, fmt, ...) feo::log::log(__FILE__, __LINE__, feo::log::Level::Trace, tag, fmt, ##__VA_ARGS__) - -// Log a message on the debug level -#define debug(tag, fmt, ...) feo::log::log(__FILE__, __LINE__, feo::log::Level::Debug, tag, fmt, ##__VA_ARGS__) - -// Log a message on the info level -#define info(tag, fmt, ...) feo::log::log(__FILE__, __LINE__, feo::log::Level::Info, tag, fmt, ##__VA_ARGS__) - -// Log a message on the warn level -#define warn(tag, fmt, ...) feo::log::log(__FILE__, __LINE__, feo::log::Level::Warn, tag, fmt, ##__VA_ARGS__) - -// Log a message on the error level -#define error(tag, fmt, ...) feo::log::log(__FILE__, __LINE__, feo::log::Level::Error, tag, fmt, ##__VA_ARGS__) - -namespace feo { -namespace log { - -// Log severity levels -enum Level { Error = 1, Warn = 2, Info = 3, Debug = 4, Trace = 5 }; - -// Log level filter -enum LevelFilter { OFF = 0, ERROR = 1, WARN = 2, INFO = 3, DEBUG = 4, TRACE = 5 }; - -// Log function -void log(const char* file, int line, Level level, const char* tag, const char* fmt, ...); - -// Sets the global maximum log level. -// Generally, this should only be called by the active logging implementation. -// Note that Trace is the maximum level, because it provides the maximum amount of detail in the emitted logs. -void set_max_level(LevelFilter level); - -// Returns the current maximum log level. -LevelFilter max_level(); - -} // namespace log -} // namespace feo - -#endif // __FEO_LOG_H__ \ No newline at end of file diff --git a/src/feo-log/src/ffi.rs b/src/feo-log/src/ffi.rs deleted file mode 100644 index 7944ee0..0000000 --- a/src/feo-log/src/ffi.rs +++ /dev/null @@ -1,106 +0,0 @@ -// ******************************************************************************* -// Copyright (c) 2025 Contributors to the Eclipse Foundation -// -// See the NOTICE file(s) distributed with this work for additional -// information regarding copyright ownership. -// -// This program and the accompanying materials are made available under the -// terms of the Apache License Version 2.0 which is available at -// -// -// SPDX-License-Identifier: Apache-2.0 -// ******************************************************************************* - -use log::{Level, LevelFilter, Record}; -use std::ffi::{c_char, c_int, CStr}; - -#[allow(non_camel_case_types)] -type feo_log_Level = ::std::os::raw::c_int; - -const LEVEL_ERROR: feo_log_Level = 1; -const LEVEL_WARN: feo_log_Level = 2; -const LEVEL_INFO: feo_log_Level = 3; -const LEVEL_DEBUG: feo_log_Level = 4; -const LEVEL_TRACE: feo_log_Level = 5; - -#[allow(non_camel_case_types)] -type feo_log_Level_Filter = ::std::os::raw::c_int; - -const LEVEL_FILTER_OFF: feo_log_Level = 0; -const LEVEL_FILTER_ERROR: feo_log_Level = 1; -const LEVEL_FILTER_WARN: feo_log_Level = 2; -const LEVEL_FILTER_INFO: feo_log_Level = 3; -const LEVEL_FILTER_DEBUG: feo_log_Level = 4; -const LEVEL_FILTER_TRACE: feo_log_Level = 5; - -#[unsafe(no_mangle)] -extern "C" fn __log( - file: *const c_char, - line: c_int, - level: feo_log_Level, - target: *const c_char, - message: *const c_char, -) { - // Map the c level to the log level - let level = match level { - LEVEL_ERROR => Level::Error, - LEVEL_WARN => Level::Warn, - LEVEL_INFO => Level::Info, - LEVEL_DEBUG => Level::Debug, - LEVEL_TRACE => Level::Trace, - _ => panic!("invalid level"), - }; - - // Extract the target. This mappes to the tag of the c api - let target = unsafe { CStr::from_ptr(target) }.to_str().expect("invalid target"); - - // Construct metadata to be used for the pre check filtering - let metadata = log::Metadata::builder().level(level).target(target).build(); - - // Check if the log would have a chance to be logged. before we do any more work. - if !log::logger().enabled(&metadata) { - return; - } - - let file = unsafe { CStr::from_ptr(file) }.to_str().expect("invalid file"); - let line = line as u32; - let message = unsafe { CStr::from_ptr(message) }.to_str().expect("invalid message"); - - // Pass the record to the logger - log::logger().log( - &Record::builder() - .level(level) - .target(target) - .file(Some(file)) - .line(Some(line)) - .args(format_args!("{}", message)) - .build(), - ); -} - -/// Set the maximum log level -#[unsafe(no_mangle)] -extern "C" fn __set_max_level(level_filter: feo_log_Level_Filter) { - let level_filter = match level_filter { - LEVEL_FILTER_OFF => LevelFilter::Off, - LEVEL_FILTER_ERROR => LevelFilter::Error, - LEVEL_FILTER_WARN => LevelFilter::Warn, - LEVEL_FILTER_INFO => LevelFilter::Info, - LEVEL_FILTER_DEBUG => LevelFilter::Debug, - LEVEL_FILTER_TRACE => LevelFilter::Trace, - _ => panic!("invalid level filter"), - }; - log::set_max_level(level_filter); -} - -#[unsafe(no_mangle)] -extern "C" fn __max_level() -> feo_log_Level_Filter { - match log::max_level() { - LevelFilter::Off => LEVEL_FILTER_OFF, - LevelFilter::Error => LEVEL_FILTER_ERROR, - LevelFilter::Warn => LEVEL_FILTER_WARN, - LevelFilter::Info => LEVEL_FILTER_INFO, - LevelFilter::Debug => LEVEL_FILTER_DEBUG, - LevelFilter::Trace => LEVEL_FILTER_TRACE, - } -} diff --git a/src/feo-log/src/lib.rs b/src/feo-log/src/lib.rs deleted file mode 100644 index 80686da..0000000 --- a/src/feo-log/src/lib.rs +++ /dev/null @@ -1,25 +0,0 @@ -// ******************************************************************************* -// Copyright (c) 2025 Contributors to the Eclipse Foundation -// -// See the NOTICE file(s) distributed with this work for additional -// information regarding copyright ownership. -// -// This program and the accompanying materials are made available under the -// terms of the Apache License Version 2.0 which is available at -// -// -// SPDX-License-Identifier: Apache-2.0 -// ******************************************************************************* - -//! The score-feo logging facade. -//! -//! Use what's proven. Use what used out there. No - we're not special. - -#![no_std] -#![deny( - clippy::std_instead_of_core, - clippy::std_instead_of_alloc, - clippy::alloc_instead_of_core -)] - -pub use log::*; diff --git a/src/feo-log/src/log.cc b/src/feo-log/src/log.cc deleted file mode 100644 index fec31a3..0000000 --- a/src/feo-log/src/log.cc +++ /dev/null @@ -1,52 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -// Log implementation. - -#include -#include -#include - -// See rust `feo_log::MAX_RECORD_SIZE`. -static const size_t MAX_RECORD_SIZE = 8 * 1024; - -extern "C" void __log(const char* file, int line, int level, const char* tag, const char* message); -extern "C" void __set_max_level(int level); -extern "C" int __max_level(); - -namespace feo { -namespace log { - -/// Forward a log message. Flatten the format string. Other parameters are passed through. -void log(const char* file, int line, Level level, const char* tag, const char* fmt, ...) { - char message[MAX_RECORD_SIZE]; - va_list vl; - va_start(vl, fmt); - vsnprintf(message, sizeof(message), fmt, vl); - va_end(vl); - - __log(file, line, level, tag, message); -} - -/// Set the maximum log level. -void set_max_level(LevelFilter level) { - __set_max_level((int)level); -} - -/// Return the maximum log level. -LevelFilter max_level() { - return (LevelFilter)__max_level(); -} - -} // namespace log -} // namespace feo \ No newline at end of file diff --git a/src/feo-logger/BUILD.bazel b/src/feo-logger/BUILD.bazel deleted file mode 100644 index 7b26c6d..0000000 --- a/src/feo-logger/BUILD.bazel +++ /dev/null @@ -1,70 +0,0 @@ -# ******************************************************************************* -# Copyright (c) 2025 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License Version 2.0 which is available at -# https://www.apache.org/licenses/LICENSE-2.0 -# -# SPDX-License-Identifier: Apache-2.0 -# ******************************************************************************* - -load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library", "rust_static_library", "rust_test") - -rust_library( - name = "libfeo_logger_rust", - srcs = [ - "src/console.rs", - "src/fmt.rs", - "src/lib.rs", - "src/logd.rs", - "src/record.rs", - "src/thread.rs", - ], - crate_name = "feo_logger", - visibility = ["//visibility:public"], - deps = [ - "//src/feo-log:libfeo_log_rust", - "//src/feo-time:libfeo_time_rust", - "@score_crates//:console", - "@score_crates//:libc", - "@score_crates//:time", - ], -) - -cc_library( - name = "libfeo_logger_cpp", - srcs = [ - "include/logger.h", - "src/logger.cc", - ], - hdrs = [ - "include/logger.h", - ], - includes = ["include"], - linkstatic = True, - visibility = ["//visibility:public"], - deps = [ - ":libfeo_logger_ffi_rust", - "//src/feo-log:libfeo_log_cpp", - ], -) - -# FFI wrapper -rust_static_library( - name = "libfeo_logger_ffi_rust", - srcs = [ - "src/ffi.rs", - ], - deps = [ - ":libfeo_logger_rust", - "//src/feo-log:libfeo_log_rust", - ], -) - -rust_test( - name = "libfeo_logger_rust_test", - crate = ":libfeo_logger_rust", -) diff --git a/src/feo-logger/Cargo.toml b/src/feo-logger/Cargo.toml deleted file mode 100644 index 8db07b8..0000000 --- a/src/feo-logger/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "feo-logger" -version = "0.1.0" -edition = "2024" - -[dependencies] -console = { workspace = true } -feo-log = { workspace = true } -feo-time = { workspace = true } -libc = { workspace = true } -time = { workspace = true } diff --git a/src/feo-logger/README.md b/src/feo-logger/README.md deleted file mode 100644 index cd4d056..0000000 --- a/src/feo-logger/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# feo-logger - -The `feo-logger` is a logger in the terms of the `log` crate. It registers a global entity that acts as a sink for `feo_log::debug!` and friends calls. -The logs are then forwarded to a sink. Collection of records and serialization is done allocation free. Currently two sinks are implemented: - -## console - -Simple sink that logs to stdout. This maybe useful for debugging. - -## logd - -Connect to `logd` and forward each log record to it. See `logd` for details. \ No newline at end of file diff --git a/src/feo-logger/include/logger.h b/src/feo-logger/include/logger.h deleted file mode 100644 index cbb1831..0000000 --- a/src/feo-logger/include/logger.h +++ /dev/null @@ -1,28 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -#ifndef FEO_LOGGER_H - -#include - -namespace feo { -namespace logger { - -/// Initialize the logger. -/// Declare the minimum log level, whether to log to the console, and whether to log to the system log. -void init(feo::log::LevelFilter level_filter, bool console, bool logd); - -} // namespace logger -} // namespace feo - -#endif diff --git a/src/feo-logger/src/console.rs b/src/feo-logger/src/console.rs deleted file mode 100644 index 00b400f..0000000 --- a/src/feo-logger/src/console.rs +++ /dev/null @@ -1,25 +0,0 @@ -// ******************************************************************************* -// Copyright (c) 2025 Contributors to the Eclipse Foundation -// -// See the NOTICE file(s) distributed with this work for additional -// information regarding copyright ownership. -// -// This program and the accompanying materials are made available under the -// terms of the Apache License Version 2.0 which is available at -// -// -// SPDX-License-Identifier: Apache-2.0 -// ******************************************************************************* - -use crate::fmt; -use crate::record::Record; -use std::io::{self}; - -#[derive(Debug, Default)] -pub struct Console; - -impl Console { - pub fn write(&self, record: &Record) -> io::Result<()> { - fmt::format(record, io::stdout()) - } -} diff --git a/src/feo-logger/src/ffi.rs b/src/feo-logger/src/ffi.rs deleted file mode 100644 index 776612b..0000000 --- a/src/feo-logger/src/ffi.rs +++ /dev/null @@ -1,28 +0,0 @@ -// ******************************************************************************* -// Copyright (c) 2025 Contributors to the Eclipse Foundation -// -// See the NOTICE file(s) distributed with this work for additional -// information regarding copyright ownership. -// -// This program and the accompanying materials are made available under the -// terms of the Apache License Version 2.0 which is available at -// -// -// SPDX-License-Identifier: Apache-2.0 -// ******************************************************************************* - -use std::ffi::c_int; - -#[unsafe(no_mangle)] -extern "C" fn __init(level_filter: c_int, console: bool, logd: bool) { - let level_filter = match level_filter { - 0 => feo_log::LevelFilter::Off, - 1 => feo_log::LevelFilter::Error, - 2 => feo_log::LevelFilter::Warn, - 3 => feo_log::LevelFilter::Info, - 4 => feo_log::LevelFilter::Debug, - 5 => feo_log::LevelFilter::Trace, - _ => panic!("invalid level filter"), - }; - feo_logger::init(level_filter, console, logd); -} diff --git a/src/feo-logger/src/fmt.rs b/src/feo-logger/src/fmt.rs deleted file mode 100644 index 0bdf3f4..0000000 --- a/src/feo-logger/src/fmt.rs +++ /dev/null @@ -1,161 +0,0 @@ -// ******************************************************************************* -// Copyright (c) 2025 Contributors to the Eclipse Foundation -// -// See the NOTICE file(s) distributed with this work for additional -// information regarding copyright ownership. -// -// This program and the accompanying materials are made available under the -// terms of the Apache License Version 2.0 which is available at -// -// -// SPDX-License-Identifier: Apache-2.0 -// ******************************************************************************* - -use crate::record::{OwnedRecord, Record}; -use console::{style, Color, StyledObject}; -use core::str; -use core::sync::atomic::{self, AtomicUsize, Ordering}; -use feo_log::Level; -use feo_time::SystemTime; -use time::format_description::FormatItem; -use time::macros::format_description; - -// TODO: Add monochrome support. - -const TIMESTAMP_FORMAT: &[FormatItem<'static>] = format_description!("[hour]:[minute]:[second].[subsecond digits:3]"); - -static TARGET_SIZE: atomic::AtomicUsize = atomic::AtomicUsize::new(16); -static TGID_SIZE: atomic::AtomicUsize = atomic::AtomicUsize::new(4); -static TID_SIZE: atomic::AtomicUsize = atomic::AtomicUsize::new(4); - -pub fn format(record: &Record, mut writer: W) -> Result<(), std::io::Error> { - let timestamp = { - let timestamp = record.timestamp; - let timestamp = time::OffsetDateTime::from_unix_timestamp_nanos( - timestamp.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_nanos() as i128, - ) - .unwrap(); - timestamp.format(TIMESTAMP_FORMAT).expect("failed to format timestamp") - }; - - let level = { - let level_color = match record.level { - Level::Error => Color::Red, - Level::Warn => Color::Yellow, - Level::Info => Color::Green, - Level::Debug => Color::Color256(243), - Level::Trace => Color::White, - }; - style(record.level).bold().fg(level_color) - }; - - let tgid = format_id(record.tgid, &TGID_SIZE, true); - let tid = format_id(record.tid, &TID_SIZE, false); - - let message = unsafe { str::from_utf8_unchecked(record.args) }; - - let target = { - let target = record.target; - TARGET_SIZE.fetch_max(target.len(), Ordering::Relaxed); - let target_size = TARGET_SIZE.load(Ordering::Relaxed); - let target_color = target.color(); - style(format!("{target:(record: OwnedRecord, writer: W) -> Result<(), std::io::Error> { - let record = Record { - timestamp: record.timestamp, - level: record.level, - target: &record.target, - file: record.file.as_deref(), - line: record.line, - tgid: record.tgid, - tid: record.tid, - args: record.args.as_bytes(), - }; - format(&record, writer) -} - -/// Generate a color of `self`. -trait HashColor { - fn color(&self) -> Color; -} - -impl HashColor for &str { - fn color(&self) -> Color { - let hash = self.bytes().fold(42u8, |c, x| c ^ x); - Color::Color256(hash) - } -} - -impl HashColor for u32 { - fn color(&self) -> Color { - (*self as u64).color() - } -} - -impl HashColor for u64 { - fn color(&self) -> Color { - // Some colors are hard to read on (at least) dark terminals - // and I consider some others as ugly ;-) - let color = match *self as u8 { - c @ 0..=1 => c + 2, - c @ 16..=21 => c + 6, - c @ 52..=55 | c @ 126..=129 => c + 4, - c @ 163..=165 | c @ 200..=201 => c + 3, - c @ 207 => c + 1, - c @ 232..=240 => c + 9, - c => c, - }; - Color::Color256(color) - } -} - -/// Format `id` with a color based on the hash of `id`. Update `g` with the -/// maximum length of the formatted `id`. -fn format_id(id: u32, g: &AtomicUsize, align_left: bool) -> StyledObject { - let tgid_len = num_hex_digits(id); - let color = id.color(); - g.fetch_max(tgid_len, Ordering::Relaxed); - let len = g.load(Ordering::Relaxed); - if align_left { - style(format!("{:l$x}", id, l = len)).fg(color) - } -} - -// Calculate the number of hex digits needed to represent `n`. -fn num_hex_digits(n: u32) -> usize { - (1 + n.checked_ilog2().unwrap_or_default() / 4) as usize -} - -#[cfg(test)] -mod test { - use super::num_hex_digits; - - #[test] - fn hex_digits() { - assert_eq!(num_hex_digits(0), 1); - assert_eq!(num_hex_digits(1), 1); - assert_eq!(num_hex_digits(15), 1); - assert_eq!(num_hex_digits(16), 2); - assert_eq!(num_hex_digits(255), 2); - assert_eq!(num_hex_digits(256), 3); - assert_eq!(num_hex_digits(4095), 3); - } -} diff --git a/src/feo-logger/src/lib.rs b/src/feo-logger/src/lib.rs deleted file mode 100644 index dd59f2c..0000000 --- a/src/feo-logger/src/lib.rs +++ /dev/null @@ -1,112 +0,0 @@ -// ******************************************************************************* -// Copyright (c) 2025 Contributors to the Eclipse Foundation -// -// See the NOTICE file(s) distributed with this work for additional -// information regarding copyright ownership. -// -// This program and the accompanying materials are made available under the -// terms of the Apache License Version 2.0 which is available at -// -// -// SPDX-License-Identifier: Apache-2.0 -// ******************************************************************************* - -//! The score-feo-logger -//! -//! Bare minimum logger implementation for the `score-feo` project. -//! This is placeholder. - -use core::fmt::Debug; -use core::str::FromStr; -use feo_log::{LevelFilter, Log, Metadata, Record}; -use feo_time::SystemTime; -use std::io::Write; -use std::{io, process}; - -mod console; -// TODO: hide fmt and its deps behind a feature flag: `console` and `time`. -pub mod fmt; -mod logd; -pub mod record; -mod thread; - -const ENV_RUST_LOG: &str = "RUST_LOG"; -const MAX_ARGS_SIZE: usize = 8 * 1024; -pub const MAX_RECORD_SIZE: usize = 8 * 1024; - -/// Initialize the logger. -/// -/// A valid level passed as `RUST_LOG` environment variable will `level`. -/// Enable output to `stdout` via `console`. -/// Enable output forwarding to `logd` via `logd=true`. -pub fn init(level: LevelFilter, console: bool, logd: bool) { - let logger = Logger::new(console, logd); - - // Set the maximum log level the log subsystem will forward to this logger impl. - feo_log::set_max_level(level_from_env().unwrap_or(level)); - // Set the logger in the global subsystem. - feo_log::set_boxed_logger(Box::new(logger)).expect("failed to set logger") -} - -/// The FEO logger. -#[derive(Debug)] -pub struct Logger { - console: Option, - logd: Option, -} - -impl Logger { - /// Create a new logger. - pub fn new(console: bool, logd: bool) -> Self { - let console = console.then(console::Console::default); - let logd = logd.then(logd::Logd::default); - Self { console, logd } - } -} - -impl Log for Logger { - /// Check if a log message with the specified metadata would be logged. - fn enabled(&self, metadata: &Metadata) -> bool { - metadata.level() <= feo_log::max_level() - } - - fn log(&self, record: &Record) { - let timestamp = SystemTime::now(); - let tgid = process::id(); - let tid = thread::id(); - // Serialize args into args buffer. This must happen without any heap allocation which is ensured - // by using std::io::Write. - let args_buffer = &mut [0u8; MAX_ARGS_SIZE]; - let args = { - let mut writer = io::Cursor::new(&mut args_buffer[..]); - write!(&mut writer, "{}", record.args()).expect("failed to format args"); - let len = writer.position() as usize; - &args_buffer[0..len] - }; - let level = record.level(); - let target = record.target(); - let file = record.file(); - let line = record.line(); - - let record = record::Record::new(timestamp, level, target, file, line, tgid, tid, args); - - if let Some(console) = &self.console { - console.write(&record).expect("failed to write to console"); - } - - if let Some(logd) = &self.logd { - let _ = logd.write(&record); - } - } - - fn flush(&self) {} -} - -/// Try to parse the log level from the environment variable `RUST_LOG`. -fn level_from_env() -> Option { - std::env::var(ENV_RUST_LOG).ok().and_then(|s| { - LevelFilter::from_str(&s) - .inspect_err(|_| eprintln!("Failed to parse log level from `RUST_LOG={s}`")) - .ok() - }) -} diff --git a/src/feo-logger/src/logd.rs b/src/feo-logger/src/logd.rs deleted file mode 100644 index ecd5ba5..0000000 --- a/src/feo-logger/src/logd.rs +++ /dev/null @@ -1,102 +0,0 @@ -// ******************************************************************************* -// Copyright (c) 2025 Contributors to the Eclipse Foundation -// -// See the NOTICE file(s) distributed with this work for additional -// information regarding copyright ownership. -// -// This program and the accompanying materials are made available under the -// terms of the Apache License Version 2.0 which is available at -// -// -// SPDX-License-Identifier: Apache-2.0 -// ******************************************************************************* - -use crate::record::Record; -use crate::MAX_RECORD_SIZE; -use core::mem; -use libc::{sockaddr_un, AF_UNIX}; -use std::io; -use std::os::fd::{AsRawFd, FromRawFd, OwnedFd}; -use std::sync::Mutex; - -pub const UNIX_PACKET_PATH: &str = "/tmp/logd.sock"; - -/// Simple connector to logd. Uses pure libc. Doesn't do any reconnects etc. Needs lots of checks and love. -#[derive(Debug, Default)] -pub struct Logd { - socket: Mutex>, -} - -impl Logd { - pub fn write(&self, record: &Record) -> io::Result<()> { - if record.encoded_len() > MAX_RECORD_SIZE { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, - "record too large to encode", - )); - } - - // TODO: this can be optimized. Use MaybeUninit and write the record directly to the buffer. - let mut writer = io::Cursor::new([0u8; MAX_RECORD_SIZE]); - - // Encode - let len = record.encode(&mut writer)?; - - let buffer = writer.into_inner(); - - let mut guard = self.socket.lock().unwrap(); - - // Reconnect if needed - if guard.is_none() { - // Connect - match Self::connect() { - Ok(connection) => *guard = Some(connection), - Err(_) => return Ok(()), - }; - } - - let socket = guard.as_mut().unwrap(); - - // Safety: buffer is a valid buffer with the correct length - let ret = unsafe { libc::send(socket.as_raw_fd(), buffer.as_ptr().cast(), len, 0) }; - if ret != len as isize { - guard.take(); - Err(io::Error::last_os_error()) - } else { - Ok(()) - } - } - - fn connect() -> io::Result { - // Create a seqpacket socket - let socket = unsafe { libc::socket(AF_UNIX, libc::SOCK_SEQPACKET, 0) }; - assert!(socket >= 0, "socket failed"); - // Wrap the socket in a OwnedFd - // Safety: socket is a valid file descriptor. Connect result is checked. - let socket = unsafe { OwnedFd::from_raw_fd(socket) }; - - // Prepare the sockaddr - let bytes = UNIX_PACKET_PATH.as_bytes(); - - // Safety: sockaddr_un is a C struct with no padding - let mut sockaddr = unsafe { mem::MaybeUninit::::zeroed().assume_init() }; - - sockaddr.sun_family = AF_UNIX as u16; - - let path = (&mut sockaddr.sun_path.as_mut_slice()[0..bytes.len()]) as *mut _ as *mut [u8]; - // Safety: path is a valid pointer to a slice of the correct length - let path = unsafe { &mut *path }; - path.clone_from_slice(bytes); - let sockaddr = &mut sockaddr as *mut _ as *mut libc::sockaddr; - let addr_len = mem::size_of::() as libc::socklen_t; - - // Connect - // Safety: sockaddr is a valid pointer to a sockaddr_un. addr_len is the correct size. - let ret = unsafe { libc::connect(socket.as_raw_fd(), sockaddr, addr_len) }; - if ret != 0 { - Err(io::Error::last_os_error()) - } else { - Ok(socket) - } - } -} diff --git a/src/feo-logger/src/logger.cc b/src/feo-logger/src/logger.cc deleted file mode 100644 index 172a9ab..0000000 --- a/src/feo-logger/src/logger.cc +++ /dev/null @@ -1,26 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -#include - -extern "C" void __init(int level_filter, bool console, bool logd); - -namespace feo { -namespace logger { - -void init(feo::log::LevelFilter level_filter, bool console, bool logd) { - __init(level_filter, console, logd); -} - -} // namespace logger -} // namespace feo \ No newline at end of file diff --git a/src/feo-logger/src/record.rs b/src/feo-logger/src/record.rs deleted file mode 100644 index 8a82c8e..0000000 --- a/src/feo-logger/src/record.rs +++ /dev/null @@ -1,334 +0,0 @@ -// ******************************************************************************* -// Copyright (c) 2025 Contributors to the Eclipse Foundation -// -// See the NOTICE file(s) distributed with this work for additional -// information regarding copyright ownership. -// -// This program and the accompanying materials are made available under the -// terms of the Apache License Version 2.0 which is available at -// -// -// SPDX-License-Identifier: Apache-2.0 -// ******************************************************************************* - -use core::mem::size_of; -use core::time::Duration; -use feo_log::Level; -use feo_time::SystemTime; -use std::io::{self, Read}; - -/// Log record that can be encoded. This is the borrowed version. -#[derive(Debug)] -pub struct Record<'a> { - pub timestamp: SystemTime, - pub level: Level, - pub target: &'a str, - pub file: Option<&'a str>, - pub line: Option, - pub tgid: u32, - pub tid: u32, - pub args: &'a [u8], -} - -impl Record<'_> { - /// Create a new record. - #[allow(clippy::too_many_arguments)] - pub fn new<'a>( - timestamp: SystemTime, - level: Level, - target: &'a str, - file: Option<&'a str>, - line: Option, - tgid: u32, - tid: u32, - args: &'a [u8], - ) -> Record<'a> { - Record { - timestamp, - level, - target, - file, - line, - tgid, - tid, - args, - } - } - - pub fn encoded_len(&self) -> usize { - let mut len: usize = 0; - - len += size_of::() + size_of::(); // Timestamp - len += size_of::(); // Level - len += size_of::() + self.target.len(); // Target - len += self.file.map_or(size_of::(), |f| size_of::() + f.len()); // File - len += size_of::(); // Line - len += size_of::(); // Tgid - len += size_of::(); // Tid - len += size_of::() + self.args.len(); // Args - len - } - - pub fn encode(&self, mut w: W) -> io::Result { - let mut len = 0; - // Timestamp - let timestamp = self.timestamp.duration_since(SystemTime::UNIX_EPOCH).unwrap(); - w.write_all(×tamp.as_secs().to_be_bytes())?; - w.write_all(×tamp.subsec_nanos().to_be_bytes())?; - len += size_of::() + size_of::(); - - // Level - w.write_all(&[self.level as u8])?; // Level - len += size_of::(); - - // Target - w.write_all(&(self.target.len() as u32).to_be_bytes())?; - w.write_all(self.target.as_bytes())?; - len += size_of::() + self.target.len(); - - // File - if let Some(file) = &self.file { - w.write_all(&(file.len() as u32).to_be_bytes())?; - w.write_all(file.as_bytes())?; - len += size_of::() + file.len(); - } else { - w.write_all(&0u32.to_be_bytes())?; - len += size_of::(); - } - - // Line - if let Some(line) = self.line { - w.write_all(&line.to_be_bytes())?; - } else { - w.write_all(&0u32.to_be_bytes())?; - } - len += size_of::(); - - // Tgid - w.write_all(&self.tgid.to_be_bytes())?; - len += size_of::(); - - // Tid - w.write_all(&self.tid.to_be_bytes())?; - len += size_of::(); - - // Args - w.write_all(&(self.args.len() as u32).to_be_bytes())?; - w.write_all(self.args)?; - len += size_of::() + self.args.len(); - - // Add the length field - Ok(len) - } -} - -/// Log record that can be decoded. This is the owned version. -#[derive(Debug)] -pub struct OwnedRecord { - pub timestamp: SystemTime, - pub level: Level, - pub target: String, - pub file: Option, - pub line: Option, - pub tgid: u32, - pub tid: u32, - pub args: String, -} - -impl OwnedRecord { - pub fn decode(r: &[u8]) -> io::Result { - let mut r = io::Cursor::new(&r); - - // Timestamp - let timestamp = { - let timestamp_secs = read_u64_be(&mut r)?; - let timestamp_nanos = read_u32_be(&mut r)?; - SystemTime::UNIX_EPOCH - .checked_add(Duration::new(timestamp_secs, timestamp_nanos)) - .unwrap() - }; - - // Level - let level = match read_u8_be(&mut r)? { - 1 => Level::Error, - 2 => Level::Warn, - 3 => Level::Info, - 4 => Level::Debug, - 5 => Level::Trace, - _ => return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid level")), - }; - - // Target - let target = { - let target_len = read_u32_be(&mut r)? as usize; - let mut buf = vec![0u8; target_len]; - r.read_exact(&mut buf)?; - String::from_utf8(buf).map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "invalid target"))? - }; - - // File - let file = { - let file_len = read_u32_be(&mut r)? as usize; - if file_len > 0 { - let mut buf = vec![0u8; file_len]; - r.read_exact(&mut buf)?; - Some(String::from_utf8(buf).map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "invalid file"))?) - } else { - None - } - }; - - // Line - let line = match read_u32_be(&mut r)? { - 0 => None, - n => Some(n), - }; - - let tgid = read_u32_be(&mut r)?; - let tid = read_u32_be(&mut r)?; - - // Args - let args = { - let args_len = read_u32_be(&mut r)? as usize; - let mut buf = vec![0u8; args_len]; - r.read_exact(&mut buf)?; - String::from_utf8(buf).map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "invalid args"))? - }; - - Ok(OwnedRecord { - timestamp, - level, - target, - file, - line, - tgid, - tid, - args, - }) - } -} - -fn read_u8_be(mut r: R) -> io::Result { - let mut buf = [0u8; size_of::()]; - r.read_exact(&mut buf)?; - Ok(u8::from_be_bytes(buf)) -} - -fn read_u32_be(mut r: R) -> io::Result { - let mut buf = [0u8; size_of::()]; - r.read_exact(&mut buf)?; - Ok(u32::from_be_bytes(buf)) -} - -fn read_u64_be(mut r: R) -> io::Result { - let mut buf = [0u8; size_of::()]; - r.read_exact(&mut buf)?; - Ok(u64::from_be_bytes(buf)) -} - -#[cfg(test)] -mod test { - use super::{read_u32_be, read_u64_be, Record}; - use crate::record::OwnedRecord; - use std::io; - - #[test] - fn read_u32_be_good() { - let buf = [0x12, 0x34, 0x56, 0x78]; - assert_eq!(read_u32_be(io::Cursor::new(&buf)).unwrap(), 0x12345678); - } - - #[test] - fn read_u32_be_short() { - let buf = [0x12, 0x34, 0x56]; - assert!(read_u32_be(io::Cursor::new(&buf)).is_err()); - } - - #[test] - fn read_u64_be_good() { - let buf = &mut [0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0]; - assert_eq!(read_u64_be(io::Cursor::new(&buf)).unwrap(), 0x123456789abcdef0); - } - - #[test] - fn read_u64_be_short() { - let buf = &mut [0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde]; - assert!(read_u64_be(io::Cursor::new(&buf)).is_err()); - } - - #[test] - fn encode_decode() { - fn do_it(record: Record) { - let mut buf = Vec::new(); - record.encode(&mut buf).unwrap(); - - let decoded = OwnedRecord::decode(&buf[..]).unwrap(); - assert_eq!(decoded.timestamp, record.timestamp); - assert_eq!(decoded.level, record.level); - assert_eq!(decoded.target, record.target); - assert_eq!(decoded.file.as_deref(), record.file); - assert_eq!(decoded.line, record.line); - assert_eq!(decoded.args.as_bytes(), record.args); - } - - // Full - do_it(Record::new( - feo_time::SystemTime::now(), - feo_log::Level::Info, - "target", - Some("file"), - Some(42), - 1, - 2, - b"args", - )); - - // Empty target - do_it(Record::new( - feo_time::SystemTime::now(), - feo_log::Level::Info, - "", - Some("file"), - Some(42), - 1, - 2, - b"args", - )); - - // Empty file - do_it(Record::new( - feo_time::SystemTime::now(), - feo_log::Level::Info, - "target", - None, - Some(42), - 1, - 2, - b"args", - )); - - // Empty line - do_it(Record::new( - feo_time::SystemTime::now(), - feo_log::Level::Info, - "target", - Some("file"), - None, - 1, - 2, - b"args", - )); - - // Empty args - do_it(Record::new( - feo_time::SystemTime::now(), - feo_log::Level::Info, - "target", - Some("file"), - Some(42), - 1, - 2, - b"", - )); - } -} diff --git a/src/feo-logger/src/thread.rs b/src/feo-logger/src/thread.rs deleted file mode 100644 index 2e8d431..0000000 --- a/src/feo-logger/src/thread.rs +++ /dev/null @@ -1,21 +0,0 @@ -// ******************************************************************************* -// Copyright (c) 2025 Contributors to the Eclipse Foundation -// -// See the NOTICE file(s) distributed with this work for additional -// information regarding copyright ownership. -// -// This program and the accompanying materials are made available under the -// terms of the Apache License Version 2.0 which is available at -// -// -// SPDX-License-Identifier: Apache-2.0 -// ******************************************************************************* - -/// The type of a thread id -pub type ThreadId = u32; - -/// Get the current thread id -pub fn id() -> ThreadId { - // Safety: gettid(2) says this never fails - unsafe { libc::gettid() as u32 } -} diff --git a/src/feo-time/BUILD.bazel b/src/feo-time/BUILD.bazel index c626012..bd14506 100644 --- a/src/feo-time/BUILD.bazel +++ b/src/feo-time/BUILD.bazel @@ -29,6 +29,10 @@ rust_library( ], crate_name = "feo_time", visibility = ["//visibility:public"], + deps = [ + "@score_baselibs_rust//src/log/score_log", + "@score_crates//:serde", + ], ) # CC library @@ -49,7 +53,11 @@ rust_static_library( "src/ffi.rs", "src/lib.rs", ], - deps = ["//src/feo-time:libfeo_time_rust"], + deps = [ + "//src/feo-time:libfeo_time_rust", + "@score_baselibs_rust//src/log/score_log", + "@score_crates//:serde", + ], ) # Rust library tests @@ -78,7 +86,7 @@ rust_binary( ], deps = [ ":libfeo_time_rust", - "//src/feo-log:libfeo_log_rust", - "//src/feo-logger:libfeo_logger_rust", + "@score_baselibs_rust//src/log/score_log", + "@score_baselibs_rust//src/log/stdout_logger", ], ) diff --git a/src/feo-time/Cargo.toml b/src/feo-time/Cargo.toml index 50d3417..3808946 100644 --- a/src/feo-time/Cargo.toml +++ b/src/feo-time/Cargo.toml @@ -5,7 +5,4 @@ edition = "2024" [dependencies] time = { workspace = true } - -[dev-dependencies] -feo-log = { workspace = true } -feo-logger = { workspace = true } +serde = { workspace = true } diff --git a/src/feo-time/examples/time_speedrun.rs b/src/feo-time/examples/time_speedrun.rs index 1041d02..6d4873e 100644 --- a/src/feo-time/examples/time_speedrun.rs +++ b/src/feo-time/examples/time_speedrun.rs @@ -11,13 +11,21 @@ // SPDX-License-Identifier: Apache-2.0 // ******************************************************************************* -use core::time::Duration; -use feo_log::{debug, info, LevelFilter}; +use feo_time::Duration; use feo_time::Scaled; +use score_log::{debug, info, LevelFilter}; use std::thread; +use stdout_logger::StdoutLoggerBuilder; fn main() { - feo_logger::init(LevelFilter::Debug, true, false); + // Initialize logger. + StdoutLoggerBuilder::new() + .context("time-speedrun") + .show_module(true) + .show_file(true) + .show_line(true) + .log_level(LevelFilter::Debug) + .set_as_default_logger(); let start_instant_std = std::time::Instant::now(); let start_instant_feo = feo_time::Instant::now(); @@ -30,35 +38,42 @@ fn main() { for _ in 0..5 { debug!("Sleeping for 1 \"real\" second..."); thread::sleep(core::time::Duration::from_secs(1)); + let start_systemtime_feo = start_systemtime_feo.elapsed().expect("time error"); + let start_instant_feo = start_instant_feo.elapsed(); info!( "feo time since start: systemtime: {:?}, instant: {:?}", - start_systemtime_feo.elapsed().expect("time error"), - start_instant_feo.elapsed() + start_systemtime_feo, start_instant_feo ); + let start_systemtime_std = Duration(start_systemtime_std.elapsed().expect("time error")); + let start_instant_std = Duration(start_instant_std.elapsed()); info!( "std time since start: systemtime: {:?}, instant: {:?}", - start_systemtime_std.elapsed().expect("time error"), - start_instant_std.elapsed() + start_systemtime_std, start_instant_std ); } // Scaling duration for thread::sleep. Use `scaled()` method to get the scaled duration // that matches the current time speed factor and feed it into `std::thread::sleep`. - const SLEEP_DURATION: Duration = core::time::Duration::from_secs(1); + const SLEEP_DURATION: Duration = Duration::from_secs(1); let sleep_duration_scaled = SLEEP_DURATION.scaled(); for _ in 0..5 { - debug!("Sleeping for {SLEEP_DURATION:?} (scaled: {sleep_duration_scaled:?})"); - thread::sleep(sleep_duration_scaled); + debug!( + "Sleeping for {:?} (scaled: {:?})", + SLEEP_DURATION, sleep_duration_scaled + ); + thread::sleep(sleep_duration_scaled.into()); + let start_systemtime_feo = start_systemtime_feo.elapsed().expect("time error"); + let start_instant_feo = start_instant_feo.elapsed(); info!( "feo time since start: systemtime: {:?}, instant: {:?}", - start_systemtime_feo.elapsed().expect("time error"), - start_instant_feo.elapsed() + start_systemtime_feo, start_instant_feo ); + let start_systemtime_std = Duration(start_systemtime_std.elapsed().expect("time error")); + let start_instant_std = Duration(start_instant_std.elapsed()); info!( "std time since start: systemtime: {:?}, instant: {:?}", - start_systemtime_std.elapsed().expect("time error"), - start_instant_std.elapsed() + start_systemtime_std, start_instant_std ); } } diff --git a/src/feo-time/src/lib.rs b/src/feo-time/src/lib.rs index 71a08d7..194d28c 100644 --- a/src/feo-time/src/lib.rs +++ b/src/feo-time/src/lib.rs @@ -63,10 +63,131 @@ use core::error::Error; use core::fmt; use core::ops::{Add, AddAssign, Sub, SubAssign}; use core::sync::atomic::{AtomicI32, Ordering}; -pub use core::time::Duration; +use score_log::fmt::ScoreDebug; +use serde::{Deserialize, Serialize}; use std::sync::{LazyLock, Once}; use std::time; +#[derive(Clone, Copy, Default, Debug, PartialEq, PartialOrd, Hash, Ord, Eq, Serialize, Deserialize)] +pub struct Duration(pub core::time::Duration); + +impl Duration { + pub const ZERO: Duration = Duration(core::time::Duration::ZERO); + + pub fn as_secs(&self) -> u64 { + self.0.as_secs() + } + + pub fn subsec_nanos(&self) -> u32 { + self.0.subsec_nanos() + } + + #[allow(dead_code)] + pub const fn from_secs(secs: u64) -> Self { + Self(core::time::Duration::from_secs(secs)) + } + + #[allow(dead_code)] + pub const fn from_millis(millis: u64) -> Self { + Self(core::time::Duration::from_millis(millis)) + } + + #[allow(dead_code)] + pub const fn from_micros(micros: u64) -> Self { + Self(core::time::Duration::from_micros(micros)) + } + + #[allow(dead_code)] + pub const fn from_nanos(nanos: u64) -> Self { + Self(core::time::Duration::from_nanos(nanos)) + } + + #[allow(dead_code)] + pub const fn new(secs: u64, nanos: u32) -> Self { + Self(core::time::Duration::new(secs, nanos)) + } + + #[allow(dead_code)] + pub const fn as_nanos(&self) -> u128 { + self.0.as_nanos() + } + + #[allow(dead_code)] + pub const fn saturating_sub(&self, rhs: Duration) -> Duration { + Duration(self.0.saturating_sub(rhs.0)) + } + + #[allow(dead_code)] + pub const fn is_zero(&self) -> bool { + self.0.is_zero() + } + + #[allow(dead_code)] + pub const fn as_secs_f64(&self) -> f64 { + self.0.as_secs_f64() + } +} + +impl From for Duration { + fn from(value: core::time::Duration) -> Self { + Self(value) + } +} + +impl From for core::time::Duration { + fn from(value: Duration) -> Self { + value.0 + } +} + +impl ScoreDebug for Duration { + fn fmt( + &self, + f: &mut dyn score_log::fmt::ScoreWrite, + spec: &score_log::fmt::FormatSpec, + ) -> Result<(), score_log::fmt::Error> { + ScoreDebug::fmt(&self.0.as_secs_f64(), f, spec) + } +} + +impl core::ops::Mul for Duration { + type Output = Duration; + + fn mul(self, rhs: u32) -> Self::Output { + Self(self.0 * rhs) + } +} + +impl core::ops::Add for Duration { + type Output = Duration; + + fn add(self, rhs: Duration) -> Self::Output { + Self(self.0 + rhs.0) + } +} + +impl core::ops::Sub for Duration { + type Output = Duration; + + fn sub(self, rhs: Duration) -> Self::Output { + Self(self.0 - rhs.0) + } +} + +impl core::iter::Sum for Duration { + fn sum>(iter: I) -> Self { + Self(iter.map(|d| d.0).sum()) + } +} + +impl core::ops::Div for Duration { + type Output = Duration; + + fn div(self, rhs: u32) -> Self::Output { + Self(self.0 / rhs) + } +} + /// An anchor in time which can be used to create new `SystemTime` instances or /// learn about where in time a `SystemTime` lies. // @@ -231,7 +352,7 @@ impl Instant { /// ``` #[must_use] pub fn checked_duration_since(&self, earlier: Instant) -> Option { - self.0.checked_duration_since(earlier.0) + self.0.checked_duration_since(earlier.0).map(Duration) } /// Returns the amount of time elapsed from another instant to this one, @@ -284,14 +405,14 @@ impl Instant { /// `Instant` (which means it's inside the bounds of the underlying data structure), `None` /// otherwise. pub fn checked_add(&self, duration: Duration) -> Option { - self.0.checked_add(duration).map(Instant) + self.0.checked_add(duration.into()).map(Instant) } /// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as /// `Instant` (which means it's inside the bounds of the underlying data structure), `None` /// otherwise. pub fn checked_sub(&self, duration: Duration) -> Option { - self.0.checked_sub(duration).map(Instant) + self.0.checked_sub(duration.into()).map(Instant) } } @@ -414,7 +535,7 @@ impl SystemTime { /// println!("{difference:?}"); /// ``` pub fn duration_since(&self, earlier: Self) -> Result { - self.0.duration_since(earlier.0).map_err(Into::into) + self.0.duration_since(earlier.0).map(Duration).map_err(Into::into) } /// Returns the difference from this system time to the @@ -450,14 +571,14 @@ impl SystemTime { /// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None` /// otherwise. pub fn checked_add(&self, duration: Duration) -> Option { - self.0.checked_add(duration).map(SystemTime) + self.0.checked_add(duration.into()).map(SystemTime) } /// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as /// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None` /// otherwise. pub fn checked_sub(&self, duration: Duration) -> Option { - self.0.checked_sub(duration).map(SystemTime) + self.0.checked_sub(duration.into()).map(SystemTime) } } @@ -469,7 +590,7 @@ impl Add for SystemTime { /// This function may panic if the resulting point in time cannot be represented by the /// underlying data structure. See [`SystemTime::checked_add`] for a version without panic. fn add(self, dur: Duration) -> SystemTime { - SystemTime(self.0.add(dur)) + SystemTime(self.0.add(dur.into())) } } @@ -483,7 +604,7 @@ impl Sub for SystemTime { type Output = SystemTime; fn sub(self, dur: Duration) -> SystemTime { - SystemTime(self.0.sub(dur)) + SystemTime(self.0.sub(dur.into())) } } @@ -523,7 +644,7 @@ impl Error for SystemTimeError { impl From for SystemTimeError { fn from(e: time::SystemTimeError) -> Self { - SystemTimeError(e.duration()) + SystemTimeError(Duration(e.duration())) } } diff --git a/src/feo-tracer/BUILD.bazel b/src/feo-tracer/BUILD.bazel index 384b2b9..1326f14 100644 --- a/src/feo-tracer/BUILD.bazel +++ b/src/feo-tracer/BUILD.bazel @@ -23,13 +23,13 @@ rust_binary( visibility = ["//visibility:public"], deps = [ ":libfeo_tracer", - "//src/feo-log:libfeo_log_rust", - "//src/feo-logger:libfeo_logger_rust", + "//src/feo-tracing:libfeo_tracing_rust", + "@score_baselibs_rust//src/log/score_log", + "@score_baselibs_rust//src/log/stdout_logger", "@score_crates//:anyhow", "@score_crates//:argh", "@score_crates//:futures", "@score_crates//:indicatif", - "@score_crates//:indicatif_log_bridge", "@score_crates//:tokio", ], ) @@ -45,9 +45,9 @@ rust_library( crate_name = "feo_tracer", visibility = ["//visibility:public"], deps = [ - "//src/feo-log:libfeo_log_rust", "//src/feo-tracing:libfeo_tracing_rust", "//src/perfetto-model", + "@score_baselibs_rust//src/log/score_log", "@score_crates//:anyhow", "@score_crates//:human_bytes", "@score_crates//:indicatif", diff --git a/src/feo-tracer/Cargo.toml b/src/feo-tracer/Cargo.toml index 7c5189c..876dc18 100644 --- a/src/feo-tracer/Cargo.toml +++ b/src/feo-tracer/Cargo.toml @@ -6,13 +6,10 @@ edition = "2024" [dependencies] anyhow = { workspace = true } argh = { workspace = true } -feo-log = { workspace = true } -feo-logger = { workspace = true } feo-tracing = { workspace = true } futures = { workspace = true } human_bytes = { workspace = true } indicatif = { workspace = true } -indicatif-log-bridge = { workspace = true } perfetto-model = { workspace = true } postcard = { workspace = true } prost = { workspace = true } diff --git a/src/feo-tracer/src/io.rs b/src/feo-tracer/src/io.rs index 5729ca4..c676a35 100644 --- a/src/feo-tracer/src/io.rs +++ b/src/feo-tracer/src/io.rs @@ -15,9 +15,9 @@ use crate::data; use anyhow::{Context, Error}; -use feo_log::{debug, info, warn}; use feo_tracing::protocol; use postcard::accumulator::{CobsAccumulator, FeedResult}; +use score_log::{debug, info, warn}; use std::collections::HashMap; use std::fs; use std::io::ErrorKind; @@ -32,11 +32,11 @@ const READ_BUFFER_SIZE: usize = 32 * protocol::MAX_PACKET_SIZE; pub async fn listen(path: &Path, sink: mpsc::Sender) -> Result<(), Error> { // Bind - info!("Binding to {path:?}"); + info!("Binding to {}", format!("{path:?}")); let listener = UnixListener::bind(path)?; // Listen - info!("Listening on {path:?}"); + info!("Listening on {}", format!("{path:?}")); loop { let (socket, _) = listener.accept().await.context("failed to accept connection")?; @@ -55,7 +55,8 @@ async fn connection(socket: UnixStream, sink: mpsc::Sender) { .ok(); info!( - "Processing messages from {pid:x} ({})", + "Processing messages from {:x} ({})", + pid, process_name.as_deref().unwrap_or("") ); @@ -84,7 +85,7 @@ async fn connection(socket: UnixStream, sink: mpsc::Sender) { let len = match socket.try_read(&mut read_buffer) { Ok(0) => { - info!("Connection from {pid} closed"); + info!("Connection from {} closed", pid); break; }, Ok(len) => len, @@ -92,7 +93,11 @@ async fn connection(socket: UnixStream, sink: mpsc::Sender) { continue; }, Err(e) => { - warn!("Failed to receive data from {pid}: {e:?}. Closing connection"); + warn!( + "Failed to receive data from {}: {}. Closing connection", + pid, + format!("{e:?}") + ); break; }, }; @@ -104,7 +109,7 @@ async fn connection(socket: UnixStream, sink: mpsc::Sender) { remaining = match cobs_buffer.feed_ref::(remaining) { FeedResult::Consumed => break, FeedResult::OverFull(_) => { - warn!("Deserialization buffer overflow in {pid}. Closing connection"); + warn!("Deserialization buffer overflow in {}. Closing connection", pid); break 'deser; }, FeedResult::DeserError(remaining) => remaining, @@ -114,7 +119,11 @@ async fn connection(socket: UnixStream, sink: mpsc::Sender) { let packet = match data::decode_packet(pid, data, &mut thread_name_cache, process_name.clone()) { Ok(packet) => packet, Err(e) => { - warn!("Failed to decode packet from {pid}: {e:?}. Closing connection",); + warn!( + "Failed to decode packet from {}: {}. Closing connection", + pid, + format!("{e:?}") + ); break 'deser; }, }; diff --git a/src/feo-tracer/src/main.rs b/src/feo-tracer/src/main.rs index 7fc1ff3..00d6a28 100644 --- a/src/feo-tracer/src/main.rs +++ b/src/feo-tracer/src/main.rs @@ -16,13 +16,13 @@ use anyhow::{bail, Context, Error}; use argh::FromArgs; use core::future::pending; -use feo_log::{debug, info, LevelFilter}; use feo_tracer::io::listen; use feo_tracer::perfetto; use futures::FutureExt; -use indicatif_log_bridge::LogWrapper; +use score_log::{debug, info, LevelFilter}; use std::path::{Path, PathBuf}; use std::{fs, io}; +use stdout_logger::StdoutLoggerBuilder; use tokio::sync::mpsc; use tokio::{runtime, select, signal, task, time}; @@ -68,14 +68,18 @@ fn main() -> Result<(), Error> { } = argh::from_env(); // Initialize logging - let logger = feo_logger::Logger::new(true, false); + StdoutLoggerBuilder::new() + .context("feo-tracer") + .show_module(true) + .show_file(true) + .show_line(true) + .log_level(LevelFilter::Warn) + .set_as_default_logger(); // Initialize progress bar let mut progress = progress::Progress::new()?; - // Wrap the logger in the progress bar to avoid interleaving - LogWrapper::new(progress.bar(), logger).try_init()?; - feo_log::set_max_level(log_level.unwrap_or(LevelFilter::Warn)); + score_log::set_max_level(log_level.unwrap_or(LevelFilter::Warn)); info!("Starting feo-tracer"); @@ -91,7 +95,7 @@ fn main() -> Result<(), Error> { let path = Path::new(UNIX_PACKET_PATH); // Check if socket is present and remove if necessary if path.exists() { - debug!("Removing stale socket at {path:?}"); + debug!("Removing stale socket at {}", format!("{path:?}")); fs::remove_file(path).with_context(|| format!("failed to remove {path:?}"))?; } listen(path, message_sender).await @@ -125,9 +129,9 @@ fn main() -> Result<(), Error> { // Timeout if configured or wait indefinitely let timeout = async move { if let Some(duration) = duration.map(time::Duration::from_secs) { - info!("Tracing for {duration:?}"); + info!("Tracing for {}", format!("{duration:?}")); time::sleep(duration).await; - info!("Traced for {duration:?}. Shutting down..."); + info!("Traced for {}. Shutting down...", format!("{duration:?}")); } else { pending::<()>().await; } diff --git a/src/feo-tracer/src/perfetto.rs b/src/feo-tracer/src/perfetto.rs index 788066b..73e19de 100644 --- a/src/feo-tracer/src/perfetto.rs +++ b/src/feo-tracer/src/perfetto.rs @@ -13,10 +13,10 @@ use crate::data::{RecordData, RecordEventInfo, Thread, TraceRecord}; use anyhow::{bail, Error}; -use feo_log::info; use perfetto_model as idl; use perfetto_model; use prost::Message as ProstMessage; +use score_log::info; use std::collections::HashMap; use std::io; use std::time::UNIX_EPOCH; @@ -64,10 +64,8 @@ pub struct Perfetto { impl Drop for Perfetto { fn drop(&mut self) { - info!( - "Dropping perfetto writer. Wrote {} bytes", - human_bytes::human_bytes(self.writer.1 as f64) - ); + let bytes = human_bytes::human_bytes(self.writer.1 as f64); + info!("Dropping perfetto writer. Wrote {} bytes", bytes,); } } diff --git a/src/feo-tracer/src/progress.rs b/src/feo-tracer/src/progress.rs index 1811743..8f9925f 100644 --- a/src/feo-tracer/src/progress.rs +++ b/src/feo-tracer/src/progress.rs @@ -62,11 +62,6 @@ impl Progress { }) } - /// Return a copy of the multi progress bar - pub fn bar(&self) -> MultiProgress { - self.bar.clone() - } - /// Add a writer to the progress bar pub fn add_writer(&mut self, name: &str, writer: T) -> impl Write + use { let pb = indicatif::ProgressBar::new(0) diff --git a/src/feo-tracing/BUILD.bazel b/src/feo-tracing/BUILD.bazel index bddf2a9..38c4192 100644 --- a/src/feo-tracing/BUILD.bazel +++ b/src/feo-tracing/BUILD.bazel @@ -23,7 +23,7 @@ rust_library( crate_name = "feo_tracing", visibility = ["//visibility:public"], deps = [ - "//src/feo-log:libfeo_log_rust", + "@score_baselibs_rust//src/log/score_log", "@score_crates//:libc", "@score_crates//:postcard", "@score_crates//:serde", @@ -39,8 +39,6 @@ rust_binary( ], deps = [ ":libfeo_tracing_rust", - "//src/feo-log:libfeo_log_rust", - "//src/feo-logger:libfeo_logger_rust", "@score_crates//:tracing", ], ) diff --git a/src/feo-tracing/Cargo.toml b/src/feo-tracing/Cargo.toml index 2f8404d..027d2d7 100644 --- a/src/feo-tracing/Cargo.toml +++ b/src/feo-tracing/Cargo.toml @@ -4,7 +4,6 @@ version = "0.1.0" edition = "2024" [dependencies] -feo-log = { workspace = true } libc = { workspace = true } postcard = { workspace = true } serde = { workspace = true } diff --git a/src/feo-tracing/src/lib.rs b/src/feo-tracing/src/lib.rs index 8e3bcd2..03c44aa 100644 --- a/src/feo-tracing/src/lib.rs +++ b/src/feo-tracing/src/lib.rs @@ -21,5 +21,6 @@ pub mod protocol; /// Initialize tracing pub use feo_subscriber::init; +pub use feo_subscriber::ScoreDebugIoError; /// Re-export of the `tracing` crate. pub use tracing::{self, event, instrument, level_filters::LevelFilter, span, Level}; diff --git a/src/feo-tracing/src/subscriber.rs b/src/feo-tracing/src/subscriber.rs index 7c98328..4ec5d4f 100644 --- a/src/feo-tracing/src/subscriber.rs +++ b/src/feo-tracing/src/subscriber.rs @@ -15,9 +15,11 @@ use crate::protocol::{truncate, EventInfo, TraceData, TracePacket, MAX_INFO_SIZE use core::sync::atomic; use core::sync::atomic::AtomicBool; use core::time::Duration; -use feo_log::error; +use score_log::error; +use score_log::fmt::{FormatSpec, ScoreDebug, ScoreWrite}; use std::io::Write; use std::os::unix::net::UnixStream; +use std::sync::mpsc::SendError; use std::sync::{mpsc, Arc}; use std::thread::JoinHandle; use std::{io, thread}; @@ -57,6 +59,113 @@ pub fn init(level: LevelFilter) { set_global_default(subscriber).expect("setting tracing default failed"); } +/// ScoreDebug support for std::io::Error +#[derive(Debug)] +pub struct ScoreDebugIoError(pub std::io::Error); + +impl std::fmt::Display for ScoreDebugIoError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl ScoreDebug for ScoreDebugIoError { + fn fmt( + &self, + f: &mut dyn score_log::fmt::ScoreWrite, + spec: &score_log::fmt::FormatSpec, + ) -> Result<(), score_log::fmt::Error> { + use std::io::ErrorKind; + + match self.0.kind() { + ErrorKind::NotFound => f.write_str("NotFound", spec), + ErrorKind::PermissionDenied => f.write_str("PermissionDenied", spec), + ErrorKind::ConnectionRefused => f.write_str("ConnectionRefused", spec), + ErrorKind::ConnectionReset => f.write_str("ConnectionReset", spec), + ErrorKind::HostUnreachable => f.write_str("HostUnreachable", spec), + ErrorKind::NetworkUnreachable => f.write_str("NetworkUnreachable", spec), + ErrorKind::ConnectionAborted => f.write_str("ConnectionAborted", spec), + ErrorKind::NotConnected => f.write_str("NotConnected", spec), + ErrorKind::AddrInUse => f.write_str("AddrInUse", spec), + ErrorKind::AddrNotAvailable => f.write_str("AddrNotAvailable", spec), + ErrorKind::NetworkDown => f.write_str("NetworkDown", spec), + ErrorKind::BrokenPipe => f.write_str("BrokenPipe", spec), + ErrorKind::AlreadyExists => f.write_str("AlreadyExists", spec), + ErrorKind::WouldBlock => f.write_str("WouldBlock", spec), + ErrorKind::NotADirectory => f.write_str("NotADirectory", spec), + ErrorKind::IsADirectory => f.write_str("IsADirectory", spec), + ErrorKind::DirectoryNotEmpty => f.write_str("DirectoryNotEmpty", spec), + ErrorKind::ReadOnlyFilesystem => f.write_str("ReadOnlyFilesystem", spec), + ErrorKind::StaleNetworkFileHandle => f.write_str("StaleNetworkFileHandle", spec), + ErrorKind::InvalidInput => f.write_str("InvalidInput", spec), + ErrorKind::InvalidData => f.write_str("InvalidData", spec), + ErrorKind::TimedOut => f.write_str("TimedOut", spec), + ErrorKind::WriteZero => f.write_str("WriteZero", spec), + ErrorKind::StorageFull => f.write_str("StorageFull", spec), + ErrorKind::NotSeekable => f.write_str("NotSeekable", spec), + ErrorKind::QuotaExceeded => f.write_str("QuotaExceeded", spec), + ErrorKind::FileTooLarge => f.write_str("FileTooLarge", spec), + ErrorKind::ResourceBusy => f.write_str("ResourceBusy", spec), + ErrorKind::ExecutableFileBusy => f.write_str("ExecutableFileBusy", spec), + ErrorKind::Deadlock => f.write_str("Deadlock", spec), + ErrorKind::CrossesDevices => f.write_str("CrossesDevices", spec), + ErrorKind::TooManyLinks => f.write_str("TooManyLinks", spec), + ErrorKind::InvalidFilename => f.write_str("InvalidFilename", spec), + ErrorKind::ArgumentListTooLong => f.write_str("ArgumentListTooLong", spec), + ErrorKind::Interrupted => f.write_str("Interrupted", spec), + ErrorKind::Unsupported => f.write_str("Unsupported", spec), + ErrorKind::UnexpectedEof => f.write_str("UnexpectedEof", spec), + ErrorKind::OutOfMemory => f.write_str("OutOfMemory", spec), + ErrorKind::Other => f.write_str("Other", spec), + _ => f.write_str("IO error", spec), + } + } +} + +impl From for ScoreDebugIoError { + fn from(err: std::io::Error) -> Self { + ScoreDebugIoError(err) + } +} + +struct ScoreDebugPostcardError(pub postcard::Error); + +impl ScoreDebug for ScoreDebugPostcardError { + fn fmt(&self, f: &mut dyn ScoreWrite, spec: &FormatSpec) -> Result<(), score_log::fmt::Error> { + use postcard::Error; + match self.0 { + Error::WontImplement => f.write_str("WontImplement", spec), + Error::NotYetImplemented => f.write_str("NotYetImplemented", spec), + Error::SerializeBufferFull => f.write_str("SerializeBufferFull", spec), + Error::SerializeSeqLengthUnknown => f.write_str("SerializeSeqLengthUnknown", spec), + Error::DeserializeUnexpectedEnd => f.write_str("DeserializeUnexpectedEnd", spec), + Error::DeserializeBadVarint => f.write_str("DeserializeBadVarint", spec), + Error::DeserializeBadBool => f.write_str("DeserializeBadBool", spec), + Error::DeserializeBadChar => f.write_str("DeserializeBadChar", spec), + Error::DeserializeBadUtf8 => f.write_str("DeserializeBadUtf8", spec), + Error::DeserializeBadOption => f.write_str("DeserializeBadOption", spec), + Error::DeserializeBadEnum => f.write_str("DeserializeBadEnum", spec), + Error::DeserializeBadEncoding => f.write_str("DeserializeBadEncoding", spec), + Error::DeserializeBadCrc => f.write_str("DeserializeBadCrc", spec), + Error::SerdeSerCustom => f.write_str("SerdeSerCustom", spec), + Error::SerdeDeCustom => f.write_str("SerdeDeCustom", spec), + Error::CollectStrError => f.write_str("CollectStrError", spec), + _ => f.write_str("postcard error", spec), + } + } +} + +// The field is unused, but kept for consistency +struct ScoreDebugSendError(#[allow(dead_code)] pub SendError); + +impl ScoreDebug for ScoreDebugSendError { + fn fmt(&self, f: &mut dyn ScoreWrite, spec: &FormatSpec) -> Result<(), score_log::fmt::Error> { + // A send operation can only fail if the receiving end of a channel is + // disconnected (according to Ferrocene docs) + f.write_str("disconnected", spec) + } +} + /// A subscriber sending trace data to the feo-tracer via unix socket and postcard serialized data. /// /// See the `TraceData` and `TracePacket` types for the data format. @@ -83,7 +192,7 @@ impl Subscriber { let connection = match UnixStream::connect(UNIX_PACKET_PATH) { Ok(connection) => connection, Err(e) => { - error!("Failed to connect to feo-tracer: {:?}, aborting", e); + error!("Failed to connect to feo-tracer: {:?}, aborting", ScoreDebugIoError(e)); // disable further tracing (TODO: add a time period of retrying) enabled.store(false, atomic::Ordering::Relaxed); return; @@ -103,14 +212,14 @@ impl Subscriber { let serialized = match postcard::to_slice_cobs(&packet, &mut buffer[..]) { Ok(serialized) => serialized, Err(e) => { - error!("Failed to serialize trace packet: {e:?}"); + error!("Failed to serialize trace packet: {:?}", ScoreDebugPostcardError(e)); continue; }, }; let ret = socket_writer.write_all(serialized); if let Err(error) = ret { - error!("Failed to send to feo-tracer: {error:?}, aborting"); + error!("Failed to send to feo-tracer: {:?}, aborting", ScoreDebugIoError(error)); enabled.store(false, atomic::Ordering::Relaxed); return; } @@ -129,7 +238,10 @@ impl Subscriber { return; } if let Err(e) = self.sender.send(packet) { - error!("Failed to connect to feo-tracer: {:?}, aborting", e); + error!( + "Failed to connect to feo-tracer: {:?}, aborting", + ScoreDebugSendError(e) + ); self.enabled.store(false, atomic::Ordering::Relaxed); } } diff --git a/src/feo/BUILD.bazel b/src/feo/BUILD.bazel index 23f4fe9..6e36cb1 100644 --- a/src/feo/BUILD.bazel +++ b/src/feo/BUILD.bazel @@ -29,6 +29,7 @@ rust_library( "src/agent/relayed/recorder.rs", "src/agent/relayed/secondary.rs", "src/cpp.rs", + "src/debug_fmt.rs", "src/error.rs", "src/ids.rs", "src/lib.rs", @@ -75,9 +76,9 @@ rust_library( visibility = ["//visibility:public"], deps = [ "//src/feo-com:libfeo_com_rust", - "//src/feo-log:libfeo_log_rust", "//src/feo-time:libfeo_time_rust", "//src/feo-tracing:libfeo_tracing_rust", + "@score_baselibs_rust//src/log/score_log", "@score_crates//:ctrlc", "@score_crates//:libc", "@score_crates//:mio", @@ -100,6 +101,7 @@ rust_library( "src/agent/relayed/recorder.rs", "src/agent/relayed/secondary.rs", "src/cpp.rs", + "src/debug_fmt.rs", "src/error.rs", "src/ids.rs", "src/lib.rs", @@ -147,9 +149,9 @@ rust_library( visibility = ["//visibility:public"], deps = [ "//src/feo-com:libfeo_com_rust", - "//src/feo-log:libfeo_log_rust", "//src/feo-time:libfeo_time_rust", "//src/feo-tracing:libfeo_tracing_rust", + "@score_baselibs_rust//src/log/score_log", "@score_crates//:ctrlc", "@score_crates//:libc", "@score_crates//:mio", diff --git a/src/feo/Cargo.toml b/src/feo/Cargo.toml index 87616d7..b988704 100644 --- a/src/feo/Cargo.toml +++ b/src/feo/Cargo.toml @@ -5,7 +5,6 @@ edition = "2024" [dependencies] feo-com = { workspace = true } -feo-log = { workspace = true } feo-time = { workspace = true } feo-tracing = { workspace = true } libc = { workspace = true } @@ -16,9 +15,6 @@ postcard = { workspace = true, features = [ serde = { workspace = true, optional = true } ctrlc = { workspace = true, features = ["termination"] } -[dev-dependencies] -feo-logger = { workspace = true } - [features] default = [] loop_duration_meter = [] diff --git a/src/feo/src/agent/direct/primary.rs b/src/feo/src/agent/direct/primary.rs index 6bfc9d7..3def76e 100644 --- a/src/feo/src/agent/direct/primary.rs +++ b/src/feo/src/agent/direct/primary.rs @@ -15,6 +15,7 @@ use crate::activity::ActivityIdAndBuilder; use crate::agent::NodeAddress; +use crate::debug_fmt::ScoreDebugDebug; use crate::error::Error; use crate::ids::{ActivityId, AgentId, WorkerId}; use crate::scheduler::Scheduler; @@ -27,8 +28,8 @@ use alloc::boxed::Box; use alloc::sync::Arc; use alloc::vec::Vec; use core::sync::atomic::AtomicBool; -use core::time::Duration; -use feo_log::info; +use feo_time::Duration; +use score_log::{error, info}; use std::collections::HashMap; use std::thread::{self, JoinHandle}; @@ -95,7 +96,7 @@ impl Primary { let worker = Worker::new(id, agent_id, activity_builders, connector, timeout); if let Err(e) = worker.run() { - feo_log::error!("Worker {} in primary agent failed: {:?}", id, e); + error!("Worker {} in primary agent failed: {:?}", id, e); } }, NodeAddress::UnixSocket(path) => { @@ -106,7 +107,7 @@ impl Primary { let worker = Worker::new(id, agent_id, activity_builders, connector, timeout); if let Err(e) = worker.run() { - feo_log::error!("Worker {} in primary agent failed: {:?}", id, e); + error!("Worker {} in primary agent failed: {:?}", id, e); } }, }) @@ -172,7 +173,10 @@ impl Primary { // We can now safely join our local worker threads. for th in self.worker_threads.drain(..) { if let Err(e) = th.join() { - feo_log::error!("A local worker thread in the primary agent panicked: {:?}", e); + error!( + "A local worker thread in the primary agent panicked: {:?}", + ScoreDebugDebug::<_, 1024>(&e) + ); } } diff --git a/src/feo/src/agent/direct/primary_mpsc.rs b/src/feo/src/agent/direct/primary_mpsc.rs index 46f2888..25d6359 100644 --- a/src/feo/src/agent/direct/primary_mpsc.rs +++ b/src/feo/src/agent/direct/primary_mpsc.rs @@ -14,6 +14,7 @@ //! Implementation of the primary agent for mpsc-only signalling use crate::activity::ActivityIdAndBuilder; +use crate::debug_fmt::ScoreDebugDebug; use crate::error::Error; use crate::ids::{ActivityId, AgentId, WorkerId}; use crate::scheduler::Scheduler; @@ -25,8 +26,8 @@ use alloc::boxed::Box; use alloc::sync::Arc; use alloc::vec::Vec; use core::sync::atomic::AtomicBool; -use core::time::Duration; -use feo_log::{debug, info}; +use feo_time::Duration; +use score_log::{debug, error, info}; use std::collections::HashMap; use std::thread::{self, JoinHandle}; @@ -139,7 +140,10 @@ impl Primary { for th in self.worker_threads.drain(..) { if let Err(e) = th.join() { - feo_log::error!("A local worker thread in the primary agent panicked: {:?}", e); + error!( + "A local worker thread in the primary agent panicked: {:?}", + ScoreDebugDebug::<_, 1024>(&e) + ); } } debug!("Primary agent finished"); diff --git a/src/feo/src/agent/direct/recorder.rs b/src/feo/src/agent/direct/recorder.rs index 7441246..f4a1da3 100644 --- a/src/feo/src/agent/direct/recorder.rs +++ b/src/feo/src/agent/direct/recorder.rs @@ -20,7 +20,7 @@ use crate::recording::registry::TypeRegistry; use crate::signalling::common::interface::ConnectRecorder; use crate::signalling::direct::recorder::{TcpRecorderConnector, UnixRecorderConnector}; use alloc::boxed::Box; -use core::time::Duration; +use feo_time::Duration; /// Configuration of a recorder pub struct RecorderConfig<'r> { diff --git a/src/feo/src/agent/direct/secondary.rs b/src/feo/src/agent/direct/secondary.rs index 7d6c7ce..a52aae8 100644 --- a/src/feo/src/agent/direct/secondary.rs +++ b/src/feo/src/agent/direct/secondary.rs @@ -15,13 +15,14 @@ use crate::activity::ActivityIdAndBuilder; use crate::agent::NodeAddress; +use crate::debug_fmt::ScoreDebugDebug; use crate::ids::{AgentId, WorkerId}; use crate::signalling::common::interface::ConnectWorker; use crate::signalling::direct::worker::{TcpWorkerConnector, UnixWorkerConnector}; use crate::worker::Worker; use alloc::vec::Vec; -use core::time::Duration; -use feo_log::{debug, error}; +use feo_time::Duration; +use score_log::{debug, error}; use std::thread::{self, JoinHandle}; /// Configuration of a secondary agent @@ -98,7 +99,11 @@ impl Secondary { for th in self.worker_threads { if let Err(e) = th.join() { - error!("Worker thread for agent {:?} panicked: {:?}", self.id, e); + error!( + "Worker thread for agent {:?} panicked: {:?}", + self.id, + ScoreDebugDebug::<_, 1024>(&e) + ); } } diff --git a/src/feo/src/agent/relayed/primary.rs b/src/feo/src/agent/relayed/primary.rs index f26b078..f526d5d 100644 --- a/src/feo/src/agent/relayed/primary.rs +++ b/src/feo/src/agent/relayed/primary.rs @@ -26,8 +26,8 @@ use alloc::boxed::Box; use alloc::sync::Arc; use alloc::vec::Vec; use core::sync::atomic::AtomicBool; -use core::time::Duration; -use feo_log::{debug, info}; +use feo_time::Duration; +use score_log::{debug, info}; use std::collections::HashMap; use std::thread::{self, JoinHandle}; diff --git a/src/feo/src/agent/relayed/recorder.rs b/src/feo/src/agent/relayed/recorder.rs index 6fca433..e92ab5c 100644 --- a/src/feo/src/agent/relayed/recorder.rs +++ b/src/feo/src/agent/relayed/recorder.rs @@ -20,7 +20,7 @@ use crate::recording::registry::TypeRegistry; use crate::signalling::common::interface::ConnectRecorder; use crate::signalling::relayed::sockets_mpsc::{RecorderConnectorTcp, RecorderConnectorUnix}; use alloc::boxed::Box; -use core::time::Duration; +use feo_time::Duration; /// Configuration of a recorder pub struct RecorderConfig<'r> { diff --git a/src/feo/src/agent/relayed/secondary.rs b/src/feo/src/agent/relayed/secondary.rs index 98c4bf4..102288f 100644 --- a/src/feo/src/agent/relayed/secondary.rs +++ b/src/feo/src/agent/relayed/secondary.rs @@ -22,8 +22,8 @@ use crate::signalling::relayed::ConnectSecondary; use crate::worker::Worker; use alloc::boxed::Box; use alloc::vec::Vec; -use core::time::Duration; -use feo_log::debug; +use feo_time::Duration; +use score_log::debug; use std::collections::HashMap; use std::thread::{self, JoinHandle}; diff --git a/src/feo/src/debug_fmt.rs b/src/feo/src/debug_fmt.rs new file mode 100644 index 0000000..b1034f4 --- /dev/null +++ b/src/feo/src/debug_fmt.rs @@ -0,0 +1,49 @@ +// ******************************************************************************* +// Copyright (c) 2026 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache License Version 2.0 which is available at +// +// +// SPDX-License-Identifier: Apache-2.0 +// ******************************************************************************* + +use alloc::collections::BTreeSet; +use score_log::fmt::ScoreDebug; +use score_log::fmt::{DebugSet, FormatSpec, ScoreWrite}; +use std::collections::HashSet; +use std::io::Write; + +pub struct ScoreDebugHashSet<'a, T: ScoreDebug>(pub &'a HashSet); + +impl<'a, T: ScoreDebug> ScoreDebug for ScoreDebugHashSet<'a, T> { + fn fmt(&self, f: &mut dyn ScoreWrite, spec: &FormatSpec) -> Result<(), score_log::fmt::Error> { + DebugSet::new(f, spec).entries(self.0.iter()).finish() + } +} + +pub struct ScoreDebugBTreeSet<'a, T: ScoreDebug>(pub &'a BTreeSet); + +impl<'a, T: ScoreDebug> ScoreDebug for ScoreDebugBTreeSet<'a, T> { + fn fmt(&self, f: &mut dyn ScoreWrite, spec: &FormatSpec) -> Result<(), score_log::fmt::Error> { + DebugSet::new(f, spec).entries(self.0.iter()).finish() + } +} + +pub struct ScoreDebugDebug<'a, T: core::fmt::Debug, const MAX_LENGTH: usize>(pub &'a T); + +impl<'a, T: core::fmt::Debug, const MAX_LENGTH: usize> ScoreDebug for ScoreDebugDebug<'a, T, MAX_LENGTH> { + fn fmt(&self, f: &mut dyn ScoreWrite, spec: &FormatSpec) -> Result<(), score_log::fmt::Error> { + let buf = &mut [0u8; { MAX_LENGTH }]; + let debug_str = { + let mut writer = std::io::Cursor::new(&mut buf[..]); + write!(&mut writer, "{:?}", self.0).expect("failed to write Debug"); + let len = writer.position() as usize; + &buf[0..len] + }; + f.write_str(core::str::from_utf8(debug_str).expect("not a valid UTF-8 string"), spec) + } +} diff --git a/src/feo/src/error.rs b/src/feo/src/error.rs index ce1f44e..5bb0384 100644 --- a/src/feo/src/error.rs +++ b/src/feo/src/error.rs @@ -15,9 +15,11 @@ use crate::ids::{ActivityId, ChannelId, WorkerId}; use crate::signalling::common::signals::Signal; -use core::time::Duration; +use feo_time::Duration; +use feo_tracing::ScoreDebugIoError; #[cfg(feature = "recording")] use postcard::experimental::max_size::MaxSize; +use score_log::ScoreDebug; #[cfg(feature = "recording")] use serde::Deserialize; #[cfg(feature = "recording")] @@ -25,14 +27,14 @@ use serde::Serialize; /// FEO Error type #[non_exhaustive] -#[derive(Debug)] +#[derive(Debug, ScoreDebug)] pub enum Error { ActivityFailed(ActivityId, ActivityError), ActivityNotFound(ActivityId), Channel(&'static str), ChannelClosed, ChannelNotFound(ChannelId), - Io((std::io::Error, &'static str)), + Io((ScoreDebugIoError, &'static str)), Timeout(Duration, &'static str), UnexpectedProtocolSignal, UnexpectedSignal(Signal), @@ -41,7 +43,7 @@ pub enum Error { /// Defines the types of failures an Activity can report. #[cfg_attr(feature = "recording", derive(Serialize, Deserialize, MaxSize))] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, ScoreDebug)] pub enum ActivityError { /// A failure during the `startup()` method. Startup, @@ -76,6 +78,6 @@ impl core::fmt::Display for Error { impl From for Error { fn from(err: std::io::Error) -> Self { - Error::Io((err, "failed")) + Error::Io((ScoreDebugIoError(err), "failed")) } } diff --git a/src/feo/src/ids.rs b/src/feo/src/ids.rs index 8c20304..55bed9a 100644 --- a/src/feo/src/ids.rs +++ b/src/feo/src/ids.rs @@ -18,6 +18,8 @@ use core::hash::Hash; use core::marker::PhantomData; #[cfg(feature = "recording")] use postcard::experimental::max_size::MaxSize; +use score_log::fmt::ScoreDebug; +use score_log::ScoreDebug; #[cfg(feature = "recording")] use serde::{Deserialize, Serialize}; @@ -48,7 +50,7 @@ impl GetPrefix for AgentIdMarker { } /// Identifies a communication channel peer -#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash, ScoreDebug)] #[non_exhaustive] pub enum ChannelId { Activity(ActivityId), @@ -108,6 +110,16 @@ pub struct GenericId { _discriminator: PhantomData, } +impl ScoreDebug for GenericId { + fn fmt( + &self, + f: &mut dyn score_log::fmt::ScoreWrite, + spec: &score_log::fmt::FormatSpec, + ) -> Result<(), score_log::fmt::Error> { + f.write_u64(&self.id, spec) + } +} + impl GenericId { pub const fn new(id: u64) -> Self { Self { diff --git a/src/feo/src/lib.rs b/src/feo/src/lib.rs index 682e167..ad9f8e6 100644 --- a/src/feo/src/lib.rs +++ b/src/feo/src/lib.rs @@ -44,6 +44,7 @@ extern crate std; pub mod activity; pub mod agent; pub mod cpp; +pub mod debug_fmt; pub mod error; pub mod ids; #[cfg(feature = "recording")] diff --git a/src/feo/src/recording/recorder.rs b/src/feo/src/recording/recorder.rs index 1ff3b1c..bd3ec4a 100644 --- a/src/feo/src/recording/recorder.rs +++ b/src/feo/src/recording/recorder.rs @@ -23,10 +23,11 @@ use crate::timestamp::{timestamp, Timestamp}; use alloc::boxed::Box; use alloc::vec; use alloc::vec::Vec; -use core::time::Duration; -use feo_log::{debug, error, trace}; +use feo_time::Duration; +use feo_tracing::ScoreDebugIoError; use io::Write; use postcard::experimental::max_size::MaxSize; +use score_log::{debug, error, trace, ScoreDebug}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::io::BufWriter; @@ -96,7 +97,7 @@ impl<'s> FileRecorder<'s> { .unwrap_or_else(|| panic!("type name {type_name} not in registry")); let transcoder_builder = &info.comrec_builder; let transcoder = transcoder_builder(topic); - debug!("Creating transcoder: {topic}, {type_name}"); + debug!("Creating transcoder: {}, {}", topic, type_name); self.transcoders.push(transcoder); } @@ -122,7 +123,7 @@ impl<'s> FileRecorder<'s> { let Some(signal) = received else { continue; }; - debug!("Received signal {signal}"); + debug!("Received signal {}", signal); match signal { Signal::StartupSync(sync_info) => { @@ -153,7 +154,7 @@ impl<'s> FileRecorder<'s> { debug!("Recorder {} sent termination ack. Exiting.", self.id); // Linger for a moment to ensure TerminateAck has time to be sent // over the network before the thread exits and closes the socket. - thread::sleep(Duration::from_millis(100)); + thread::sleep(Duration::from_millis(100).into()); return; // Graceful exit from the run loop }, @@ -196,7 +197,7 @@ impl<'s> FileRecorder<'s> { let mut buf = [0u8; Record::POSTCARD_MAX_SIZE]; let serialized_header = postcard::to_slice(&data_desc_record, &mut buf).expect("serialization failed"); - trace!("Writing data: {description:?}"); + trace!("Writing data: {:?}", description); // Write description record and subsequent data block // In case of failure, log an error message and continue @@ -206,7 +207,7 @@ impl<'s> FileRecorder<'s> { .write_all(serialized_header) .and_then(|_| self.writer.write_all(serialized_data)) { - error!("Failed to write data: {e:?}"); + error!("Failed to write data: {:?}", ScoreDebugIoError(e)); } } } @@ -221,7 +222,7 @@ impl<'s> FileRecorder<'s> { let mut buf = [0u8; Record::POSTCARD_MAX_SIZE]; let serialized = postcard::to_slice(&signal_record, &mut buf).expect("serialization failed"); if let Err(e) = self.writer.write_all(serialized) { - error!("Failed to write signal {signal:?}: {e:?}"); + error!("Failed to write signal {:?}: {:?}", signal, ScoreDebugIoError(e)); } } @@ -262,7 +263,7 @@ pub struct SignalRecord { pub signal: Signal, } -#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize, ScoreDebug)] pub struct DataDescriptionRecord<'s> { // The monotonic time at the moment of recording as duration since the epoch pub timestamp: Timestamp, diff --git a/src/feo/src/recording/registry.rs b/src/feo/src/recording/registry.rs index 01079f9..2ace242 100644 --- a/src/feo/src/recording/registry.rs +++ b/src/feo/src/recording/registry.rs @@ -16,6 +16,7 @@ use crate::recording::transcoder::{ComRecTranscoderBuilder, RecordingTranscoder} use alloc::borrow::ToOwned as _; use alloc::boxed::Box; use feo_com::interface::ActivityInput; +use score_log::fmt::ScoreDebug; use serde::Serialize; use std::collections::HashMap; @@ -51,7 +52,7 @@ impl TypeRegistry { /// This method will panic if /// - a type with identical type id (i.e. the same type) has already been registered /// - the explicitly or implicitly provided type name is not unique - pub fn add( + pub fn add( &mut self, type_name: Option<&'static str>, input_builder: impl Fn(&str) -> Box> + Clone + Send + 'static, @@ -147,7 +148,7 @@ fn test_type_registry() { // Dummy input implementation for the test struct DummyInput; - impl ActivityInput for DummyInput { + impl ActivityInput for DummyInput { fn read(&self) -> Result, feo_com::interface::Error> { todo!() } diff --git a/src/feo/src/recording/transcoder.rs b/src/feo/src/recording/transcoder.rs index d2bdf06..b28278e 100644 --- a/src/feo/src/recording/transcoder.rs +++ b/src/feo/src/recording/transcoder.rs @@ -17,16 +17,18 @@ use alloc::boxed::Box; use alloc::string::String; use core::ops::Deref as _; use feo_com::interface::ActivityInput; +use score_log::fmt::ScoreDebug; +use score_log::info; use serde::Serialize; /// Transcode data of the given type from com layer representation to recording serialization -pub(crate) struct RecordingTranscoder { +pub(crate) struct RecordingTranscoder { input: Box>, topic: String, type_name: String, } -impl RecordingTranscoder { +impl RecordingTranscoder { /// Create a transcoder reading from the given com layer topic pub fn build( input_builder: impl Fn(&str) -> Box> + Send, @@ -46,7 +48,7 @@ impl ComRecTranscoder +impl ComRecTranscoder for RecordingTranscoder { fn buffer_size(&self) -> usize { diff --git a/src/feo/src/scheduler.rs b/src/feo/src/scheduler.rs index c49115f..0fd4ffd 100644 --- a/src/feo/src/scheduler.rs +++ b/src/feo/src/scheduler.rs @@ -13,6 +13,7 @@ //! Global activity scheduler +use crate::debug_fmt::ScoreDebugBTreeSet; use crate::error::Error; use crate::ids::{ActivityId, AgentId}; use crate::signalling::common::interface::ConnectScheduler; @@ -22,8 +23,8 @@ use alloc::sync::Arc; use alloc::vec::Vec; use alloc::{boxed::Box, collections::BTreeSet}; use core::sync::atomic::{AtomicBool, Ordering}; -use feo_log::{debug, error, info, trace}; use feo_time::Instant; +use score_log::{debug, error, info, trace}; use std::collections::HashMap; use std::thread; @@ -36,9 +37,9 @@ pub(crate) struct Scheduler { /// Target duration of a task chain cycle cycle_time: feo_time::Duration, /// Timeout of receive function - receive_timeout: core::time::Duration, + receive_timeout: feo_time::Duration, /// Timeout for waiting on activities to become ready during startup. - startup_timeout: core::time::Duration, + startup_timeout: feo_time::Duration, /// For each activity: list of activities it depends on activity_depends: HashMap>, /// Map keeping track of activity states @@ -60,8 +61,8 @@ impl Scheduler { pub(crate) fn new( agent_id: AgentId, feo_cycle_time: feo_time::Duration, - receive_timeout: core::time::Duration, - startup_timeout: core::time::Duration, + receive_timeout: feo_time::Duration, + startup_timeout: feo_time::Duration, activity_depends: HashMap>, connector: Box, recorder_ids: Vec, @@ -175,7 +176,7 @@ impl Scheduler { self.record_task_chain_end().unwrap(); self.wait_recorders_ready().unwrap(); let flush_duration = start_flush.elapsed(); - trace!("Flushing recorders took {flush_duration:?}"); + trace!("Flushing recorders took {:?}", flush_duration); let task_chain_duration = task_chain_start.elapsed(); @@ -185,12 +186,15 @@ impl Scheduler { let time_left = self.cycle_time.saturating_sub(task_chain_duration); if time_left.is_zero() { error!( - "Finished task chain after {task_chain_duration:?}. Expected to be less than {:?}", - self.cycle_time + "Finished task chain after {:?}. Expected to be less than {:?}", + task_chain_duration, self.cycle_time ); } else { - debug!("Finished task chain after {task_chain_duration:?}. Sleeping for {time_left:?}"); - thread::sleep(time_left); + debug!( + "Finished task chain after {:?}. Sleeping for {:?}", + task_chain_duration, time_left + ); + thread::sleep(time_left.into()); } // Check for an external shutdown request (e.g., from Ctrl-C). @@ -281,7 +285,7 @@ impl Scheduler { // 2. Send a shutdown signal to only the started activities. info!( "Sending Shutdown signal to started activities: {:?}", - started_activities + ScoreDebugBTreeSet(&started_activities) ); for activity_id in &started_activities { Self::shutdown_activity(activity_id, &self.recorder_ids, &mut self.connector) @@ -291,7 +295,10 @@ impl Scheduler { // 3. Wait for confirmation from the activities that were told to shut down. // A worker sends a `Ready` signal after completing its shutdown. let mut pending_shutdown_ack = started_activities; - info!("Waiting for shutdown confirmation from: {:?}", pending_shutdown_ack); + info!( + "Waiting for shutdown confirmation from: {:?}", + ScoreDebugBTreeSet(&pending_shutdown_ack) + ); let shutdown_timeout = self.receive_timeout * (pending_shutdown_ack.len() as u32 + 2); let start = Instant::now(); @@ -300,7 +307,7 @@ impl Scheduler { if start.elapsed() > shutdown_timeout { error!( "Timeout waiting for shutdown confirmation. Still waiting for: {:?}", - pending_shutdown_ack + ScoreDebugBTreeSet(&pending_shutdown_ack) ); break; } @@ -348,15 +355,18 @@ impl Scheduler { return; } - info!("Waiting for TerminateAck from agents: {:?}", pending_agent_acks); + info!( + "Waiting for TerminateAck from agents: {}", + ScoreDebugBTreeSet(&pending_agent_acks) + ); let agent_ack_timeout = self.receive_timeout * (pending_agent_acks.len() as u32 + 4); let start = Instant::now(); while !pending_agent_acks.is_empty() { if start.elapsed() > agent_ack_timeout { error!( - "Timeout waiting for TerminateAck. Still waiting for: {:?}", - pending_agent_acks + "Timeout waiting for TerminateAck. Still waiting for: {}", + ScoreDebugBTreeSet(&pending_agent_acks) ); break; } @@ -410,7 +420,7 @@ impl Scheduler { continue; }, Some(other) => { - error!("Received unexpected signal {other:?} while waiting for ready signal"); + error!("Received unexpected signal {:?} while waiting for ready signal", other); }, } }; @@ -465,11 +475,14 @@ impl Scheduler { if let Some(value) = self.recorders_ready.get_mut(&id) { *value = true; } else { - error!("Received unexpected id {id} in recorder ready signal"); + error!("Received unexpected id {} in recorder ready signal", id); } }, Some(other) => { - error!("Received unexpected signal {other} while waiting for recorder ready signal"); + error!( + "Received unexpected signal {} while waiting for recorder ready signal", + other + ); }, } } diff --git a/src/feo/src/signalling/common/interface.rs b/src/feo/src/signalling/common/interface.rs index 315b358..b5dd984 100644 --- a/src/feo/src/signalling/common/interface.rs +++ b/src/feo/src/signalling/common/interface.rs @@ -15,7 +15,7 @@ use crate::error::Error; use crate::ids::{ActivityId, AgentId}; use crate::signalling::common::signals::Signal; use alloc::vec::Vec; -use core::time::Duration; +use feo_time::Duration; use std::thread::JoinHandle; /// Trait for the connector of a scheduler diff --git a/src/feo/src/signalling/common/mpsc/endpoint.rs b/src/feo/src/signalling/common/mpsc/endpoint.rs index 46784d2..1810c9b 100644 --- a/src/feo/src/signalling/common/mpsc/endpoint.rs +++ b/src/feo/src/signalling/common/mpsc/endpoint.rs @@ -13,13 +13,14 @@ //! Basic components for mpsc channel signalling protocol +use crate::debug_fmt::ScoreDebugHashSet; use crate::error::Error; use crate::ids::ChannelId; use crate::signalling::common::mpsc::primitives::{channel, Receiver, Sender}; use crate::signalling::common::signals::Signal; -use core::time::Duration; -use feo_log::{debug, error, trace}; +use feo_time::Duration; use feo_time::Instant; +use score_log::{debug, error, trace, ScoreDebug}; use std::collections::{HashMap, HashSet}; pub(crate) struct ProtocolSender { @@ -71,7 +72,7 @@ impl ProtocolReceiver { self.channel_id = match protocol_signal { Some(ProtocolSignal::Connect(c)) => Some(c), Some(other) => { - error!("Received unexpected protocol signal {other:?}"); + error!("Received unexpected protocol signal {:?}", other); continue; }, None => return Err(Error::Timeout(timeout, "connecting sender")), @@ -118,25 +119,28 @@ impl ProtocolMultiReceiver { let mut missing = self.channel_ids.clone(); let start = Instant::now(); while !missing.is_empty() && start.elapsed() < timeout { - trace!("Connecting, missing channels {missing:?}"); + trace!("Connecting, missing channels {:?}", ScoreDebugHashSet(&missing)); let protocol_signal = self.receiver.receive(timeout)?; let channel_id = match protocol_signal { Some(ProtocolSignal::Connect(c)) => c, Some(other) => { - error!("Received unexpected protocol signal {other:?}"); + error!("Received unexpected protocol signal {:?}", other); continue; }, None => return Err(Error::Timeout(timeout, "connecting senders")), }; if !self.channel_ids.contains(&channel_id) { - error!("Received connect signal from unexpected channel {channel_id:?}"); + error!("Received connect signal from unexpected channel {:?}", channel_id); continue; } let is_new = missing.remove(&channel_id); if !is_new { - error!("Ignoring connect signal from previously connected channel {channel_id:?}"); + error!( + "Ignoring connect signal from previously connected channel {:?}", + channel_id + ); } else { - trace!("Sender channel connected: {channel_id:?}"); + trace!("Sender channel connected: {:?}", channel_id); } } self.connected = true; @@ -190,7 +194,7 @@ impl ProtocolMultiSender { } /// Internal input signal specific to this signalling implementation -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, ScoreDebug)] pub(crate) enum ProtocolSignal { Core(Signal), Connect(ChannelId), diff --git a/src/feo/src/signalling/common/mpsc/primitives.rs b/src/feo/src/signalling/common/mpsc/primitives.rs index 61fde73..b9e2ed6 100644 --- a/src/feo/src/signalling/common/mpsc/primitives.rs +++ b/src/feo/src/signalling/common/mpsc/primitives.rs @@ -15,7 +15,7 @@ use crate::error::Error; use core::fmt; -use core::time::Duration; +use feo_time::Duration; use std::sync::mpsc; use std::sync::mpsc::RecvTimeoutError; @@ -38,7 +38,7 @@ impl Receiver { } pub fn receive(&mut self, timeout: Duration) -> Result, Error> { - match self.receiver.recv_timeout(timeout) { + match self.receiver.recv_timeout(timeout.into()) { Ok(v) => Ok(Some(v)), Err(err) => match err { RecvTimeoutError::Timeout => Ok(None), diff --git a/src/feo/src/signalling/common/mpsc/worker.rs b/src/feo/src/signalling/common/mpsc/worker.rs index a39e322..37dcd0a 100644 --- a/src/feo/src/signalling/common/mpsc/worker.rs +++ b/src/feo/src/signalling/common/mpsc/worker.rs @@ -15,7 +15,7 @@ use crate::error::Error; use crate::signalling::common::interface::ConnectWorker; use crate::signalling::common::mpsc::endpoint::{ProtocolReceiver, ProtocolSender, ProtocolSignal}; use crate::signalling::common::signals::Signal; -use core::time::Duration; +use feo_time::Duration; pub(crate) struct WorkerConnector { receiver: ProtocolReceiver, diff --git a/src/feo/src/signalling/common/signals.rs b/src/feo/src/signalling/common/signals.rs index 4ac8743..28c694c 100644 --- a/src/feo/src/signalling/common/signals.rs +++ b/src/feo/src/signalling/common/signals.rs @@ -19,12 +19,13 @@ use crate::timestamp::{SyncInfo, Timestamp}; use core::fmt::Display; #[cfg(feature = "recording")] use postcard::experimental::max_size::MaxSize; +use score_log::ScoreDebug; #[cfg(feature = "recording")] use serde::{Deserialize, Serialize}; /// Signal types sent between threads or processes #[cfg_attr(feature = "recording", derive(Serialize, Deserialize, MaxSize))] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, ScoreDebug)] pub enum Signal { // Signal sent from the primary agent to each secondary agent containing synchronization info StartupSync(SyncInfo), diff --git a/src/feo/src/signalling/common/socket/client.rs b/src/feo/src/signalling/common/socket/client.rs index 2cc8b99..6060b26 100644 --- a/src/feo/src/signalling/common/socket/client.rs +++ b/src/feo/src/signalling/common/socket/client.rs @@ -14,11 +14,13 @@ use crate::error::Error; use crate::signalling::common::socket::connection::Connection; use crate::signalling::common::socket::{FdExt, ProtocolSignal}; +use alloc::format; use core::net::SocketAddr; -use core::time::Duration; -use feo_log::{info, trace}; +use feo_time::Duration; +use feo_tracing::ScoreDebugIoError; use mio::net::{TcpStream, UnixStream}; use mio::{Events, Interest, Poll, Token}; +use score_log::{info, trace}; use std::path::Path; use std::{io, thread}; @@ -51,15 +53,15 @@ impl SocketClient { break TcpStream::from_std(stream); } - thread::sleep(Duration::from_millis(300)); + thread::sleep(Duration::from_millis(300).into()); }; - info!("Successfully connected to {address:?}"); + info!("Successfully connected to {}", format!("{address:?}")); stream.set_nodelay(true).unwrap(); let mut connection = Connection::::new(stream); for signal in connect_signals { connection.send(&signal).unwrap(); - trace!("Sent message {signal:?}"); + trace!("Sent message {:?}", signal); } let poll = Poll::new().unwrap(); @@ -79,14 +81,14 @@ impl SocketClient { break stream; } - thread::sleep(Duration::from_millis(300)); + thread::sleep(Duration::from_millis(300).into()); }; - info!("Successfully connected to {path:?}"); + info!("Successfully connected to {:?}", path.to_str().expect("invalid path")); let mut connection = Connection::::new(stream); for signal in connect_signals { connection.send(&signal).unwrap(); - trace!("Sent message {signal:?}"); + trace!("Sent message {:?}", signal); } let poll = Poll::new().unwrap(); @@ -115,7 +117,7 @@ where } } - self.poll.poll(events, Some(timeout)).unwrap(); + self.poll.poll(events, Some(timeout.into())).unwrap(); for event in events.iter() { if event.token() == CLIENT_TOKEN { @@ -138,6 +140,6 @@ where pub(crate) fn send(&mut self, msg: &ProtocolSignal) -> Result<(), Error> { self.connection .send(msg) - .map_err(|e| Error::Io((e, "failed to send on connection"))) + .map_err(|e| Error::Io((ScoreDebugIoError(e), "failed to send on connection"))) } } diff --git a/src/feo/src/signalling/common/socket/connection.rs b/src/feo/src/signalling/common/socket/connection.rs index da447df..710179b 100644 --- a/src/feo/src/signalling/common/socket/connection.rs +++ b/src/feo/src/signalling/common/socket/connection.rs @@ -13,8 +13,8 @@ use crate::signalling::common::socket::EncodeDecode; use core::marker::PhantomData; -use feo_log::trace; use mio::net::{TcpStream, UnixStream}; +use score_log::trace; use std::io::{self, Cursor}; /// Size of the buffer within a connection @@ -143,7 +143,7 @@ where return Err(io::ErrorKind::ConnectionReset.into()); }, Ok(n) => { - trace!("Read {n} bytes"); + trace!("Read {} bytes", n); self.recv_end += n; self.buffer_readable = true; diff --git a/src/feo/src/signalling/common/socket/mod.rs b/src/feo/src/signalling/common/socket/mod.rs index 5ef063a..4f28e6c 100644 --- a/src/feo/src/signalling/common/socket/mod.rs +++ b/src/feo/src/signalling/common/socket/mod.rs @@ -17,6 +17,7 @@ use crate::error::ActivityError; use crate::ids::{ActivityId, AgentId, ChannelId, RelayId, WorkerId}; use crate::signalling::common::signals::Signal; use crate::timestamp::{SyncInfo, Timestamp}; +use score_log::ScoreDebug; use std::io::{self, Write}; use std::os::fd::AsRawFd; @@ -72,7 +73,7 @@ where /// /// This type wraps the core [Signal] type and adds signal variants /// which are only needed by this particular implementation. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, ScoreDebug)] pub(crate) enum ProtocolSignal { /// Core [Signal] as known to schedulers, workers and recorders Core(Signal), diff --git a/src/feo/src/signalling/common/socket/server.rs b/src/feo/src/signalling/common/socket/server.rs index d1ae0fa..4fc707d 100644 --- a/src/feo/src/signalling/common/socket/server.rs +++ b/src/feo/src/signalling/common/socket/server.rs @@ -11,14 +11,15 @@ // SPDX-License-Identifier: Apache-2.0 // ******************************************************************************* +use crate::debug_fmt::ScoreDebugDebug; use crate::signalling::common::socket::connection::Connection; use crate::signalling::common::socket::{EncodeDecode, ProtocolSignal}; use core::fmt; use core::net::SocketAddr; -use core::time::Duration; -use feo_log::{debug, info, warn}; +use feo_time::Duration; use mio::net::{TcpListener, TcpStream, UnixListener, UnixStream}; use mio::{event, Events, Interest, Poll, Token}; +use score_log::{debug, info, warn}; use std::collections::HashMap; use std::fs; use std::io; @@ -68,7 +69,7 @@ where // There was no readable connection -> poll loop { - match self.poll.poll(events, Some(timeout)) { + match self.poll.poll(events, Some(timeout.into())) { Err(e) if e.kind() == std::io::ErrorKind::Interrupted => { // ignore system interrupts }, @@ -83,7 +84,7 @@ where self.accepted_connections.get_mut(&token).unwrap().set_stream_readable(); }, other => { - warn!("Received readiness event for unknown token {other:?}"); + warn!("Received readiness event for unknown token {}", other.0); }, } } @@ -120,7 +121,7 @@ where self.accepted_connections.insert(token, connection); - info!("Accepted connection from {peer_addr:?}"); + info!("Accepted connection from {:?}", ScoreDebugDebug::<_, 256>(&peer_addr)); }, Err(err) if err.kind() == io::ErrorKind::WouldBlock => break, Err(err) => panic!("failed to accept connection: {err}"), @@ -180,9 +181,9 @@ impl SocketServer { // Check for and remove stale socket file // This is a workaround until the shutdown is defined in FEO if path.exists() { - debug!("Removing stale socket file {}", path.display()); + debug!("Removing stale socket file {:?}", path.to_str().expect("invalid path")); fs::remove_file(path) - .unwrap_or_else(|e| panic!("failed to remove stale socket file {}: {e}", path.display())); + .unwrap_or_else(|e| panic!("failed to remove stale socket file {}: {e}", path.to_string_lossy())); } let listener = UnixListener::bind(path).unwrap(); diff --git a/src/feo/src/signalling/direct/mpsc/scheduler.rs b/src/feo/src/signalling/direct/mpsc/scheduler.rs index e0d9d3f..d592713 100644 --- a/src/feo/src/signalling/direct/mpsc/scheduler.rs +++ b/src/feo/src/signalling/direct/mpsc/scheduler.rs @@ -22,7 +22,7 @@ use crate::signalling::common::mpsc::worker::WorkerConnector; use crate::signalling::common::mpsc::WorkerConnectorBuilder; use crate::signalling::common::signals::Signal; use alloc::boxed::Box; -use core::time::Duration; +use feo_time::Duration; use std::collections::{HashMap, HashSet}; pub(crate) struct SchedulerConnector { diff --git a/src/feo/src/signalling/direct/recorder.rs b/src/feo/src/signalling/direct/recorder.rs index bb09de7..7832b5c 100644 --- a/src/feo/src/signalling/direct/recorder.rs +++ b/src/feo/src/signalling/direct/recorder.rs @@ -18,10 +18,10 @@ use crate::signalling::common::signals::Signal; use crate::signalling::common::socket::client::{SocketClient, TcpClient, UnixClient}; use crate::signalling::common::socket::ProtocolSignal; use core::net::SocketAddr; -use core::time::Duration; -use feo_log::warn; +use feo_time::Duration; use mio::net::{TcpStream, UnixStream}; use mio::Events; +use score_log::warn; use std::io; use std::path::PathBuf; @@ -59,7 +59,7 @@ where { Ok(Some(ProtocolSignal::Core(signal))) => Ok(Some(signal)), Ok(Some(signal)) => { - warn!("Received unexpected signal {signal:?}"); + warn!("Received unexpected signal {:?}", signal); Ok(None) }, Ok(None) => Ok(None), diff --git a/src/feo/src/signalling/direct/scheduler.rs b/src/feo/src/signalling/direct/scheduler.rs index f0cfaa3..f235886 100644 --- a/src/feo/src/signalling/direct/scheduler.rs +++ b/src/feo/src/signalling/direct/scheduler.rs @@ -20,11 +20,12 @@ use crate::signalling::common::socket::ProtocolSignal; use crate::timestamp::sync_info; use alloc::vec::Vec; use core::net::SocketAddr; -use core::time::Duration; -use feo_log::warn; +use feo_time::Duration; use feo_time::Instant; +use feo_tracing::ScoreDebugIoError; use mio::net::{TcpListener, UnixListener}; use mio::{Events, Token}; +use score_log::warn; use std::collections::{HashMap, HashSet}; use std::path::Path; @@ -136,7 +137,10 @@ where while !missing_activities.is_empty() || !missing_recorders.is_empty() { let elapsed = start_time.elapsed(); if elapsed >= self.connection_timeout { - return Err(Error::Io((std::io::ErrorKind::TimedOut.into(), "CONNECTION_TIMEOUT"))); + return Err(Error::Io(( + ScoreDebugIoError(std::io::ErrorKind::TimedOut.into()), + "CONNECTION_TIMEOUT", + ))); } let remaining_timeout = self.connection_timeout.saturating_sub(elapsed); // Wait for a new connection, but no longer than the remaining overall timeout. @@ -151,7 +155,10 @@ where missing_recorders.remove(&agent_id); }, other => { - warn!("received unexpected signal {other:?} from connection with token {token:?}"); + warn!( + "received unexpected signal {:?} from connection with token {}", + other, token.0 + ); }, } } @@ -171,7 +178,7 @@ where { self.server .send(token, &ProtocolSignal::Core(signal)) - .map_err(|e| Error::Io((e, "failed to send")))?; + .map_err(|e| Error::Io((ScoreDebugIoError(e), "failed to send")))?; } Ok(()) @@ -206,7 +213,7 @@ where .unwrap_or_else(|| panic!("failed to find token for activity ID {activity_id}")); self.server .send(token, &ProtocolSignal::Core(*signal)) - .map_err(|e| Error::Io((e, "failed to send"))) + .map_err(|e| Error::Io((ScoreDebugIoError(e), "failed to send"))) } fn send_to_recorder(&mut self, recorder_id: AgentId, signal: &Signal) -> Result<(), Error> { @@ -216,7 +223,7 @@ where .unwrap_or_else(|| panic!("failed to find token for recorder ID {recorder_id}")); self.server .send(token, &ProtocolSignal::Core(*signal)) - .map_err(|e| Error::Io((e, "failed to send"))) + .map_err(|e| Error::Io((ScoreDebugIoError(e), "failed to send"))) } fn broadcast_terminate(&mut self, signal: &Signal) -> Result<(), Error> { let protocol_signal = ProtocolSignal::Core(*signal); diff --git a/src/feo/src/signalling/direct/worker.rs b/src/feo/src/signalling/direct/worker.rs index fa41dc1..5ff760c 100644 --- a/src/feo/src/signalling/direct/worker.rs +++ b/src/feo/src/signalling/direct/worker.rs @@ -19,7 +19,7 @@ use crate::signalling::common::socket::client::{SocketClient, TcpClient, UnixCli use crate::signalling::common::socket::ProtocolSignal; use alloc::vec::Vec; use core::net::SocketAddr; -use core::time::Duration; +use feo_time::Duration; use mio::net::{TcpStream, UnixStream}; use mio::Events; use std::io; diff --git a/src/feo/src/signalling/relayed/connectors/recorder.rs b/src/feo/src/signalling/relayed/connectors/recorder.rs index d560ffc..a88a860 100644 --- a/src/feo/src/signalling/relayed/connectors/recorder.rs +++ b/src/feo/src/signalling/relayed/connectors/recorder.rs @@ -15,7 +15,7 @@ use crate::error::Error; use crate::signalling::common::interface::ConnectRecorder; use crate::signalling::common::signals::Signal; use crate::signalling::relayed::interface::{IsChannel, ProtocolRecv, ProtocolSend}; -use core::time::Duration; +use feo_time::Duration; /// Connector for a recorder pub(crate) struct RecorderConnector { diff --git a/src/feo/src/signalling/relayed/connectors/relays.rs b/src/feo/src/signalling/relayed/connectors/relays.rs index 2961825..b9931fb 100644 --- a/src/feo/src/signalling/relayed/connectors/relays.rs +++ b/src/feo/src/signalling/relayed/connectors/relays.rs @@ -21,9 +21,9 @@ use crate::signalling::relayed::interface::{ }; use crate::timestamp; use crate::timestamp::sync_info; -use core::time::Duration; -use feo_log::{debug, error, trace}; +use feo_time::Duration; use feo_time::Instant; +use score_log::{debug, error, trace}; use std::collections::{HashMap, HashSet}; use std::{io::ErrorKind, thread}; @@ -85,7 +85,7 @@ impl PrimaryReceiveRelay { debug!("[PrimaryReceiveRelay]Channel closed. Exiting."); return Ok(()); }, - Err(Error::Io((e, _))) if e.kind() == ErrorKind::ConnectionReset => { + Err(Error::Io((e, _))) if e.0.kind() == ErrorKind::ConnectionReset => { // A single client disconnected. This is expected during shutdown. // Log it and continue listening for other clients. debug!("[PrimaryReceiveRelay]A remote agent connection was reset."); @@ -184,7 +184,7 @@ impl SecondaryReceiveRelay { Ok(None) }, Err(Error::ChannelClosed) => Err(Error::ChannelClosed), - Err(Error::Io((e, _))) if e.kind() == ErrorKind::ConnectionReset => { + Err(Error::Io((e, _))) if e.0.kind() == ErrorKind::ConnectionReset => { debug!("SecondaryReceiveRelay detected connection to primary reset (expected during shutdown)"); Err(Error::Io((e, "connection reset"))) }, @@ -233,7 +233,7 @@ impl SecondaryReceiveRelay { let sync_info = match protocol_signal.try_into() { Ok(Signal::StartupSync(s)) => s, Ok(_) | Err(_) => { - error!("[SecondaryReceiveRelay]Unexpected signal {protocol_signal:?}"); + error!("[SecondaryReceiveRelay]Unexpected signal {:?}", protocol_signal); continue; }, }; @@ -254,7 +254,7 @@ impl SecondaryReceiveRelay { debug!("[SecondaryReceiveRelay]Connection to primary lost. Initiating self-shutdown."); return; // Exit the relay thread. The workers will detect the closed channel. }, - Err(Error::Io((e, _))) if e.kind() == ErrorKind::ConnectionReset => { + Err(Error::Io((e, _))) if e.0.kind() == ErrorKind::ConnectionReset => { debug!( "[SecondaryReceiveRelay]Connection to primary was reset (expected during shutdown). Exiting." ); @@ -269,7 +269,10 @@ impl SecondaryReceiveRelay { let core_signal: Signal = match protocol_signal.try_into() { Ok(signal) => signal, Err(_) => { - error!("[SecondaryReceiveRelay]Received unexpected signal {protocol_signal:?}"); + error!( + "[SecondaryReceiveRelay]Received unexpected signal {:?}", + protocol_signal + ); continue; }, }; @@ -280,7 +283,10 @@ impl SecondaryReceiveRelay { // This is a targeted signal for a specific activity. // Lookup corresponding worker id. let Some(worker_id) = activity_worker_map.get(&act_id) else { - error!("[SecondaryReceiveRelay]Received unexpected activity id {act_id:?} in {core_signal:?}"); + error!( + "[SecondaryReceiveRelay]Received unexpected activity id {:?} in {:?}", + act_id, core_signal + ); continue; }; @@ -418,7 +424,7 @@ impl SecondarySendRelay { let core_signal: Signal = match signal.try_into() { Ok(signal) => signal, Err(_) => { - error!("[SecondarySendRelay]Received unexpected signal {signal:?}"); + error!("[SecondarySendRelay]Received unexpected signal {:?}", signal); continue; }, }; diff --git a/src/feo/src/signalling/relayed/connectors/scheduler.rs b/src/feo/src/signalling/relayed/connectors/scheduler.rs index 6ded8ec..048a6bb 100644 --- a/src/feo/src/signalling/relayed/connectors/scheduler.rs +++ b/src/feo/src/signalling/relayed/connectors/scheduler.rs @@ -20,8 +20,8 @@ use crate::signalling::common::signals::Signal; use crate::signalling::relayed::connectors::relays::{PrimaryReceiveRelay, PrimarySendRelay}; use crate::signalling::relayed::interface::{Builder, IsChannel, ProtocolMultiRecv, ProtocolMultiSend}; use alloc::{collections::BTreeSet, vec::Vec}; -use core::time::Duration; -use feo_log::debug; +use feo_time::Duration; +use score_log::debug; use std::collections::{HashMap, HashSet}; use std::thread::JoinHandle; diff --git a/src/feo/src/signalling/relayed/connectors/secondary.rs b/src/feo/src/signalling/relayed/connectors/secondary.rs index a3356e2..0ea481c 100644 --- a/src/feo/src/signalling/relayed/connectors/secondary.rs +++ b/src/feo/src/signalling/relayed/connectors/secondary.rs @@ -14,7 +14,7 @@ use crate::signalling::relayed::connectors::relays::{SecondaryReceiveRelay, SecondarySendRelay}; use crate::signalling::relayed::interface::IsChannel; use crate::signalling::relayed::ConnectSecondary; -use feo_log::debug; +use score_log::debug; pub(crate) struct SecondaryConnector { local_to_ipc_relay: SecondarySendRelay, diff --git a/src/feo/src/signalling/relayed/interface.rs b/src/feo/src/signalling/relayed/interface.rs index d1bbc15..9b9c690 100644 --- a/src/feo/src/signalling/relayed/interface.rs +++ b/src/feo/src/signalling/relayed/interface.rs @@ -16,13 +16,14 @@ use crate::ids::ChannelId; use crate::signalling::common::signals::Signal; use alloc::boxed::Box; use core::fmt::Debug; -use core::time::Duration; +use feo_time::Duration; +use score_log::fmt::ScoreDebug; pub(crate) type Builder = Box T + Send>; /// Collection of types needed to implement a signalling channel pub(crate) trait IsChannel: 'static { - type ProtocolSignal: From + TryInto + Copy + Debug; + type ProtocolSignal: From + TryInto + Copy + Debug + ScoreDebug; type Sender: ProtocolSend; type Receiver: ProtocolRecv; type MultiSender: ProtocolMultiSend; @@ -30,7 +31,7 @@ pub(crate) trait IsChannel: 'static { } pub(crate) trait ProtocolSend { - type ProtocolSignal: From + TryInto + Copy + Debug; + type ProtocolSignal: From + TryInto + Copy + Debug + ScoreDebug; fn send(&mut self, signal: Self::ProtocolSignal) -> Result<(), Error>; @@ -38,7 +39,7 @@ pub(crate) trait ProtocolSend { } pub(crate) trait ProtocolRecv { - type ProtocolSignal: From + TryInto + Copy + Debug; + type ProtocolSignal: From + TryInto + Copy + Debug + ScoreDebug; fn receive(&mut self, timeout: Duration) -> Result, Error>; @@ -46,7 +47,7 @@ pub(crate) trait ProtocolRecv { } pub(crate) trait ProtocolMultiRecv { - type ProtocolSignal: From + TryInto + Copy + Debug; + type ProtocolSignal: From + TryInto + Copy + Debug + ScoreDebug; fn receive(&mut self, timeout: Duration) -> Result, Error>; @@ -54,7 +55,7 @@ pub(crate) trait ProtocolMultiRecv { } pub(crate) trait ProtocolMultiSend { - type ProtocolSignal: From + TryInto + Copy + Debug; + type ProtocolSignal: From + TryInto + Copy + Debug + ScoreDebug; fn send(&mut self, channel_id: ChannelId, signal: Self::ProtocolSignal) -> Result<(), Error>; /// Broadcast a signal to all channels diff --git a/src/feo/src/signalling/relayed/mpsc/endpoint.rs b/src/feo/src/signalling/relayed/mpsc/endpoint.rs index 99798b4..126e1f2 100644 --- a/src/feo/src/signalling/relayed/mpsc/endpoint.rs +++ b/src/feo/src/signalling/relayed/mpsc/endpoint.rs @@ -22,7 +22,7 @@ pub(crate) use crate::signalling::common::mpsc::endpoint::{ }; use crate::signalling::common::signals::Signal; use crate::signalling::relayed; -use core::time::Duration; +use feo_time::Duration; impl relayed::interface::ProtocolSend for ProtocolSender { type ProtocolSignal = ProtocolSignal; diff --git a/src/feo/src/signalling/relayed/sockets/endpoint.rs b/src/feo/src/signalling/relayed/sockets/endpoint.rs index b9d0699..13b8878 100644 --- a/src/feo/src/signalling/relayed/sockets/endpoint.rs +++ b/src/feo/src/signalling/relayed/sockets/endpoint.rs @@ -19,13 +19,14 @@ use crate::signalling::common::signals::Signal; use crate::signalling::common::socket::client::{TcpClient, UnixClient}; use crate::signalling::common::socket::server::{TcpServer, UnixServer}; // Re-use protocol signal definition from socket building blocks +use crate::debug_fmt::ScoreDebugHashSet; pub(crate) use crate::signalling::common::socket::ProtocolSignal; use crate::signalling::relayed; use core::net::SocketAddr; -use core::time::Duration; -use feo_log::{debug, error, trace, warn}; -use feo_time::Instant; +use feo_time::{Duration, Instant}; +use feo_tracing::ScoreDebugIoError; use mio::{Events, Token}; +use score_log::{debug, error, trace, warn}; use std::collections::{HashMap, HashSet}; use std::path::PathBuf; @@ -158,10 +159,13 @@ impl ProtocolMultiEndpoint { let deadline = Instant::now() + timeout; let mut missing_peers: HashSet = self.channel_ids.clone(); while !missing_peers.is_empty() { - trace!("Connecting missing channels {:?}", missing_peers); + trace!("Connecting missing channels {:?}", ScoreDebugHashSet(&missing_peers)); let time_left = deadline.saturating_duration_since(Instant::now()); if time_left.is_zero() { - return Err(Error::Io((std::io::ErrorKind::TimedOut.into(), "CONNECTION_TIMEOUT"))); + return Err(Error::Io(( + ScoreDebugIoError(std::io::ErrorKind::TimedOut.into()), + "CONNECTION_TIMEOUT", + ))); } // TODO: server to reject connections from unexpected peers if let Ok(Some((token, signal))) = server.receive(&mut self.events, time_left) { @@ -169,12 +173,12 @@ impl ProtocolMultiEndpoint { ProtocolSignal::ChannelHello(channel_id) => { self.channel_token_map.insert(channel_id, token); missing_peers.remove(&channel_id); - debug!("Channel connected {channel_id:?}"); + debug!("Channel connected {:?}", channel_id); }, other => { warn!( "Received unexpected signal {:?} from unknown token {:?} during connect", - other, token + other, token.0 ); }, } @@ -217,7 +221,7 @@ impl ProtocolMultiEndpoint { // Iterate over all known connection tokens and send the signal. for token in self.channel_token_map.values() { if let Err(e) = server.send(token, &signal) { - error!("Failed to broadcast to token {:?}: {:?}", token, e); + error!("Failed to broadcast to token {}: {:?}", token.0, e); } } Ok(()) diff --git a/src/feo/src/signalling/relayed/sockets_mpsc.rs b/src/feo/src/signalling/relayed/sockets_mpsc.rs index e5c202d..eb3c4f6 100644 --- a/src/feo/src/signalling/relayed/sockets_mpsc.rs +++ b/src/feo/src/signalling/relayed/sockets_mpsc.rs @@ -31,7 +31,7 @@ use crate::signalling::relayed::{mpsc, sockets}; use alloc::boxed::Box; use alloc::vec::Vec; use core::net::SocketAddr; -use core::time::Duration; +use feo_time::Duration; use std::collections::{HashMap, HashSet}; use std::path::PathBuf; diff --git a/src/feo/src/timestamp.rs b/src/feo/src/timestamp.rs index c097593..4e08a87 100644 --- a/src/feo/src/timestamp.rs +++ b/src/feo/src/timestamp.rs @@ -13,9 +13,10 @@ //! Timestamping module -use feo_time::Scaled; +use feo_time::{Duration, Scaled}; #[cfg(feature = "recording")] use postcard::experimental::max_size::MaxSize; +use score_log::ScoreDebug; #[cfg(feature = "recording")] use serde::{Deserialize, Serialize}; use std::sync::OnceLock; @@ -63,7 +64,7 @@ pub fn initialize_from(sync_info: SyncInfo) { let time_info_now = time_info_now(); // Calculate the startup time of the primary agent - let startup_time = std::time::SystemTime::UNIX_EPOCH + sync_info.since_epoch; + let startup_time = std::time::SystemTime::UNIX_EPOCH + sync_info.since_epoch.into(); // Calculate the time elapsed since the startup of the primary agent; // assumption is that system clocks are synchronized (but monotonic clocks can be unsynchronized). @@ -115,18 +116,20 @@ pub fn sync_info() -> SyncInfo { .systime .duration_since(std::time::UNIX_EPOCH) .expect("failed to obtain system time for synchronization"); - SyncInfo { since_epoch } + SyncInfo { + since_epoch: since_epoch.into(), + } } /// A timestamp: Duration since system startup #[cfg_attr(feature = "recording", derive(Serialize, Deserialize))] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, ScoreDebug)] pub struct Timestamp(pub feo_time::Duration); pub fn timestamp() -> Timestamp { // get real time duration since startup and scale it with feo-time speed factor let real_duration = std::time::Instant::now().duration_since(startup_instant()); - let feo_duration: feo_time::Duration = real_duration.scaled(); + let feo_duration: feo_time::Duration = Duration(real_duration).scaled(); Timestamp(feo_duration) } @@ -141,9 +144,9 @@ impl MaxSize for Timestamp { /// the duration since the EPOCH. That means, secondary agents synchronizing later based on /// that value might get affected by leap seconds occurring in between. #[cfg_attr(feature = "recording", derive(Serialize, Deserialize))] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, ScoreDebug)] pub struct SyncInfo { - since_epoch: core::time::Duration, + since_epoch: feo_time::Duration, } /// Return current system time and instant as a TimeInfo object @@ -195,7 +198,7 @@ impl From for SyncInfo { fn from(nanos: u128) -> SyncInfo { assert!(nanos <= u64::MAX.into(), "input value too large"); SyncInfo { - since_epoch: core::time::Duration::from_nanos(nanos as u64), + since_epoch: feo_time::Duration::from_nanos(nanos as u64), } } } @@ -203,7 +206,7 @@ impl From for SyncInfo { impl From for SyncInfo { fn from(nanos: u64) -> SyncInfo { SyncInfo { - since_epoch: core::time::Duration::from_nanos(nanos), + since_epoch: feo_time::Duration::from_nanos(nanos), } } } diff --git a/src/feo/src/topicspec.rs b/src/feo/src/topicspec.rs index b99def2..5af6b8d 100644 --- a/src/feo/src/topicspec.rs +++ b/src/feo/src/topicspec.rs @@ -21,6 +21,7 @@ use feo_com::interface::{ init_topic_primary, init_topic_secondary, ComBackendTopicPrimaryInitialization, ComBackendTopicSecondaryInitialization, Topic, TopicHandle, }; +use score_log::fmt::ScoreDebug; #[derive(Debug, Default, Clone, Copy, Eq, PartialEq)] /// Describes the direction of the data flow for one topic of one component @@ -45,7 +46,10 @@ pub struct TopicSpecification<'a> { } impl<'a> TopicSpecification<'a> { - pub fn new(topic: Topic<'a>, peers: Vec<(ActivityId, Direction)>) -> Self { + pub fn new( + topic: Topic<'a>, + peers: Vec<(ActivityId, Direction)>, + ) -> Self { let init_primary_fn = Box::new(init_topic_primary::); let init_secondary_fn = Box::new(init_topic_secondary::); Self { diff --git a/src/feo/src/worker/mod.rs b/src/feo/src/worker/mod.rs index adf3a5e..d51346c 100644 --- a/src/feo/src/worker/mod.rs +++ b/src/feo/src/worker/mod.rs @@ -20,9 +20,9 @@ use crate::signalling::common::interface::ConnectWorker; use crate::signalling::common::signals::Signal; use crate::timestamp; use alloc::boxed::Box; -use core::time::Duration; -use feo_log::{debug, error}; +use feo_time::Duration; use feo_time::Instant; +use score_log::{debug, error}; use std::collections::HashMap; use std::thread; @@ -108,7 +108,7 @@ impl Worker { debug!("Worker {} sent termination ack. Exiting.", self.id); // Linger for a moment to ensure TerminateAck has time to be sent // over the network before the thread exits and closes the socket. - thread::sleep(Duration::from_millis(100)); + thread::sleep(Duration::from_millis(100).into()); return Ok(()); // Graceful exit }, other => return Err(Error::UnexpectedSignal(other)), @@ -130,7 +130,7 @@ impl Worker { }, }; let elapsed = start.elapsed(); - debug!("Ran startup of activity {id:?} in {elapsed:?}"); + debug!("Ran startup of activity {:?} in {:?}", id, elapsed); self.connector.send_to_scheduler(&response_signal) }, Signal::Step((activity_id, _ts)) => { @@ -142,7 +142,7 @@ impl Worker { }, }; let elapsed = start.elapsed(); - debug!("Stepped activity {id:?} in {elapsed:?}"); + debug!("Stepped activity {:?} in {:?}", id, elapsed); self.connector.send_to_scheduler(&response_signal) }, Signal::Shutdown((activity_id, _ts)) => { @@ -154,7 +154,7 @@ impl Worker { }, }; let elapsed = start.elapsed(); - debug!("Ran shutdown of activity {id:?} in {elapsed:?}"); + debug!("Ran shutdown of activity {:?} in {}", id, elapsed); self.connector.send_to_scheduler(&response_signal) }, other => Err(Error::UnexpectedSignal(*other)), diff --git a/src/logd/BUILD.bazel b/src/logd/BUILD.bazel deleted file mode 100644 index fdecd88..0000000 --- a/src/logd/BUILD.bazel +++ /dev/null @@ -1,56 +0,0 @@ -# ******************************************************************************* -# Copyright (c) 2025 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License Version 2.0 which is available at -# https://www.apache.org/licenses/LICENSE-2.0 -# -# SPDX-License-Identifier: Apache-2.0 -# ******************************************************************************* - -load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library", "rust_test") - -rust_binary( - name = "logd", - srcs = [ - "src/main.rs", - ], - crate_name = "logd", - visibility = ["//visibility:public"], - deps = [ - ":liblogd", - "//src/feo-log:libfeo_log_rust", - "//src/feo-logger:libfeo_logger_rust", - "@score_crates//:anyhow", - "@score_crates//:tokio", - ], -) - -rust_library( - name = "liblogd", - srcs = [ - "src/input.rs", - "src/lib.rs", - ], - crate_name = "logd", - visibility = ["//visibility:public"], - deps = [ - "//src/feo-log:libfeo_log_rust", - "//src/feo-logger:libfeo_logger_rust", - "@score_crates//:anyhow", - "@score_crates//:async_stream", - "@score_crates//:bytes", - "@score_crates//:futures", - "@score_crates//:tokio", - "@score_crates//:tokio_seqpacket", - "@score_crates//:tokio_util", - ], -) - -rust_test( - name = "liblogd_test", - crate = ":liblogd", -) diff --git a/src/logd/Cargo.toml b/src/logd/Cargo.toml deleted file mode 100644 index bc766e9..0000000 --- a/src/logd/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "logd" -version = "0.1.0" -edition = "2024" - -[dependencies] -anyhow = { workspace = true } -async-stream = { workspace = true } -bytes = { workspace = true } -env_logger = { workspace = true } -feo-log = { workspace = true } -feo-logger = { workspace = true } -futures = { workspace = true } -tokio = { workspace = true } -tokio-seqpacket = { workspace = true } -tokio-util = { workspace = true } - -[dev-dependencies] -feo-time = { workspace = true } -socket2 = { workspace = true } diff --git a/src/logd/examples/client_packet.rs b/src/logd/examples/client_packet.rs deleted file mode 100644 index 2335644..0000000 --- a/src/logd/examples/client_packet.rs +++ /dev/null @@ -1,46 +0,0 @@ -// ******************************************************************************* -// Copyright (c) 2025 Contributors to the Eclipse Foundation -// -// See the NOTICE file(s) distributed with this work for additional -// information regarding copyright ownership. -// -// This program and the accompanying materials are made available under the -// terms of the Apache License Version 2.0 which is available at -// -// -// SPDX-License-Identifier: Apache-2.0 -// ******************************************************************************* - -//! Connect to logd and send a log record every second via seqpackets. - -use anyhow::Error; -use feo_log::Level; -use feo_logger::record::Record; -use feo_time::SystemTime; -use logd::{MAX_RECORD_SIZE, UNIX_PACKET_PATH}; -use socket2::{SockAddr, Socket}; -use std::{process, thread, time}; - -fn main() -> Result<(), Error> { - let socket = Socket::new(socket2::Domain::UNIX, socket2::Type::SEQPACKET, None)?; - socket.connect(&SockAddr::unix(UNIX_PACKET_PATH)?)?; - let mut buffer = Vec::with_capacity(MAX_RECORD_SIZE); - - loop { - let record = Record { - timestamp: SystemTime::now(), - level: Level::Info, - target: "some::module", - file: Some(file!()), - line: Some(line!()), - tgid: process::id(), - tid: 12, - args: b"hello again via seqpacket", - }; - buffer.clear(); - record.encode(&mut buffer)?; - socket.send(&buffer)?; - - thread::sleep(time::Duration::from_secs(1)); - } -} diff --git a/src/logd/examples/client_stream.rs b/src/logd/examples/client_stream.rs deleted file mode 100644 index c023d0e..0000000 --- a/src/logd/examples/client_stream.rs +++ /dev/null @@ -1,42 +0,0 @@ -// ******************************************************************************* -// Copyright (c) 2025 Contributors to the Eclipse Foundation -// -// See the NOTICE file(s) distributed with this work for additional -// information regarding copyright ownership. -// -// This program and the accompanying materials are made available under the -// terms of the Apache License Version 2.0 which is available at -// -// -// SPDX-License-Identifier: Apache-2.0 -// ******************************************************************************* - -//! This example demonstrates how to send log records to the logd daemon using a Unix stream socket. - -use anyhow::Error; -use logd::UNIX_STREAM_PATH; -use std::io::Write; -use std::os::unix::net; -use std::{thread, time}; - -fn main() -> Result<(), Error> { - let mut stream = net::UnixStream::connect(UNIX_STREAM_PATH)?; - - loop { - let record = feo_logger::record::Record { - timestamp: feo_time::SystemTime::now(), - level: feo_log::Level::Info, - target: "some::module", - file: Some(file!()), - line: Some(line!()), - tgid: std::process::id(), - tid: 19, - args: b"hello again unix via unix stream", - }; - let len = record.encoded_len() as u32; - stream.write_all(&len.to_be_bytes())?; - record.encode(&mut stream)?; - - thread::sleep(time::Duration::from_secs(1)); - } -} diff --git a/src/logd/src/input.rs b/src/logd/src/input.rs deleted file mode 100644 index 8a3376a..0000000 --- a/src/logd/src/input.rs +++ /dev/null @@ -1,141 +0,0 @@ -// ******************************************************************************* -// Copyright (c) 2025 Contributors to the Eclipse Foundation -// -// See the NOTICE file(s) distributed with this work for additional -// information regarding copyright ownership. -// -// This program and the accompanying materials are made available under the -// terms of the Apache License Version 2.0 which is available at -// -// -// SPDX-License-Identifier: Apache-2.0 -// ******************************************************************************* - -use crate::{RecordSender, MAX_RECORD_SIZE, UNIX_PACKET_PATH, UNIX_STREAM_PATH}; -use anyhow::{Context, Error}; -use async_stream::stream; -use bytes::BytesMut; -use feo_log::{debug, info, trace}; -use feo_logger::record::OwnedRecord; -use futures::{Stream, StreamExt}; -use std::path::Path; -use std::{fs, io}; -use tokio::{net, pin}; -use tokio_seqpacket::UnixSeqpacketListener; -use tokio_util::codec::{self, FramedRead, LengthDelimitedCodec}; - -pub async fn packet(record_sender: RecordSender) -> Result<(), Error> { - let path = UNIX_PACKET_PATH; - // Check if socket is present and remove if necessary - if Path::new(path).exists() { - debug!("Removing stale socket at {path:?}"); - fs::remove_file(path).with_context(|| format!("failed to remove {path}"))?; - } - - // Bind - info!("Binding to {path:?}"); - let mut listener = UnixSeqpacketListener::bind(path)?; - - // Listen - info!("Listening on {path:?}"); - loop { - let socket = listener.accept().await.context("failed to accept packet connection")?; - info!("Accepted seqpacket connection"); - let stream = stream! { - let mut buffer = [0u8; MAX_RECORD_SIZE]; - loop { - let len = socket.recv(&mut buffer).await?; - - // Connection closed? - if len == 0 { - break; - } - // No length prefix, so just decode the record. Seqpacket guarantees that the entire record is read. - - yield OwnedRecord::decode(&buffer[..len]); - } - }; - - // Spawn a new task to handle the connection - tokio::spawn(connection(stream, record_sender.clone())); - } -} - -/// Handle a connection. -pub async fn stream(record_sender: RecordSender) -> Result<(), Error> { - let path = UNIX_STREAM_PATH; - // Check if socket is present and remove if necessary - let socket = Path::new(path); - if socket.exists() { - debug!("Removing stale socket at {path:?}"); - fs::remove_file(socket).with_context(|| format!("failed to remove {path}"))?; - } - - // Bind - info!("Binding to {path:?}"); - let listener = net::UnixListener::bind(path).with_context(|| format!("failed to bind to {path}"))?; - - // Listen - info!("Listening on {:?}", path); - loop { - let (stream, addr) = listener.accept().await.context("failed to accept unix connection")?; - info!("Accepted connection from {addr:?}"); - let framed = FramedRead::with_capacity(stream, LogStreamCodec::default(), MAX_RECORD_SIZE); - - // Spawn a new task to handle the connection - tokio::spawn(connection(framed, record_sender.clone())); - } -} - -/// Handle a connection. -async fn connection>>(stream: S, record_sender: RecordSender) { - pin!(stream); - - loop { - let record = match stream.next().await { - Some(Ok(record)) => { - trace!("Received record: {:?}", record); - record - }, - Some(Err(e)) => { - info!("Failed to read socket: {:?}. Closing connection", e); - break; - }, - None => { - info!("Connection closed"); - break; - }, - }; - - record_sender.send(record).await.expect("channel closed"); - } -} - -/// A codec for decoding log records from a stream. The stream contains length-prefixed records. -/// The length is a u32 in big-endian format. -#[derive(Debug)] -pub struct LogStreamCodec { - inner: LengthDelimitedCodec, -} - -impl Default for LogStreamCodec { - fn default() -> Self { - let inner = LengthDelimitedCodec::builder() - .big_endian() - .length_field_type::() - .new_codec(); - Self { inner } - } -} - -impl codec::Decoder for LogStreamCodec { - type Item = OwnedRecord; - type Error = std::io::Error; - - fn decode(&mut self, src: &mut BytesMut) -> Result, Self::Error> { - self.inner - .decode(src)? - .map(|record| OwnedRecord::decode(&record)) - .transpose() - } -} diff --git a/src/logd/src/lib.rs b/src/logd/src/lib.rs deleted file mode 100644 index 0e9ee06..0000000 --- a/src/logd/src/lib.rs +++ /dev/null @@ -1,54 +0,0 @@ -// ******************************************************************************* -// Copyright (c) 2025 Contributors to the Eclipse Foundation -// -// See the NOTICE file(s) distributed with this work for additional -// information regarding copyright ownership. -// -// This program and the accompanying materials are made available under the -// terms of the Apache License Version 2.0 which is available at -// -// -// SPDX-License-Identifier: Apache-2.0 -// ******************************************************************************* - -//! Central trace collector - -use anyhow::{bail, Error}; -use feo_logger::fmt::format_owned; -use feo_logger::record::OwnedRecord; -use tokio::sync::mpsc; -use tokio::task::JoinSet; - -mod input; - -pub const MAX_RECORD_SIZE: usize = feo_logger::MAX_RECORD_SIZE; -const RECORD_CHANNEL_SIZE: usize = 100; -pub const UNIX_PACKET_PATH: &str = "/tmp/logd.sock"; -pub const UNIX_STREAM_PATH: &str = "/tmp/logd.stream.sock"; - -type RecordSender = mpsc::Sender; -type RecordReceiver = mpsc::Receiver; - -/// Start tasks for each input source. Start a task that processes records. -pub async fn run() -> Result<(), Error> { - let (record_sender, record_receiver) = mpsc::channel(RECORD_CHANNEL_SIZE); - let mut tasks = JoinSet::new(); - - tasks.spawn(process_records(record_receiver)); - tasks.spawn(input::stream(record_sender.clone())); - tasks.spawn(input::packet(record_sender)); - - let done = tasks.join_next().await.expect("no tasks to join"); - match done { - Ok(_) => unreachable!("tasks should never return"), - Err(e) => bail!(e), - } -} - -/// Process records. Placeholder - just print to stdout. -async fn process_records(mut record_receiver: RecordReceiver) -> Result<(), Error> { - while let Some(record) = record_receiver.recv().await { - format_owned(record, std::io::stdout())?; - } - unreachable!("record receiver closed"); -} diff --git a/src/logd/src/main.rs b/src/logd/src/main.rs deleted file mode 100644 index 5c83a65..0000000 --- a/src/logd/src/main.rs +++ /dev/null @@ -1,32 +0,0 @@ -// ******************************************************************************* -// Copyright (c) 2025 Contributors to the Eclipse Foundation -// -// See the NOTICE file(s) distributed with this work for additional -// information regarding copyright ownership. -// -// This program and the accompanying materials are made available under the -// terms of the Apache License Version 2.0 which is available at -// -// -// SPDX-License-Identifier: Apache-2.0 -// ******************************************************************************* - -//! Placeholder logging daemon that collects logs from various sources. Minimal effort implementation. - -use anyhow::Error; -use feo_log::{info, LevelFilter}; -use tokio::runtime; - -fn main() -> Result<(), Error> { - // Initialize the logger *without* the logd part logger. - feo_logger::init(LevelFilter::Debug, true, false); - - info!("Starting logd"); - - let logd = logd::run(); - - runtime::Builder::new_current_thread() - .enable_io() - .build()? - .block_on(logd) -} diff --git a/tests/rust/feo_tests/test_agent/BUILD b/tests/rust/feo_tests/test_agent/BUILD index 68f1c5e..6f02d07 100644 --- a/tests/rust/feo_tests/test_agent/BUILD +++ b/tests/rust/feo_tests/test_agent/BUILD @@ -36,10 +36,10 @@ rust_binary( deps = [ "//src/feo:libfeo_rust", "//src/feo-com:libfeo_com_rust", - "//src/feo-log:libfeo_log_rust", - "//src/feo-logger:libfeo_logger_rust", "//src/feo-time:libfeo_time_rust", "//src/feo-tracing:libfeo_tracing_rust", + "@score_baselibs_rust//src/log/score_log", + "@score_baselibs_rust//src/log/stdout_logger", "@score_crates//:clap", "@score_crates//:ipc_channel", "@score_crates//:libc", diff --git a/tests/rust/feo_tests/test_agent/Cargo.toml b/tests/rust/feo_tests/test_agent/Cargo.toml index 0dee994..4210695 100644 --- a/tests/rust/feo_tests/test_agent/Cargo.toml +++ b/tests/rust/feo_tests/test_agent/Cargo.toml @@ -10,8 +10,6 @@ com_linux_shm = [] [dependencies] feo = { workspace = true } feo-com = { workspace = true } -feo-log = { workspace = true } -feo-logger = { workspace = true } feo-cpp-macros = { workspace = true } feo-time = { workspace = true } feo-tracing = { workspace = true } diff --git a/tests/rust/feo_tests/test_agent/src/activities.rs b/tests/rust/feo_tests/test_agent/src/activities.rs index 3f307e6..daa7f28 100644 --- a/tests/rust/feo_tests/test_agent/src/activities.rs +++ b/tests/rust/feo_tests/test_agent/src/activities.rs @@ -18,9 +18,10 @@ use feo::activity::Activity; use feo::error::ActivityError; use feo::ids::ActivityId; use feo_com::interface::{ActivityInput, ActivityOutput}; -use feo_log::debug; use feo_tracing::instrument; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; +use score_log::debug; +use score_log::fmt::ScoreDebug; use std::ops::Deref; /// Sender activity @@ -118,7 +119,7 @@ impl Activity for Receiver { } self.counter += 1; - debug!("Received {:?}", &counter.deref()); + debug!("Received {:?}", counter.deref()); Ok(()) } @@ -193,7 +194,7 @@ impl Activity for Monitor { /// Create an activity input. fn activity_input(topic: &str) -> Box> where - T: core::fmt::Debug + 'static, + T: core::fmt::Debug + ScoreDebug + 'static, { #[cfg(feature = "com_iox2")] { @@ -208,7 +209,7 @@ where /// Create an activity output. fn activity_output(topic: &str) -> Box> where - T: core::fmt::Debug + 'static, + T: core::fmt::Debug + ScoreDebug + 'static, { #[cfg(feature = "com_iox2")] { diff --git a/tests/rust/feo_tests/test_agent/src/config.rs b/tests/rust/feo_tests/test_agent/src/config.rs index 0c299ee..246585b 100644 --- a/tests/rust/feo_tests/test_agent/src/config.rs +++ b/tests/rust/feo_tests/test_agent/src/config.rs @@ -14,7 +14,7 @@ use core::net::{IpAddr, Ipv4Addr, SocketAddr}; use feo::ids::AgentId; use feo_com::interface::ComBackend; -use std::time::Duration; +use feo_time::Duration; pub const PRIMARY_AGENT_ID: AgentId = AgentId::new(100); pub const BIND_ADDR: SocketAddr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 8081); diff --git a/tests/rust/feo_tests/test_agent/src/main.rs b/tests/rust/feo_tests/test_agent/src/main.rs index 75f1e17..04cc76a 100644 --- a/tests/rust/feo_tests/test_agent/src/main.rs +++ b/tests/rust/feo_tests/test_agent/src/main.rs @@ -12,10 +12,11 @@ // ******************************************************************************* use clap::{Parser, Subcommand, ValueEnum}; use feo::error::Error; -use feo_log::LevelFilter; +use score_log::LevelFilter; use std::path::Path; use std::path::PathBuf; use std::sync::Once; +use stdout_logger::StdoutLoggerBuilder; use crate::primary::PrimaryLauncher as _; use crate::secondary::SecondaryLauncher as _; @@ -64,7 +65,13 @@ enum Scenario { fn init(_com_config: Option<&Path>) { static ONCE: Once = Once::new(); ONCE.call_once(|| { - feo_logger::init(LevelFilter::Debug, true, true); + StdoutLoggerBuilder::new() + .context("test") + .show_module(true) + .show_file(true) + .show_line(true) + .log_level(LevelFilter::Debug) + .set_as_default_logger(); feo_tracing::init(feo_tracing::LevelFilter::TRACE); }); } diff --git a/tests/rust/feo_tests/test_agent/src/primary.rs b/tests/rust/feo_tests/test_agent/src/primary.rs index 93f266e..4ee7bd2 100644 --- a/tests/rust/feo_tests/test_agent/src/primary.rs +++ b/tests/rust/feo_tests/test_agent/src/primary.rs @@ -19,8 +19,8 @@ use crate::scenario::ScenarioConfig; use crate::{Scenario, Signalling}; use feo::agent::com_init::initialize_com_primary; use feo::error::Error; -use feo_log::info; use feo_time::Duration; +use score_log::info; use std::path::PathBuf; pub trait PrimaryLauncher { @@ -30,7 +30,7 @@ pub trait PrimaryLauncher { impl PrimaryLauncher for Signalling { fn launch_primary(&self, scenario: Scenario, server_name: String) -> Result<(), Error> { - info!("Starting primary agent {PRIMARY_AGENT_ID}"); + info!("Starting primary agent {}", PRIMARY_AGENT_ID); // Initialize topics. Do not drop. let _topic_guards = initialize_com_primary( diff --git a/tests/rust/feo_tests/test_agent/src/scenario.rs b/tests/rust/feo_tests/test_agent/src/scenario.rs index 6f08b97..949a7db 100644 --- a/tests/rust/feo_tests/test_agent/src/scenario.rs +++ b/tests/rust/feo_tests/test_agent/src/scenario.rs @@ -17,6 +17,7 @@ use crate::Scenario; use feo::activity::{ActivityBuilder, ActivityIdAndBuilder}; use feo::ids::{ActivityId, AgentId, WorkerId}; use feo::topicspec::{Direction, TopicSpecification}; +use score_log::ScoreDebug; use std::collections::HashMap; // For each activity, list the activities it needs to wait for @@ -128,7 +129,7 @@ impl ScenarioConfig for Scenario { } /// COM type for Sender and Receiver activities' data exchange -#[derive(Debug, Default)] +#[derive(Debug, Default, ScoreDebug)] pub struct Counter { pub counter: usize, } diff --git a/tests/rust/feo_tests/test_agent/src/secondary.rs b/tests/rust/feo_tests/test_agent/src/secondary.rs index 226cd6d..8713b1d 100644 --- a/tests/rust/feo_tests/test_agent/src/secondary.rs +++ b/tests/rust/feo_tests/test_agent/src/secondary.rs @@ -11,7 +11,7 @@ // SPDX-License-Identifier: Apache-2.0 // ******************************************************************************* -use core::time::Duration; +use feo_time::Duration; use std::collections::HashSet; use std::path::PathBuf; @@ -20,7 +20,7 @@ use feo::agent::com_init::initialize_com_secondary; use feo::agent::NodeAddress; use feo::error::Error; use feo::ids::{ActivityId, AgentId}; -use feo_log::info; +use score_log::info; use crate::scenario::ScenarioConfig as _; use crate::{config::PRIMARY_AGENT_ID, Scenario, Signalling};