Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::fmt;
- use log::kv::{self, Source, value::{self, Fill}};
- use tracing::{Value, Field, field::{self, Visit}};
- #[doc(hidden)]
- pub struct LogField<'kvs>(&'kvs Field, &'kvs dyn Value);
- impl fmt::Debug for LogField<'_> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let mut visitor = f.debug_tuple("");
- self.visit(&mut visitor)?;
- visitor.finish()
- }
- }
- impl Source for LogField<'_> {
- fn visit<'kvs>(&'kvs self, visitor: &mut dyn kv::Visitor<'kvs>) -> Result<(), kv::Error> {
- visitor.visit_pair(kv::Key::from_str(self.0.as_ref()), kv::Value::from_fill(self))
- }
- }
- /*
- This `Fill` trait lets us capture a value that might not be able to produce
- its concrete representation for the lifetime `log` requires of its values.
- This is an issue here because `tracing`'s record API essentially 'forgets'
- the lifetime of the value being recorded. As an example, to record some
- `Debug`, we go from:
- ```
- &'kvs tracing::Value -> tracing::Visit::record_debug -> &'_ Debug
- ```
- while in `log` we need to go from:
- ```
- &'kvs log::kv::Source -> log::kv::Visitor<'kvs>::visit_pair -> &'kvs Debug -> log::kv::Value<'kvs>;
- ```
- so that values can be tied to the lifetime of their source and outlive
- a single call to `log::kv::Source::visit`. The lifetime of the `&Debug`
- we can pull from `tracing` simply doesn't match up with the lifetime we
- need in `log`.
- So this trait gives us a place to host the code that translates a `tracing::Value`
- into a `log::Value`, and doesn't require the lifetime of the concrete value
- materialized by `tracing` to satisfy the lifetime needed by `log`.
- */
- impl<'kvs> Fill for LogField<'kvs> {
- fn fill(&self, slot: value::Slot) -> Result<(), value::Error> {
- struct VisitValue<'slot> {
- slot: value::Slot<'slot>,
- err: Option<value::Error>,
- }
- impl VisitValue<'_> {
- fn record(&mut self, value: kv::Value) {
- if let Err(err) = self.slot.fill(value) {
- self.err = Some(err);
- }
- }
- }
- impl Visit for VisitValue<'_> {
- fn record_i64(&mut self, _field: &Field, value: i64) {
- self.record(value.into());
- }
- fn record_u64(&mut self, _field: &Field, value: u64) {
- self.record(value.into());
- }
- fn record_bool(&mut self, _field: &Field, value: bool) {
- self.record(value.into());
- }
- fn record_str(&mut self, _field: &Field, value: &str) {
- self.record(value.into());
- }
- fn record_debug(&mut self, _field: &Field, value: &dyn fmt::Debug) {
- self.record(kv::Value::from_debug(&value));
- }
- }
- let mut visit = VisitValue {
- slot,
- err: None,
- };
- self.1.record(self.0, &mut visit);
- if let Some(err) = visit.err {
- Err(err)
- } else {
- Ok(())
- }
- }
- }
- fn example_record(mut iter: field::Iter) {
- log::Record::builder()
- .key_values(&(&[
- LogField(
- &iter
- .next()
- .expect("FieldSet corrupted (this is a bug)"),
- &42 as &dyn Value,
- ),
- LogField(
- &iter
- .next()
- .expect("FieldSet corrupted (this is a bug)"),
- &false as &dyn Value,
- ),
- ] as &[_]))
- .build();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement