layer.rs 7.4 KB

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