-
Notifications
You must be signed in to change notification settings - Fork 734
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
Feature/valuable integration #1608
Changes from all commits
13f01f8
1638739
bb74cfb
cfee46a
3f3a477
e228504
5919719
344c43e
7d2e431
b848ee0
bc4d326
9735ac5
9ade843
5e93474
3bb628c
e7770f6
0ef179f
d9f1aa8
e5fc2d3
aed9534
3177709
c7ac0ac
a24c78d
67e1bbd
9d22b47
16e0c8b
062a6ea
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
#![allow(dead_code)] | ||
//! This example shows how a field value may be recorded using the `valuable` | ||
//! crate (https://crates.io/crates/valuable). | ||
//! | ||
//! `valuable` provides a lightweight but flexible way to record structured data, allowing | ||
//! visitors to extract individual fields or elements of structs, maps, arrays, and other | ||
//! nested structures. | ||
//! | ||
//! `tracing`'s support for `valuable` is currently feature flagged. Additionally, `valuable` | ||
//! support is considered an *unstable feature*: in order to use `valuable` with `tracing`, | ||
//! the project must be built with `RUSTFLAGS="--cfg tracing_unstable`. | ||
//! | ||
//! Therefore, when `valuable` support is not enabled, this example falls back to using | ||
//! `fmt::Debug` to record fields that implement `valuable::Valuable`. | ||
#[cfg(tracing_unstable)] | ||
use tracing::field::valuable; | ||
use tracing::{info, info_span}; | ||
use valuable::Valuable; | ||
|
||
#[derive(Clone, Debug, Valuable)] | ||
struct User { | ||
name: String, | ||
age: u32, | ||
address: Address, | ||
} | ||
|
||
#[derive(Clone, Debug, Valuable)] | ||
struct Address { | ||
country: String, | ||
city: String, | ||
street: String, | ||
} | ||
|
||
fn main() { | ||
tracing_subscriber::fmt() | ||
.with_max_level(tracing::Level::TRACE) | ||
.init(); | ||
|
||
let user = User { | ||
name: "Arwen Undomiel".to_string(), | ||
age: 3000, | ||
address: Address { | ||
country: "Middle Earth".to_string(), | ||
city: "Rivendell".to_string(), | ||
street: "leafy lane".to_string(), | ||
}, | ||
}; | ||
|
||
// If the `valuable` feature is enabled, record `user` using its' | ||
// `valuable::Valuable` implementation: | ||
#[cfg(tracing_unstable)] | ||
let span = info_span!("Processing", user = valuable(&user)); | ||
|
||
// Otherwise, record `user` using its `fmt::Debug` implementation: | ||
#[cfg(not(tracing_unstable))] | ||
let span = info_span!("Processing", user = ?user); | ||
|
||
let _handle = span.enter(); | ||
info!("Nothing to do"); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#[cfg(tracing_unstable)] | ||
mod app { | ||
use std::collections::HashMap; | ||
use tracing::field::valuable; | ||
use tracing::{info, info_span, instrument}; | ||
use valuable::Valuable; | ||
|
||
#[derive(Valuable)] | ||
struct Headers<'a> { | ||
headers: HashMap<&'a str, &'a str>, | ||
} | ||
|
||
// Current there's no way to automatically apply valuable to a type, so we need to make use of | ||
// the fields argument for instrument | ||
#[instrument(fields(headers=valuable(&headers)))] | ||
fn process(headers: Headers) { | ||
info!("Handle request") | ||
} | ||
|
||
pub fn run() { | ||
let headers = [ | ||
("content-type", "application/json"), | ||
("content-length", "568"), | ||
("server", "github.com"), | ||
] | ||
.iter() | ||
.cloned() | ||
.collect::<HashMap<_, _>>(); | ||
|
||
let http_headers = Headers { headers }; | ||
|
||
process(http_headers); | ||
} | ||
} | ||
|
||
fn main() { | ||
tracing_subscriber::fmt() | ||
.with_max_level(tracing::Level::TRACE) | ||
.init(); | ||
|
||
#[cfg(tracing_unstable)] | ||
app::run(); | ||
#[cfg(not(tracing_unstable))] | ||
println!("Nothing to do, this example needs --cfg=tracing_unstable to run"); | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -184,6 +184,15 @@ pub struct Iter { | |||||||||||||||
/// [`Event`]: ../event/struct.Event.html | ||||||||||||||||
/// [`ValueSet`]: struct.ValueSet.html | ||||||||||||||||
pub trait Visit { | ||||||||||||||||
/// Visits an arbitrary type implementing the [`valuable`] crate's `Valuable` trait. | ||||||||||||||||
/// | ||||||||||||||||
/// [`valuable`]: https://docs.rs/valuable | ||||||||||||||||
#[cfg(all(tracing_unstable, feature = "valuable"))] | ||||||||||||||||
xd009642 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
#[cfg_attr(docsrs, doc(cfg(all(tracing_unstable, feature = "valuable"))))] | ||||||||||||||||
fn record_value(&mut self, field: &Field, value: &dyn valuable::Valuable) { | ||||||||||||||||
self.record_debug(field, &value) | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
/// Visit a double-precision floating point value. | ||||||||||||||||
fn record_f64(&mut self, field: &Field, value: f64) { | ||||||||||||||||
self.record_debug(field, &value) | ||||||||||||||||
|
@@ -249,6 +258,14 @@ pub struct DisplayValue<T: fmt::Display>(T); | |||||||||||||||
#[derive(Clone)] | ||||||||||||||||
pub struct DebugValue<T: fmt::Debug>(T); | ||||||||||||||||
|
||||||||||||||||
/// A `Value` which serializes using [`Valuable`]. | ||||||||||||||||
/// | ||||||||||||||||
/// [`Valuable`]: https://docs.rs/valuable/latest/valuable/trait.Valuable.html | ||||||||||||||||
#[derive(Clone)] | ||||||||||||||||
#[cfg(all(tracing_unstable, feature = "valuable"))] | ||||||||||||||||
xd009642 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
#[cfg_attr(docsrs, doc(cfg(all(tracing_unstable, feature = "valuable"))))] | ||||||||||||||||
pub struct ValuableValue<T: valuable::Valuable>(T); | ||||||||||||||||
|
||||||||||||||||
/// Wraps a type implementing `fmt::Display` as a `Value` that can be | ||||||||||||||||
/// recorded using its `Display` implementation. | ||||||||||||||||
pub fn display<T>(t: T) -> DisplayValue<T> | ||||||||||||||||
|
@@ -267,6 +284,19 @@ where | |||||||||||||||
DebugValue(t) | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
/// Wraps a type implementing [`Valuable`] as a `Value` that | ||||||||||||||||
/// can be recorded using its `Valuable` implementation. | ||||||||||||||||
/// | ||||||||||||||||
/// [`Valuable`]: https://docs.rs/valuable/latest/valuable/trait.Valuable.html | ||||||||||||||||
#[cfg(all(tracing_unstable, feature = "valuable"))] | ||||||||||||||||
xd009642 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
#[cfg_attr(docsrs, doc(cfg(all(tracing_unstable, feature = "valuable"))))] | ||||||||||||||||
pub fn valuable<T>(t: T) -> ValuableValue<T> | ||||||||||||||||
xd009642 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
where | ||||||||||||||||
T: valuable::Valuable, | ||||||||||||||||
{ | ||||||||||||||||
ValuableValue(t) | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
// ===== impl Visit ===== | ||||||||||||||||
|
||||||||||||||||
impl<'a, 'b> Visit for fmt::DebugStruct<'a, 'b> { | ||||||||||||||||
|
@@ -539,6 +569,27 @@ impl<T: fmt::Debug> fmt::Debug for DebugValue<T> { | |||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
// ===== impl ValuableValue ===== | ||||||||||||||||
|
||||||||||||||||
#[cfg(all(tracing_unstable, feature = "valuable"))] | ||||||||||||||||
impl<T: valuable::Valuable> crate::sealed::Sealed for ValuableValue<T> {} | ||||||||||||||||
|
||||||||||||||||
#[cfg(all(tracing_unstable, feature = "valuable"))] | ||||||||||||||||
#[cfg_attr(docsrs, doc(cfg(all(tracing_unstable, feature = "valuable"))))] | ||||||||||||||||
impl<T: valuable::Valuable> Value for ValuableValue<T> { | ||||||||||||||||
fn record(&self, key: &Field, visitor: &mut dyn Visit) { | ||||||||||||||||
visitor.record_value(key, &self.0) | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a potential thought, although i'm not sure whether or not it's necessary:
Suggested change
I'm not totally sure if this is the right approach or not, but the thought process here is that visitors that are aware of |
||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
#[cfg(all(tracing_unstable, feature = "valuable"))] | ||||||||||||||||
xd009642 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
#[cfg_attr(docsrs, doc(cfg(all(tracing_unstable, feature = "valuable"))))] | ||||||||||||||||
impl<T: valuable::Valuable> fmt::Debug for ValuableValue<T> { | ||||||||||||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||||||||||||||||
write!(f, "{:?}", &self.0 as &dyn valuable::Valuable) | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
impl crate::sealed::Sealed for Empty {} | ||||||||||||||||
impl Value for Empty { | ||||||||||||||||
#[inline] | ||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this causes cargo to download the
valuable
crate even though it isn't actually used withouttracing_unstable