Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to track upstream changes #3

Merged
merged 7 commits into from
Feb 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
211 changes: 124 additions & 87 deletions tokio-trace-env-logger/examples/hyper-echo/sloggish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,68 @@
//! [`slog` README]: https://github.com/slog-rs/slog#terminal-output-example
extern crate ansi_term;
extern crate humantime;
extern crate tokio_trace_subscriber;

use self::ansi_term::{Color, Style};
use super::tokio_trace::{self, Id, Level, Subscriber};
use super::tokio_trace::{
self,
field::{Field, Record},
Id, Level, Subscriber,
};

use std::{
cell::RefCell,
collections::HashMap,
fmt,
io::{self, Write},
sync::{
atomic::{AtomicUsize, Ordering},
Mutex,
},
thread,
time::SystemTime,
};

/// Tracks the currently executing span on a per-thread basis.
#[derive(Clone)]
pub struct CurrentSpanPerThread {
current: &'static thread::LocalKey<RefCell<Vec<Id>>>,
}

impl CurrentSpanPerThread {
pub fn new() -> Self {
thread_local! {
static CURRENT: RefCell<Vec<Id>> = RefCell::new(vec![]);
};
Self { current: &CURRENT }
}

/// Returns the [`Id`](::Id) of the span in which the current thread is
/// executing, or `None` if it is not inside of a span.
pub fn id(&self) -> Option<Id> {
self.current
.with(|current| current.borrow().last().cloned())
}

pub fn enter(&self, span: Id) {
self.current.with(|current| {
current.borrow_mut().push(span);
})
}

pub fn exit(&self) {
self.current.with(|current| {
let _ = current.borrow_mut().pop();
})
}
}

pub struct SloggishSubscriber {
// TODO: this can probably be unified with the "stack" that's used for
// printing?
current: tokio_trace_subscriber::CurrentSpanPerThread,
current: CurrentSpanPerThread,
indent_amount: usize,
stderr: io::Stderr,
stack: Mutex<Vec<Id>>,
spans: Mutex<HashMap<Id, Span>>,
events: Mutex<HashMap<Id, Event>>,
ids: AtomicUsize,
}

Expand All @@ -45,72 +82,86 @@ struct Span {
kvs: Vec<(&'static str, String)>,
}

struct Event {
level: tokio_trace::Level,
target: String,
message: String,
kvs: Vec<(&'static str, String)>,
struct Event<'a> {
stderr: io::StderrLock<'a>,
comma: bool,
}

struct ColorLevel(Level);
struct ColorLevel<'a>(&'a Level);

impl fmt::Display for ColorLevel {
impl<'a> fmt::Display for ColorLevel<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
Level::TRACE => Color::Purple.paint("TRACE"),
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::TRACE => Color::Purple.paint("TRACE"),
&Level::DEBUG => Color::Blue.paint("DEBUG"),
&Level::INFO => Color::Green.paint("INFO "),
&Level::WARN => Color::Yellow.paint("WARN "),
&Level::ERROR => Color::Red.paint("ERROR"),
}
.fmt(f)
}
}

impl Span {
fn new(parent: Option<Id>, _meta: &tokio_trace::Metadata) -> Self {
Self {
fn new(
parent: Option<Id>,
_meta: &tokio_trace::Metadata,
values: &tokio_trace::field::ValueSet,
) -> Self {
let mut span = Self {
parent,
kvs: Vec::new(),
}
}

fn record(&mut self, key: &tokio_trace::field::Field, value: fmt::Arguments) {
let v = fmt::format(value);
self.kvs.push((key.name(), v));
};
values.record(&mut span);
span
}
}

impl Event {
fn new(meta: &tokio_trace::Metadata) -> Self {
Self {
target: meta.target.to_owned(),
level: meta.level.clone(),
message: String::new(),
kvs: Vec::new(),
}
impl Record for Span {
fn record_debug(&mut self, field: &Field, value: &fmt::Debug) {
self.kvs.push((field.name(), format!("{:?}", value)))
}
}

fn record(&mut self, key: &tokio_trace::field::Field, value: fmt::Arguments) {
if key.name() == "message" {
self.message = fmt::format(value);
return;
impl<'a> Record for Event<'a> {
fn record_debug(&mut self, field: &Field, value: &fmt::Debug) {
write!(
&mut self.stderr,
"{comma} ",
comma = if self.comma { "," } else { "" },
)
.unwrap();
let name = field.name();
if name == "message" {
write!(
&mut self.stderr,
"{}",
// Have to alloc here due to `ansi_term`'s API...
Style::new().bold().paint(format!("{:?}", value))
)
.unwrap();
self.comma = true;
} else {
write!(
&mut self.stderr,
"{}: {:?}",
Style::new().bold().paint(name),
value
)
.unwrap();
self.comma = true;
}

let v = fmt::format(value);
self.kvs.push((key.name(), v));
}
}

impl SloggishSubscriber {
pub fn new(indent_amount: usize) -> Self {
Self {
current: tokio_trace_subscriber::CurrentSpanPerThread::new(),
current: CurrentSpanPerThread::new(),
indent_amount,
stderr: io::stderr(),
stack: Mutex::new(vec![]),
spans: Mutex::new(HashMap::new()),
events: Mutex::new(HashMap::new()),
ids: AtomicUsize::new(0),
}
}
Expand Down Expand Up @@ -155,39 +206,26 @@ impl Subscriber for SloggishSubscriber {
true
}

fn new_span(&self, span: &tokio_trace::Metadata) -> tokio_trace::Id {
fn new_span(
&self,
span: &tokio_trace::Metadata,
values: &tokio_trace::field::ValueSet,
) -> tokio_trace::Id {
let next = self.ids.fetch_add(1, Ordering::SeqCst) as u64;
let id = tokio_trace::Id::from_u64(next);
if span.name.contains("event") {
self.events
.lock()
.unwrap()
.insert(id.clone(), Event::new(span));
} else {
self.spans
.lock()
.unwrap()
.insert(id.clone(), Span::new(self.current.id(), span));
}
let span = Span::new(self.current.id(), span, values);
self.spans.lock().unwrap().insert(id.clone(), span);
id
}

fn record_debug(
&self,
span: &tokio_trace::Id,
name: &tokio_trace::field::Field,
value: &fmt::Debug,
) {
if let Some(event) = self.events.lock().expect("mutex poisoned!").get_mut(span) {
return event.record(name, format_args!("{:?}", value));
};
fn record(&self, span: &tokio_trace::Id, values: &tokio_trace::field::ValueSet) {
let mut spans = self.spans.lock().expect("mutex poisoned!");
if let Some(span) = spans.get_mut(span) {
span.record(name, format_args!("{:?}", value))
values.record(span);
}
}

fn add_follows_from(&self, _span: &tokio_trace::Id, _follows: tokio_trace::Id) {
fn record_follows_from(&self, _span: &tokio_trace::Id, _follows: &tokio_trace::Id) {
// unimplemented
}

Expand Down Expand Up @@ -223,34 +261,33 @@ impl Subscriber for SloggishSubscriber {
}
}

fn event(&self, event: &tokio_trace::Event) {
let mut stderr = self.stderr.lock();
let indent = self.stack.lock().unwrap().len();
self.print_indent(&mut stderr, indent).unwrap();
write!(
&mut stderr,
"{timestamp} {level} {target}",
timestamp = humantime::format_rfc3339_seconds(SystemTime::now()),
level = ColorLevel(event.metadata().level()),
target = &event.metadata().target(),
)
.unwrap();
let mut recorder = Event {
stderr,
comma: false,
};
event.record(&mut recorder);
write!(&mut recorder.stderr, "\n").unwrap();
}

#[inline]
fn exit(&self, _span: &tokio_trace::Id) {
// TODO: unify stack with current span
self.current.exit();
}

fn drop_span(&self, id: tokio_trace::Id) {
if let Some(event) = self.events.lock().expect("mutex poisoned").remove(&id) {
let mut stderr = self.stderr.lock();
let indent = self.stack.lock().unwrap().len();
self.print_indent(&mut stderr, indent).unwrap();
write!(
&mut stderr,
"{timestamp} {level} {target} {message}",
timestamp = humantime::format_rfc3339_seconds(SystemTime::now()),
level = ColorLevel(event.level),
target = &event.target,
message = Style::new().bold().paint(event.message),
)
.unwrap();
self.print_kvs(
&mut stderr,
event.kvs.iter().map(|&(ref k, ref v)| (k, v)),
", ",
)
.unwrap();
write!(&mut stderr, "\n").unwrap();
}
fn drop_span(&self, _id: tokio_trace::Id) {
// TODO: GC unneeded spans.
}
}
6 changes: 3 additions & 3 deletions tokio-trace-futures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ extern crate tokio;
extern crate tokio_trace;

use futures::{Async, Future, Poll, Sink, StartSend, Stream};
use tokio_trace::{dispatcher, Dispatch, Span, Subscriber};
use tokio_trace::{dispatcher, Dispatch, Span};

pub mod executor;

Expand All @@ -21,11 +21,11 @@ pub trait Instrument: Sized {
pub trait WithSubscriber: Sized {
fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where
S: Subscriber + Send + Sync + 'static,
S: Into<Dispatch>,
{
WithDispatch {
inner: self,
dispatch: Dispatch::new(subscriber),
dispatch: subscriber.into(),
}
}
}
Expand Down
Loading