-
Notifications
You must be signed in to change notification settings - Fork 748
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This PR adds a README and an example to the `tokio-trace-serde` crate.
- Loading branch information
1 parent
f8bef30
commit d74867e
Showing
3 changed files
with
234 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
# tokio-trace-serde | ||
|
||
An adapter for serializing `tokio-trace` types using `serde`. | ||
|
||
[Documentation](https://docs.rs/tokio-trace-serde/0.1.0/tokio_trace_serde/index.html) | ||
|
||
## Overview | ||
|
||
`tokio-trace-serde` enables serializing `tokio-trace` types using | ||
`serde`. `tokio-trace` is a framework for instrumenting Rust programs | ||
to collect structured, event-based diagnostic information. | ||
|
||
Traditional logging is based on human-readable text messages. | ||
`tokio-trace` gives us machine-readable structured diagnostic | ||
information. This lets us interact with diagnostic data | ||
programmatically. With `tokio-trace-serde`, you can implement a | ||
`Subscriber` to serialize your `tokio-trace` types and make use of the | ||
existing ecosystem of `serde` serializers to talk with distributed | ||
tracing systems. | ||
|
||
Serializing diagnostic information allows us to do more with our logged | ||
values. For instance, when working with logging data in JSON gives us | ||
pretty-print when we're debugging in development and you can emit JSON | ||
and tracing data to monitor your services in production. | ||
|
||
The `tokio-trace` crate provides the APIs necessary for instrumenting | ||
libraries and applications to emit trace data. | ||
|
||
## Usage | ||
|
||
First, add this to your `Cargo.toml`: | ||
|
||
```toml | ||
[dependencies] | ||
tokio-trace = "0.1" | ||
tokio-trace-serde = "0.1" | ||
``` | ||
|
||
Next, add this to your crate: | ||
|
||
```rust | ||
#[macro_use] | ||
extern crate tokio_trace; | ||
extern crate tokio_trace_serde; | ||
|
||
use tokio_trace_serde::AsSerde; | ||
``` | ||
|
||
Please read the [`tokio-trace` documentation](https://docs.rs/tokio-trace/0.1.0/tokio_trace/index.html) | ||
for more information on how to create trace data. | ||
|
||
This crate provides the `as_serde` function, via the `AsSerde` trait, | ||
which enables serializing the `Attributes`, `Event`, `Id`, `Metadata`, | ||
and `Record` `tokio-trace` values. | ||
|
||
For the full example, please see the [examples](../examples) folder. | ||
|
||
Implement a `Subscriber` to format the serialization of `tokio-trace` | ||
types how you'd like. | ||
|
||
```rust | ||
pub struct JsonSubscriber { | ||
next_id: AtomicUsize, // you need to assign span IDs, so you need a counter | ||
} | ||
|
||
impl Subscriber for JsonSubscriber { | ||
|
||
fn new_span(&self, attrs: &Attributes) -> Id { | ||
let id = self.next_id.fetch_add(1, Ordering::Relaxed); | ||
let id = Id::from_u64(id as u64); | ||
let json = json!({ | ||
"new_span": { | ||
"attributes": attrs.as_serde(), | ||
"id": id.as_serde(), | ||
}}); | ||
println!("{}", json); | ||
id | ||
} | ||
// ... | ||
} | ||
``` | ||
|
||
After you implement your `Subscriber`, you can use your `tokio-trace` | ||
subscriber (`JsonSubscriber` in the above example) to record serialized | ||
trace data. | ||
|
||
## License | ||
|
||
This project is licensed under the [MIT license](LICENSE). | ||
|
||
### Contribution | ||
|
||
Unless you explicitly state otherwise, any contribution intentionally submitted | ||
for inclusion in Tokio by you, shall be licensed as MIT, without any additional | ||
terms or conditions. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
#[macro_use] | ||
extern crate serde_json; | ||
|
||
#[macro_use] | ||
extern crate tokio_trace; | ||
extern crate tokio_trace_core; | ||
extern crate tokio_trace_serde; | ||
|
||
use std::sync::atomic::AtomicUsize; | ||
use std::sync::atomic::Ordering; | ||
|
||
use tokio_trace_core::{ | ||
event::Event, | ||
metadata::{Level, Metadata}, | ||
span::{Attributes, Id, Record}, | ||
subscriber::Subscriber, | ||
}; | ||
|
||
use tokio_trace_serde::AsSerde; | ||
|
||
pub struct JsonSubscriber { | ||
next_id: AtomicUsize, // you need to assign span IDs, so you need a counter | ||
} | ||
|
||
impl Subscriber for JsonSubscriber { | ||
fn enabled(&self, metadata: &Metadata) -> bool { | ||
let json = json!({ | ||
"enabled": { | ||
"metadata": metadata.as_serde(), | ||
}}); | ||
println!("{}", json); | ||
true | ||
} | ||
|
||
fn new_span(&self, attrs: &Attributes) -> Id { | ||
let id = self.next_id.fetch_add(1, Ordering::Relaxed); | ||
let id = Id::from_u64(id as u64); | ||
let json = json!({ | ||
"new_span": { | ||
"attributes": attrs.as_serde(), | ||
"id": id.as_serde(), | ||
}}); | ||
println!("{}", json); | ||
id | ||
} | ||
|
||
fn record(&self, span: &Id, values: &Record) { | ||
let json = json!({ | ||
"record": { | ||
"span": span.as_serde(), | ||
"values": values.as_serde(), | ||
}}); | ||
println!("{}", json); | ||
} | ||
|
||
fn record_follows_from(&self, span: &Id, follows: &Id) { | ||
let json = json!({ | ||
"record_follows_from": { | ||
"span": span.as_serde(), | ||
"follows": follows.as_serde(), | ||
}}); | ||
println!("{}", json); | ||
} | ||
|
||
fn event(&self, event: &Event) { | ||
let json = json!({ | ||
"event": event.as_serde(), | ||
}); | ||
println!("{}", json); | ||
} | ||
|
||
fn enter(&self, span: &Id) { | ||
let json = json!({ | ||
"enter": span.as_serde(), | ||
}); | ||
println!("{}", json); | ||
} | ||
|
||
fn exit(&self, span: &Id) { | ||
let json = json!({ | ||
"exit": span.as_serde(), | ||
}); | ||
println!("{}", json); | ||
} | ||
} | ||
|
||
fn shave(yak: usize) -> bool { | ||
span!(Level::TRACE, "shave", yak = yak).enter(|| { | ||
debug!( | ||
message = "hello! I'm gonna shave a yak.", | ||
excitement = "yay!" | ||
); | ||
if yak == 3 { | ||
warn!(target: "yak_events", "could not locate yak!"); | ||
false | ||
} else { | ||
trace!(target: "yak_events", "yak shaved successfully"); | ||
true | ||
} | ||
}) | ||
} | ||
|
||
fn main() { | ||
let subscriber = JsonSubscriber { | ||
next_id: AtomicUsize::new(1), | ||
}; | ||
|
||
tokio_trace::subscriber::with_default(subscriber, || { | ||
let number_of_yaks = 3; | ||
let mut number_shaved = 0; | ||
debug!("preparing to shave {} yaks", number_of_yaks); | ||
|
||
span!(Level::TRACE, "shaving_yaks", yaks_to_shave = number_of_yaks).enter(|| { | ||
info!("shaving yaks"); | ||
|
||
for yak in 1..=number_of_yaks { | ||
let shaved = shave(yak); | ||
trace!(target: "yak_events", yak = yak, shaved = shaved); | ||
|
||
if !shaved { | ||
error!(message = "failed to shave yak!", yak = yak); | ||
} else { | ||
number_shaved += 1; | ||
} | ||
|
||
trace!(target: "yak_events", yaks_shaved = number_shaved); | ||
} | ||
}); | ||
|
||
debug!( | ||
message = "yak shaving completed.", | ||
all_yaks_shaved = number_shaved == number_of_yaks, | ||
); | ||
}); | ||
} |