From f2f3cdfbe47c2e47d52ea614f10e0815af565919 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Fri, 21 Sep 2018 13:34:06 -0700 Subject: [PATCH] working slog-style example --- tokio-trace/examples/sloggish.rs | 77 ++++++++++++++++++++++++++------ tokio-trace/src/dedup.rs | 17 ++++--- 2 files changed, 74 insertions(+), 20 deletions(-) diff --git a/tokio-trace/examples/sloggish.rs b/tokio-trace/examples/sloggish.rs index 39de863f..c9e368c8 100644 --- a/tokio-trace/examples/sloggish.rs +++ b/tokio-trace/examples/sloggish.rs @@ -1,3 +1,15 @@ +//! A simple example demonstrating how one might implement a custom +//! subscriber. +//! +//! This subscriber implements a tree-structured logger similar to +//! the "compact" formatter in [`slog-term`]. The demo mimicks the +//! example output in the screenshot in the [`slog` README]. +//! +//! Note that this logger isn't ready for actual production use. +//! Several corners were cut to make the example simple. +//! +//! [`slog-term`]: https://docs.rs/slog-term/2.4.0/slog_term/ +//! [`slog` README]: https://github.com/slog-rs/slog#terminal-output-example #[macro_use] extern crate tokio_trace; extern crate ansi_term; @@ -8,8 +20,8 @@ use tokio_trace::Level; use std::{ fmt, io::{self, Write}, - time::Instant, sync::atomic::{AtomicUsize, Ordering}, + time::Instant, }; struct SloggishSubscriber { @@ -27,7 +39,7 @@ impl fmt::Display for ColorLevel { Level::Debug => Color::Blue.paint("DEBUG"), Level::Info => Color::Green.paint("INFO "), Level::Warn => Color::Yellow.paint("WARN "), - Level::Error => Color::Red.paint("ERROR") + Level::Error => Color::Red.paint("ERROR"), }.fmt(f) } } @@ -41,18 +53,27 @@ impl SloggishSubscriber { } } - fn print_kvs<'a, I>(&self, writer: &mut impl Write, kvs: I) -> io::Result<()> + fn print_kvs<'a, I>(&self, writer: &mut impl Write, kvs: I, leading: &str) -> io::Result<()> where - I: IntoIterator, + I: IntoIterator, { + let mut kvs = kvs.into_iter(); + if let Some((k, v)) = kvs.next() { + write!(writer, "{}{}: {:?}", leading, Style::new().bold().paint(k), v)?; + } for (k, v) in kvs { - write!(writer, "{}: {:?} ", Style::new().bold().paint(k), v)?; + write!(writer, ", {}: {:?}", Style::new().bold().paint(k), v)?; } Ok(()) } - fn print_meta(&self, writer: &mut impl Write, meta: &tokio_trace::StaticMeta) -> io::Result<()> { - write!(writer, + fn print_meta( + &self, + writer: &mut impl Write, + meta: &tokio_trace::StaticMeta, + ) -> io::Result<()> { + write!( + writer, "{level} {target} ", level = ColorLevel(meta.level), target = meta.target.unwrap_or(meta.module_path), @@ -74,8 +95,12 @@ impl tokio_trace::Subscriber for SloggishSubscriber { let mut stderr = self.stderr.lock(); self.print_meta(&mut stderr, event.static_meta).unwrap(); self.print_indent(&mut stderr).unwrap(); - write!(&mut stderr, "{}, ", Style::new().bold().paint(format!("{}", event.message))).unwrap(); - self.print_kvs(&mut stderr, event.all_fields()).unwrap(); + write!( + &mut stderr, + "{}", + Style::new().bold().paint(format!("{}", event.message)) + ).unwrap(); + self.print_kvs(&mut stderr, event.fields(), ", ").unwrap(); write!(&mut stderr, "\n").unwrap(); } @@ -84,9 +109,10 @@ impl tokio_trace::Subscriber for SloggishSubscriber { let mut stderr = self.stderr.lock(); self.print_meta(&mut stderr, span.meta()).unwrap(); let indent = self.print_indent(&mut stderr).unwrap(); - self.print_kvs(&mut stderr, span.fields()).unwrap(); + self.print_kvs(&mut stderr, span.fields(), "").unwrap(); write!(&mut stderr, "\n").unwrap(); - self.indent.compare_and_swap(indent, indent + self.indent_amount, Ordering::Release); + self.indent + .compare_and_swap(indent, indent + self.indent_amount, Ordering::Release); } #[inline] @@ -103,8 +129,31 @@ fn main() { let foo = 3; event!(Level::Info, { foo = foo, bar = "bar" }, "hello world"); - let span = span!("my_great_span", foo = 4, baz = 5); - span.enter(|| { - event!(Level::Info, { yak_shaved = true }, "hi from inside my span"); + span!("", version = 5.0).enter(|| { + span!("server", host = "localhost", port = 8080).enter(|| { + event!(Level::Info, {}, "starting"); + event!(Level::Info, {}, "listening"); + let peer1 = span!("conn", peer_addr = "82.9.9.9", port = 42381); + peer1.enter(|| { + event!(Level::Debug, {}, "connected"); + event!(Level::Debug, { length = 2 }, "message received"); + }); + let peer2 = span!("conn", peer_addr = "8.8.8.8", port = 18230); + peer2.enter(|| { + event!(Level::Debug, {}, "connected"); + }); + peer1.enter(|| { + event!(Level::Warn, { algo = "xor" }, "weak encryption requested"); + event!(Level::Debug, { length = 8 }, "response sent"); + event!(Level::Debug, { }, "disconnected"); + }); + peer2.enter(|| { + event!(Level::Debug, { length = 5 }, "message received"); + event!(Level::Debug, { length = 8 }, "response sent"); + event!(Level::Debug, { }, "disconnected"); + }); + event!(Level::Error, {}, "internal error"); + event!(Level::Info, {}, "exit"); + }) }); } diff --git a/tokio-trace/src/dedup.rs b/tokio-trace/src/dedup.rs index 8b0b9435..16dee39f 100644 --- a/tokio-trace/src/dedup.rs +++ b/tokio-trace/src/dedup.rs @@ -3,7 +3,7 @@ use std::iter::Peekable; pub trait IteratorDedup: Iterator + Sized { fn dedup_by(self, f: F) -> DedupBy where - F: Fn(&Self::Item) -> K, + F: Fn(&Self::Item) -> &K, K: PartialEq, { DedupBy { @@ -19,16 +19,21 @@ where I: Iterator + Sized, {} -pub struct DedupBy { +pub struct DedupBy &K, K> { f: F, inner: Peekable, emit: bool, } -impl Iterator for DedupBy -where I: Iterator, ::Item: PartialEq { +impl Iterator for DedupBy +where + I: Iterator, + F: Fn(&I::Item) -> &K, + K: PartialEq, +{ type Item = ::Item; fn next(&mut self) -> Option<::Item> { + let f = &self.f; let result = if self.emit { self.inner.next() @@ -37,9 +42,9 @@ where I: Iterator, ::Item: PartialEq { None => return None, Some(first) => first, }; - self.inner.find(|item| first != *item) + self.inner.find(|item| (f)(&first) != (f)(item)) }; - self.emit = result.as_ref() != self.inner.peek(); + self.emit = result.as_ref().map(f) != self.inner.peek().map(f); result } }