diff --git a/.zetch.lock b/.zetch.lock index 4b31640a..a9e19cc1 100644 --- a/.zetch.lock +++ b/.zetch.lock @@ -1,23 +1,23 @@ { "version": "0.0.10", "files": { - "docs/LICENSE.zetch.md": "d2c12e539d357957b950a54a5477c3a9f87bd2b3ee707be7a4db7adaf5aacc2b", - "py_rust/LICENSE.zetch.md": "d2c12e539d357957b950a54a5477c3a9f87bd2b3ee707be7a4db7adaf5aacc2b", - "rust/README.zetch.md": "d437e5a66fb74e7920b633f042195b89bcdec96274deace6d5919841c28a378e", - "docs/index.zetch.md": "d437e5a66fb74e7920b633f042195b89bcdec96274deace6d5919841c28a378e", - "CODE_OF_CONDUCT.zetch.md": "bf106326ffc75f5167cfde27c997c77c6b97c843a9e392b564355d0e70e50b97", - "py/LICENSE.zetch.md": "d2c12e539d357957b950a54a5477c3a9f87bd2b3ee707be7a4db7adaf5aacc2b", - "rust/LICENSE.zetch.md": "d2c12e539d357957b950a54a5477c3a9f87bd2b3ee707be7a4db7adaf5aacc2b", "js/tsconfig.zetch.json": "fb5d57b825bb3c2f6dd4254bf939f2444e52946622a7f93b91e3acb75876ebbc", - "docs/CODE_OF_CONDUCT.zetch.md": "bf106326ffc75f5167cfde27c997c77c6b97c843a9e392b564355d0e70e50b97", - "js/LICENSE.zetch.md": "d2c12e539d357957b950a54a5477c3a9f87bd2b3ee707be7a4db7adaf5aacc2b", - "py_rust/README.zetch.md": "d437e5a66fb74e7920b633f042195b89bcdec96274deace6d5919841c28a378e", + "docs/index.zetch.md": "d437e5a66fb74e7920b633f042195b89bcdec96274deace6d5919841c28a378e", "CONTRIBUTING.zetch.md": "bace46dc064746b54cf472eba960d934d705c2f83120b865a4b47032ff1552c5", + "py_rust/LICENSE.zetch.md": "d2c12e539d357957b950a54a5477c3a9f87bd2b3ee707be7a4db7adaf5aacc2b", "LICENSE.zetch.md": "d2c12e539d357957b950a54a5477c3a9f87bd2b3ee707be7a4db7adaf5aacc2b", + "opencollector.yaml.zetch": "61ef569d5d016214672a01a5f372a87ee9a2bbb885c8f4f4e57f421d3812a312", + "rust/README.zetch.md": "d437e5a66fb74e7920b633f042195b89bcdec96274deace6d5919841c28a378e", "README.zetch.md": "999ec659475c35f7ebafa5b246c2f0083b4bf7e25740d70e708d17887d1f2d36", - "py/README.zetch.md": "d437e5a66fb74e7920b633f042195b89bcdec96274deace6d5919841c28a378e", "js/README.zetch.md": "d437e5a66fb74e7920b633f042195b89bcdec96274deace6d5919841c28a378e", + "docs/CODE_OF_CONDUCT.zetch.md": "bf106326ffc75f5167cfde27c997c77c6b97c843a9e392b564355d0e70e50b97", "docs/CONTRIBUTING.zetch.md": "bace46dc064746b54cf472eba960d934d705c2f83120b865a4b47032ff1552c5", - "opencollector.yaml.zetch": "27c7cbc36a0a6d0eb0af8bece63a6d170bfabe098f26ae0c82e5d671441418ad" + "rust/LICENSE.zetch.md": "d2c12e539d357957b950a54a5477c3a9f87bd2b3ee707be7a4db7adaf5aacc2b", + "CODE_OF_CONDUCT.zetch.md": "bf106326ffc75f5167cfde27c997c77c6b97c843a9e392b564355d0e70e50b97", + "js/LICENSE.zetch.md": "d2c12e539d357957b950a54a5477c3a9f87bd2b3ee707be7a4db7adaf5aacc2b", + "py/README.zetch.md": "d437e5a66fb74e7920b633f042195b89bcdec96274deace6d5919841c28a378e", + "py/LICENSE.zetch.md": "d2c12e539d357957b950a54a5477c3a9f87bd2b3ee707be7a4db7adaf5aacc2b", + "py_rust/README.zetch.md": "d437e5a66fb74e7920b633f042195b89bcdec96274deace6d5919841c28a378e", + "docs/LICENSE.zetch.md": "d2c12e539d357957b950a54a5477c3a9f87bd2b3ee707be7a4db7adaf5aacc2b" } } \ No newline at end of file diff --git a/opencollector.yaml b/opencollector.yaml index b47ed42f..79fe6f30 100644 --- a/opencollector.yaml +++ b/opencollector.yaml @@ -27,7 +27,7 @@ exporters: stream-name: default # Writes all opentelemetry logs, traces, metrics to a file, useful for testing: file/debug_file_writing: - path: /home/runner/work/bitbazaar/bitbazaar/logs/otlp_telemetry_out.log + path: /Users/zak/z/code/bitbazaar/logs/otlp_telemetry_out.log rotation: max_megabytes: 10 max_days: 3 diff --git a/rust/bitbazaar/log/global_log/event_formatter.rs b/rust/bitbazaar/log/global_log/event_formatter.rs index f4ca56dd..6bb8e473 100644 --- a/rust/bitbazaar/log/global_log/event_formatter.rs +++ b/rust/bitbazaar/log/global_log/event_formatter.rs @@ -1,3 +1,4 @@ +use colored::Colorize; use tracing_core::Subscriber; use tracing_subscriber::{ fmt::{format::Writer, FmtContext, FormatEvent, FormatFields}, @@ -57,18 +58,16 @@ where if is_exception { let mut visitor = ExceptionEventVisitor::default(); event.record(&mut visitor); - if let Some(stacktrace) = visitor.stacktrace.as_ref() { - writeln!(writer, "{}", clean_string(stacktrace))?; - } - if let Some(typ) = visitor.typ.as_ref() { - if let Some(message) = visitor.message.as_ref() { - writeln!(writer, "{}: {}", clean_string(typ), clean_string(message))?; - } else { - writeln!(writer, "{}", clean_string(typ))?; - } - } else if let Some(message) = visitor.message.as_ref() { - writeln!(writer, "{}", clean_string(message))?; + + let indent = 6; + writeln!(writer, "{}", "ERROR: ".red())?; + + let msg = visitor.into_msg(); + // Write each line and indent it by 7 to match the ERROR: prefix + for line in msg.lines() { + writeln!(writer, "{:indent$}{}", "", line.red())?; } + Ok(()) } else { self.inner.format_event(ctx, writer, event) @@ -76,13 +75,6 @@ where } } -#[inline] -/// Weirdly they seem to come in with quotes around them, this simple removes them. -/// In a sep func to allow extending if needed. -fn clean_string(s: &str) -> &str { - s.trim_matches('"') -} - #[derive(Default)] struct ExceptionEventVisitor { message: Option, @@ -90,7 +82,51 @@ struct ExceptionEventVisitor { stacktrace: Option, } +impl ExceptionEventVisitor { + fn into_msg(self) -> String { + let mut msg = String::new(); + if let Some(stacktrace) = self.stacktrace { + msg.push_str(clean_string(&stacktrace)); + msg.push('\n'); + } + if let Some(typ) = self.typ { + if let Some(message) = self.message { + msg.push_str(&format!( + "{}: {}\n", + clean_string(&typ), + clean_string(&message) + )); + } else { + msg.push_str(clean_string(&typ)); + msg.push('\n'); + } + } else if let Some(message) = self.message { + msg.push_str(clean_string(&message)); + msg.push('\n'); + } + msg + } +} + +#[inline] +/// Weirdly they seem to come in with quotes around them, this simple removes them. +/// In a sep func to allow extending if needed. +fn clean_string(s: &str) -> &str { + s.trim_matches('"') +} + impl tracing::field::Visit for ExceptionEventVisitor { + fn record_str(&mut self, field: &tracing_core::Field, value: &str) { + match field.name() { + "exception.message" => self.message = Some(value.to_string()), + "exception.type" => self.typ = Some(value.to_string()), + "exception.stacktrace" => self.stacktrace = Some(value.to_string()), + _ => {} + } + } + + /// NOTE: record_str() is the one that's actually used, this would escape newlines etc. + /// But keeping as the trait requires it and just in case for some reason one of these isn't a string. fn record_debug(&mut self, field: &tracing_core::Field, value: &dyn std::fmt::Debug) { match field.name() { "exception.message" => self.message = Some(format!("{:?}", value)), diff --git a/rust/bitbazaar/log/mod.rs b/rust/bitbazaar/log/mod.rs index 7ec4f490..e5b923cb 100644 --- a/rust/bitbazaar/log/mod.rs +++ b/rust/bitbazaar/log/mod.rs @@ -221,7 +221,7 @@ mod tests { let line_preceding_panic = AtomicU32::new(0); log.with_tmp_global(|| { // Manual record: - record_exception("test_exc", "test_stack"); + record_exception("test_exc", "test_stack\nfoodle\nwoodle"); // Panics should be auto recorded: let _ = std::panic::catch_unwind(|| { @@ -239,14 +239,13 @@ mod tests { line_preceding_panic.load(std::sync::atomic::Ordering::Relaxed) + 1 ), ] - .join(if cfg!(windows) { "\\\\" } else { "/" }); - assert_eq!( - out, - vec![ - "test_stack\nErr: test_exc".to_string(), - format!("{}\nPanic: test_panic", exp_panic_loc) - ] - ); + .join(if cfg!(windows) { "\\" } else { "/" }); + + assert_eq!(out.len(), 2, "{:?}", out); + assert!(out[0].contains("test_stack"), "{:?}", out[0]); + assert!(out[0].contains("Err: test_exc"), "{:?}", out[0]); + assert!(out[1].contains(&exp_panic_loc), "{:?}", out[1]); + assert!(out[1].contains("Panic: test_panic"), "{:?}", out[1]); Ok(()) } diff --git a/rust/bitbazaar/timing/mod.rs b/rust/bitbazaar/timing/mod.rs index b7be5c5a..b3be665d 100644 --- a/rust/bitbazaar/timing/mod.rs +++ b/rust/bitbazaar/timing/mod.rs @@ -62,12 +62,7 @@ mod tests { let elapsed = recorder.total_elapsed().unwrap(); assert!( - elapsed.as_millis() >= 1, - "elapsed: {:?}", - elapsed.as_millis() - ); - assert!( - elapsed.as_millis() < 2, + elapsed.as_millis() == 1 || elapsed.as_millis() == 2, "elapsed: {:?}", elapsed.as_millis() ); @@ -83,12 +78,7 @@ mod tests { }); let elapsed = GLOBAL_TIME_RECORDER.total_elapsed().unwrap(); assert!( - elapsed.as_millis() >= 1, - "elapsed: {:?}", - elapsed.as_millis() - ); - assert!( - elapsed.as_millis() < 2, + elapsed.as_millis() == 1 || elapsed.as_millis() == 2, "elapsed: {:?}", elapsed.as_millis() );