Advertisement
Guest User

Untitled

a guest
Jul 15th, 2019
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.47 KB | None | 0 0
  1. use std::fmt;
  2.  
  3. use log::kv::{self, Source, value::{self, Fill}};
  4.  
  5. use tracing::{Value, Field, field::{self, Visit}};
  6.  
  7. #[doc(hidden)]
  8. pub struct LogField<'kvs>(&'kvs Field, &'kvs dyn Value);
  9.  
  10. impl fmt::Debug for LogField<'_> {
  11. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  12. let mut visitor = f.debug_tuple("");
  13. self.visit(&mut visitor)?;
  14. visitor.finish()
  15. }
  16. }
  17.  
  18. impl Source for LogField<'_> {
  19. fn visit<'kvs>(&'kvs self, visitor: &mut dyn kv::Visitor<'kvs>) -> Result<(), kv::Error> {
  20. visitor.visit_pair(kv::Key::from_str(self.0.as_ref()), kv::Value::from_fill(self))
  21. }
  22. }
  23.  
  24. /*
  25. This `Fill` trait lets us capture a value that might not be able to produce
  26. its concrete representation for the lifetime `log` requires of its values.
  27.  
  28. This is an issue here because `tracing`'s record API essentially 'forgets'
  29. the lifetime of the value being recorded. As an example, to record some
  30. `Debug`, we go from:
  31.  
  32. ```
  33. &'kvs tracing::Value -> tracing::Visit::record_debug -> &'_ Debug
  34. ```
  35.  
  36. while in `log` we need to go from:
  37.  
  38. ```
  39. &'kvs log::kv::Source -> log::kv::Visitor<'kvs>::visit_pair -> &'kvs Debug -> log::kv::Value<'kvs>;
  40. ```
  41.  
  42. so that values can be tied to the lifetime of their source and outlive
  43. a single call to `log::kv::Source::visit`. The lifetime of the `&Debug`
  44. we can pull from `tracing` simply doesn't match up with the lifetime we
  45. need in `log`.
  46.  
  47. So this trait gives us a place to host the code that translates a `tracing::Value`
  48. into a `log::Value`, and doesn't require the lifetime of the concrete value
  49. materialized by `tracing` to satisfy the lifetime needed by `log`.
  50. */
  51. impl<'kvs> Fill for LogField<'kvs> {
  52. fn fill(&self, slot: value::Slot) -> Result<(), value::Error> {
  53. struct VisitValue<'slot> {
  54. slot: value::Slot<'slot>,
  55. err: Option<value::Error>,
  56. }
  57.  
  58. impl VisitValue<'_> {
  59. fn record(&mut self, value: kv::Value) {
  60. if let Err(err) = self.slot.fill(value) {
  61. self.err = Some(err);
  62. }
  63. }
  64. }
  65.  
  66. impl Visit for VisitValue<'_> {
  67. fn record_i64(&mut self, _field: &Field, value: i64) {
  68. self.record(value.into());
  69. }
  70.  
  71. fn record_u64(&mut self, _field: &Field, value: u64) {
  72. self.record(value.into());
  73. }
  74.  
  75. fn record_bool(&mut self, _field: &Field, value: bool) {
  76. self.record(value.into());
  77. }
  78.  
  79. fn record_str(&mut self, _field: &Field, value: &str) {
  80. self.record(value.into());
  81. }
  82.  
  83. fn record_debug(&mut self, _field: &Field, value: &dyn fmt::Debug) {
  84. self.record(kv::Value::from_debug(&value));
  85. }
  86. }
  87.  
  88. let mut visit = VisitValue {
  89. slot,
  90. err: None,
  91. };
  92.  
  93. self.1.record(self.0, &mut visit);
  94.  
  95. if let Some(err) = visit.err {
  96. Err(err)
  97. } else {
  98. Ok(())
  99. }
  100. }
  101. }
  102.  
  103. fn example_record(mut iter: field::Iter) {
  104. log::Record::builder()
  105. .key_values(&(&[
  106. LogField(
  107. &iter
  108. .next()
  109. .expect("FieldSet corrupted (this is a bug)"),
  110. &42 as &dyn Value,
  111. ),
  112. LogField(
  113. &iter
  114. .next()
  115. .expect("FieldSet corrupted (this is a bug)"),
  116. &false as &dyn Value,
  117. ),
  118. ] as &[_]))
  119. .build();
  120. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement