layer.rs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. use serde::ser::{SerializeMap, Serializer};
  2. use serde_json::Value;
  3. use std::{fmt, io::Write};
  4. use tracing::{Event, Id, Subscriber};
  5. use tracing_bunyan_formatter::JsonStorage;
  6. use tracing_core::{metadata::Level, span::Attributes};
  7. use tracing_subscriber::{fmt::MakeWriter, layer::Context, registry::SpanRef, Layer};
  8. const LEVEL: &str = "level";
  9. const TIME: &str = "time";
  10. const MESSAGE: &str = "msg";
  11. const FLOWY_RESERVED_FIELDS: [&str; 3] = [LEVEL, TIME, MESSAGE];
  12. pub struct FlowyFormattingLayer<W: MakeWriter + 'static> {
  13. make_writer: W,
  14. with_target: bool,
  15. }
  16. impl<W: MakeWriter + 'static> FlowyFormattingLayer<W> {
  17. pub fn new(make_writer: W) -> Self {
  18. Self {
  19. make_writer,
  20. with_target: false,
  21. }
  22. }
  23. fn serialize_flowy_core_fields(
  24. &self,
  25. map_serializer: &mut impl SerializeMap<Error = serde_json::Error>,
  26. message: &str,
  27. level: &Level,
  28. ) -> Result<(), std::io::Error> {
  29. map_serializer.serialize_entry(MESSAGE, &message)?;
  30. map_serializer.serialize_entry(LEVEL, &format!("{}", level))?;
  31. map_serializer.serialize_entry(TIME, &chrono::Utc::now().timestamp())?;
  32. Ok(())
  33. }
  34. fn serialize_span<S: Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>>(
  35. &self,
  36. span: &SpanRef<S>,
  37. ty: Type,
  38. ) -> Result<Vec<u8>, std::io::Error> {
  39. let mut buffer = Vec::new();
  40. let mut serializer = serde_json::Serializer::new(&mut buffer);
  41. let mut map_serializer = serializer.serialize_map(None)?;
  42. let message = format_span_context(&span, ty);
  43. self.serialize_flowy_core_fields(&mut map_serializer, &message, span.metadata().level())?;
  44. if self.with_target {
  45. map_serializer.serialize_entry("target", &span.metadata().target())?;
  46. }
  47. map_serializer.serialize_entry("line", &span.metadata().line())?;
  48. map_serializer.serialize_entry("file", &span.metadata().file())?;
  49. let extensions = span.extensions();
  50. if let Some(visitor) = extensions.get::<JsonStorage>() {
  51. for (key, value) in visitor.values() {
  52. if !FLOWY_RESERVED_FIELDS.contains(key) {
  53. map_serializer.serialize_entry(key, value)?;
  54. } else {
  55. tracing::debug!("{} is a reserved field in the bunyan log format. Skipping it.", key);
  56. }
  57. }
  58. }
  59. map_serializer.end()?;
  60. Ok(buffer)
  61. }
  62. fn emit(&self, mut buffer: Vec<u8>) -> Result<(), std::io::Error> {
  63. buffer.write_all(b"\n")?;
  64. self.make_writer.make_writer().write_all(&buffer)
  65. }
  66. }
  67. /// The type of record we are dealing with: entering a span, exiting a span, an
  68. /// event.
  69. #[derive(Clone, Debug)]
  70. pub enum Type {
  71. EnterSpan,
  72. ExitSpan,
  73. Event,
  74. }
  75. impl fmt::Display for Type {
  76. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  77. let repr = match self {
  78. Type::EnterSpan => "START",
  79. Type::ExitSpan => "END",
  80. Type::Event => "EVENT",
  81. };
  82. write!(f, "{}", repr)
  83. }
  84. }
  85. fn format_span_context<S: Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>>(span: &SpanRef<S>, ty: Type) -> String {
  86. format!("[⛳ {} - {}]", span.metadata().name().to_uppercase(), ty)
  87. }
  88. fn format_event_message<S: Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>>(
  89. current_span: &Option<SpanRef<S>>,
  90. event: &Event,
  91. event_visitor: &JsonStorage<'_>,
  92. ) -> String {
  93. // Extract the "message" field, if provided. Fallback to the target, if missing.
  94. let mut message = event_visitor
  95. .values()
  96. .get("message")
  97. .map(|v| match v {
  98. Value::String(s) => Some(s.as_str()),
  99. _ => None,
  100. })
  101. .flatten()
  102. .unwrap_or_else(|| event.metadata().target())
  103. .to_owned();
  104. // If the event is in the context of a span, prepend the span name to the
  105. // message.
  106. if let Some(span) = &current_span {
  107. message = format!("{} {}", format_span_context(span, Type::Event), message);
  108. }
  109. message
  110. }
  111. impl<S, W> Layer<S> for FlowyFormattingLayer<W>
  112. where
  113. S: Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>,
  114. W: MakeWriter + 'static,
  115. {
  116. fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
  117. // Events do not necessarily happen in the context of a span, hence
  118. // lookup_current returns an `Option<SpanRef<_>>` instead of a
  119. // `SpanRef<_>`.
  120. let current_span = ctx.lookup_current();
  121. let mut event_visitor = JsonStorage::default();
  122. event.record(&mut event_visitor);
  123. // Opting for a closure to use the ? operator and get more linear code.
  124. let format = || {
  125. let mut buffer = Vec::new();
  126. let mut serializer = serde_json::Serializer::new(&mut buffer);
  127. let mut map_serializer = serializer.serialize_map(None)?;
  128. let message = format_event_message(&current_span, event, &event_visitor);
  129. self.serialize_flowy_core_fields(&mut map_serializer, &message, event.metadata().level())?;
  130. // Additional metadata useful for debugging
  131. // They should be nested under `src` (see https://github.com/trentm/node-bunyan#src )
  132. // but `tracing` does not support nested values yet
  133. if self.with_target {
  134. map_serializer.serialize_entry("target", event.metadata().target())?;
  135. }
  136. map_serializer.serialize_entry("line", &event.metadata().line())?;
  137. map_serializer.serialize_entry("file", &event.metadata().file())?;
  138. // Add all the other fields associated with the event, expect the message we
  139. // already used.
  140. for (key, value) in event_visitor
  141. .values()
  142. .iter()
  143. .filter(|(&key, _)| key != "message" && !FLOWY_RESERVED_FIELDS.contains(&key))
  144. {
  145. map_serializer.serialize_entry(key, value)?;
  146. }
  147. // Add all the fields from the current span, if we have one.
  148. if let Some(span) = &current_span {
  149. let extensions = span.extensions();
  150. if let Some(visitor) = extensions.get::<JsonStorage>() {
  151. for (key, value) in visitor.values() {
  152. if !FLOWY_RESERVED_FIELDS.contains(key) {
  153. map_serializer.serialize_entry(key, value)?;
  154. } else {
  155. tracing::debug!("{} is a reserved field in the flowy log format. Skipping it.", key);
  156. }
  157. }
  158. }
  159. }
  160. map_serializer.end()?;
  161. Ok(buffer)
  162. };
  163. let result: std::io::Result<Vec<u8>> = format();
  164. if let Ok(formatted) = result {
  165. let _ = self.emit(formatted);
  166. }
  167. }
  168. fn new_span(&self, _attrs: &Attributes, id: &Id, ctx: Context<'_, S>) {
  169. let span = ctx.span(id).expect("Span not found, this is a bug");
  170. if let Ok(serialized) = self.serialize_span(&span, Type::EnterSpan) {
  171. let _ = self.emit(serialized);
  172. }
  173. }
  174. fn on_close(&self, id: Id, ctx: Context<'_, S>) {
  175. let span = ctx.span(&id).expect("Span not found, this is a bug");
  176. if let Ok(serialized) = self.serialize_span(&span, Type::ExitSpan) {
  177. let _ = self.emit(serialized);
  178. }
  179. }
  180. }