diff --git a/.gitignore b/.gitignore index ea8c4bf7..7f6e1d8b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +log.csv diff --git a/Cargo.lock b/Cargo.lock index ea70f0f8..2f3e7de2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.80" @@ -149,6 +164,12 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + [[package]] name = "byteorder" version = "1.5.0" @@ -173,6 +194,20 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.4", +] + [[package]] name = "colored" version = "2.1.0" @@ -260,6 +295,15 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "dirs" version = "3.0.2" @@ -562,6 +606,29 @@ dependencies = [ "tokio-io-timeout", ] +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -607,6 +674,15 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -770,6 +846,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-traits" version = "0.2.18" @@ -823,6 +905,7 @@ dependencies = [ "async-trait", "bitflags 2.5.0", "bytes", + "chrono", "colored", "console-subscriber", "dirs", @@ -835,6 +918,7 @@ dependencies = [ "tokio", "tokio-serial", "tracing", + "tracing-appender", "tracing-core", "tracing-subscriber", ] @@ -900,6 +984,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1347,6 +1437,37 @@ dependencies = [ "once_cell", ] +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tokio" version = "1.36.0" @@ -1507,6 +1628,18 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-appender" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" +dependencies = [ + "crossbeam-channel", + "thiserror", + "time", + "tracing-subscriber", +] + [[package]] name = "tracing-attributes" version = "0.1.27" @@ -1605,6 +1738,60 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + [[package]] name = "winapi" version = "0.3.9" @@ -1627,6 +1814,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.4", +] + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index d3fb3c6c..f758289b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,7 @@ bitflags = "2.5.0" # hostname = "0.3.1" +chrono = "0.4" # lazy_static = "1.4.0" @@ -71,6 +72,8 @@ tracing-core = { version = "0.1.32" } # Fmt subscriber tracing-subscriber = "0.3" +tracing-appender = "0.2.3" + # To see instrumentation through tokio console console-subscriber = { version="0.2.0", optional = true } @@ -78,6 +81,7 @@ console-subscriber = { version="0.2.0", optional = true } # Enable tracing in stdout trac-fmt = [ ] +log-issue = [ ] # Enable tracing in tokio console trac-console = [ "console-subscriber" ] diff --git a/src/builtin_devices/panduza/server/itf_platform.rs b/src/builtin_devices/panduza/server/itf_platform.rs index c88df4cd..53485cb7 100644 --- a/src/builtin_devices/panduza/server/itf_platform.rs +++ b/src/builtin_devices/panduza/server/itf_platform.rs @@ -1,6 +1,6 @@ use async_trait::async_trait; -use serde_json::Value; +use serde_json::{json, Value}; use crate::{attribute::JsonAttribute, interface::{self, AmInterface}, subscription}; use crate::interface::Builder as InterfaceBuilder; @@ -149,6 +149,11 @@ impl interface::fsm::States for TestInterfaceStates { ii.update_attribute_with_json("devices", "hunting", ps.lock().await.get_device_store() ); + + + ii.update_attribute_with_string("dtree", "name", &"pok".to_string()); + ii.update_attribute_with_json("dtree", "content", &json!({ "a": 1 })); + ii.publish_all_attributes().await; diff --git a/src/log/formatter_csv.rs b/src/log/formatter_csv.rs new file mode 100644 index 00000000..b285c232 --- /dev/null +++ b/src/log/formatter_csv.rs @@ -0,0 +1,95 @@ +use std::{fmt, thread}; +use regex::Regex; +use tracing_core::{Event, Subscriber}; +use tracing_subscriber::fmt::{ + format::{self, FormatEvent, FormatFields}, + FmtContext +}; +use tracing_subscriber::registry::LookupSpan; + +use crate::log::hash_visitor::HashVisitor; +use chrono::Utc; + +/// A custom event formatter that formats events in a platform-specific way. +/// +pub struct FormatterCSV; + +impl FormatEvent for FormatterCSV +where + S: Subscriber + for<'a> LookupSpan<'a>, + N: for<'a> FormatFields<'a> + 'static, +{ + fn format_event( + &self, + _ctx: &FmtContext<'_, S, N>, + mut writer: format::Writer<'_>, + event: &Event<'_>, + ) -> fmt::Result { + + // + let mut visitor = HashVisitor::new(); + event.record(&mut visitor); + + // println!("{:?}", visitor.entries()); + + // Format the event, if it has at least one message + let res = visitor.entries().get("message"); + if res.is_some() { + + // Format values from the event's metadata: + let metadata = event.metadata(); + + // Print thread id + let thread_id = thread::current().id(); + let thread_id_string = format!("{:?}", thread_id); + // println!("{}", thread_id_string); + let re = Regex::new(r"ThreadId\((\d+)\)").unwrap(); + let caps = re.captures(&thread_id_string).unwrap(); + let id_number = &caps[1]; + + // Get class name + let class_name = visitor.entries() + .get("class") + .or(Some(&"".to_string())) + .and_then(|s| Some(String::from(s))) + .unwrap(); + + let i1 = visitor.entries() + .get("i1") + .or(Some(&"".to_string())) + .and_then(|s| Some(String::from(s))) + .unwrap(); + + let i2 = visitor.entries() + .get("i2") + .or(Some(&"".to_string())) + .and_then(|s| Some(String::from(s))) + .unwrap(); + + let i3 = visitor.entries() + .get("i3") + .or(Some(&"".to_string())) + .and_then(|s| Some(String::from(s))) + .unwrap(); + + // timestamp + // Level (debug/info/warning…) + // class + // i1 + // i2 + // i3 + // message + // thread/task + let message = res.unwrap(); + write!(&mut writer, "{},{},{},{},{},{},{},{}", + Utc::now().to_rfc3339().to_string(), + metadata.level().as_str(), + class_name, + i1, i2, i3, + message, id_number)?; + } + + // Return the formatted event + writeln!(writer) + } +} \ No newline at end of file diff --git a/src/log/platform_formatter.rs b/src/log/formatter_platform.rs similarity index 100% rename from src/log/platform_formatter.rs rename to src/log/formatter_platform.rs diff --git a/src/log/log_issue.rs b/src/log/log_issue.rs new file mode 100644 index 00000000..79e80a59 --- /dev/null +++ b/src/log/log_issue.rs @@ -0,0 +1,81 @@ + +use tracing_subscriber::fmt::format::Writer; +use tracing_subscriber::fmt::time::FormatTime; + +use tracing_subscriber::fmt::format::FmtSpan; + +use chrono::Utc; + +use super::formatter_csv::FormatterCSV; + +struct LogIssueMultiWriter { + filea: tracing_appender::rolling::RollingFileAppender +} + +impl LogIssueMultiWriter { + pub fn new() -> Self { + LogIssueMultiWriter{ + filea: tracing_appender::rolling::never(".", "log.csv") + } + } +} + +impl std::io::Write for LogIssueMultiWriter { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + let buf_len = buf.len(); + + + self.filea.write_all(buf).unwrap(); + + print!("{}", String::from_utf8_lossy(buf)); + Ok(buf_len) + } + + fn flush(&mut self) -> std::io::Result<()> { + self.filea.flush().unwrap(); + Ok(()) + } +} + + +struct MyFormatTime; + +impl FormatTime for MyFormatTime { + fn format_time(&self, w: &mut Writer<'_>) -> std::fmt::Result { + write!(w, "{} ", Utc::now().to_rfc3339()) + } +} + + +/// Configuration for Github/Gitlab issue logger +/// +pub fn init_fmt_subscriber_for_log_issue() +{ + + + let subscriber = tracing_subscriber::fmt() + // + .with_timer(MyFormatTime{}) + // + .with_max_level(tracing::Level::TRACE) + // Display source code line numbers + .with_line_number(false) + // Display the thread ID an event was recorded on + .with_thread_ids(true) + // Don't display the event's target (module path) + .with_target(false) + // No span + .with_span_events(FmtSpan::NONE) + // + .event_format(FormatterCSV{}) + // + .with_writer(||LogIssueMultiWriter::new()) + + // + .finish(); + + + // use that subscriber to process traces emitted after this point + tracing::subscriber::set_global_default(subscriber).unwrap(); +} + diff --git a/src/log/mod.rs b/src/log/mod.rs index 8627a586..9df9ca06 100644 --- a/src/log/mod.rs +++ b/src/log/mod.rs @@ -1,7 +1,12 @@ +mod log_issue; mod hash_visitor; -mod platform_formatter; +mod formatter_csv; +mod formatter_platform; + +use log_issue::init_fmt_subscriber_for_log_issue; + +use crate::log::formatter_platform::PlatformFormatter; -use crate::log::platform_formatter::PlatformFormatter; /// Define the fmt subscriber for the platform /// @@ -32,6 +37,10 @@ fn init_fmt_subscriber() tracing::subscriber::set_global_default(subscriber).unwrap(); } + + + + /// Function to initiliaze tracing for the application /// pub fn init() @@ -39,13 +48,12 @@ pub fn init() if cfg!(feature = "trac-fmt") { init_fmt_subscriber(); } + else if cfg!(feature = "log-issue") { + init_fmt_subscriber_for_log_issue(); + } else if cfg!(feature = "trac-console") { #[cfg(feature = "trac-console")] console_subscriber::init(); } } - - - -