Skip to main content

tale_ndjson/logpatterns/
mod.rs

1//! JSON log patterns and deserialization implementations, plus pretty-printing
2//! for all identified varieties. Also, traits for all of them, so everything
3//! outside this module doesn't have to care what kind of log pattern it is: its
4//! just a printable log.
5
6use std::fmt::Display;
7
8use bytes::BytesMut;
9use serde::Deserialize;
10
11mod columns;
12mod formatting;
13mod logfmt;
14mod patterns;
15mod sourced;
16
17use logfmt::*;
18use patterns::*;
19pub use sourced::SourcedLine;
20
21/// If you can be pretty-printed, you write into a mutable byte buffer.
22/// We don't have any opinions about what you write; pretty is in the eye
23/// of the implementor.
24pub trait PrettyPrintable
25where
26    Self: Display,
27{
28    fn write(&self, buffer: &mut BytesMut) -> usize;
29    fn cells(&self) -> Vec<String>;
30}
31
32/// An enum to help serde deserialize incoming log lines. There are some
33/// we decide are log lines with fields we recognize, and some that are just
34/// json we pretty-print. And then there's plain text.
35/// Ordered from most specific to least specific for serde deserialization.
36#[derive(Debug, Clone, Deserialize)]
37#[serde(untagged, bound(deserialize = "'de: 'a"))]
38pub enum Printable<'a> {
39    Canonical(Box<Canonical<'a>>),
40    Java(Box<Java<'a>>),
41    Message(Box<Message<'a>>),
42    TimeOnly(Timestamped),
43    Json(GenericJson),
44    Logfmt(LogfmtLine),
45    Text(String),
46}
47
48impl<'a> PrettyPrintable for Printable<'a> {
49    fn write(&self, buffer: &mut BytesMut) -> usize {
50        match self {
51            Printable::Canonical(canonical) => canonical.as_ref().write(buffer),
52            Printable::Java(java) => java.as_ref().write(buffer),
53            Printable::Message(message) => message.as_ref().write(buffer),
54            Printable::TimeOnly(timestamped) => timestamped.write(buffer),
55            Printable::Json(generic) => generic.write(buffer),
56            Printable::Logfmt(logfmt) => logfmt.write(buffer),
57            Printable::Text(text) => {
58                buffer.extend_from_slice(text.as_bytes());
59                buffer.len()
60            }
61        }
62    }
63
64    fn cells(&self) -> Vec<String> {
65        match self {
66            Printable::Canonical(canonical) => canonical.as_ref().cells(),
67            Printable::Java(java) => java.as_ref().cells(),
68            Printable::Message(message) => message.as_ref().cells(),
69            Printable::TimeOnly(timestamped) => timestamped.cells(),
70            Printable::Json(generic) => generic.cells(),
71            Printable::Logfmt(logfmt) => logfmt.cells(),
72            Printable::Text(_) => Vec::new(),
73        }
74    }
75}
76
77impl<'a> Display for Printable<'a> {
78    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79        match self {
80            Printable::Canonical(canonical) => canonical.fmt(f),
81            Printable::Java(java) => java.fmt(f),
82            Printable::Message(message) => message.fmt(f),
83            Printable::TimeOnly(timestamped) => timestamped.fmt(f),
84            Printable::Json(generic) => generic.fmt(f),
85            Printable::Logfmt(logfmt) => logfmt.fmt(f),
86            Printable::Text(text) => text.fmt(f),
87        }
88    }
89}