diff --git a/lib/codecs/src/encoding/config.rs b/lib/codecs/src/encoding/config.rs index f40f70cba..8059432c5 100644 --- a/lib/codecs/src/encoding/config.rs +++ b/lib/codecs/src/encoding/config.rs @@ -173,6 +173,7 @@ where #[cfg(test)] mod tests { use super::*; + use crate::encoding::format::json::JsonSerializerConfig; use crate::encoding::TimestampFormat; use event::log::parse_value_path; @@ -188,7 +189,7 @@ except_fields: - ignore_me timestamp_format: unix "##, - SerializerConfig::Json, + SerializerConfig::Json(JsonSerializerConfig { pretty: false }), Transformer::new( Some(vec![parse_value_path("a.b[0]").unwrap()]), Some(vec![parse_value_path("ignore_me").unwrap()]), diff --git a/lib/codecs/src/encoding/format/json.rs b/lib/codecs/src/encoding/format/json.rs index fed408e4f..1fa8b55eb 100644 --- a/lib/codecs/src/encoding/format/json.rs +++ b/lib/codecs/src/encoding/format/json.rs @@ -1,17 +1,30 @@ use bytes::{BufMut, BytesMut}; +use configurable::Configurable; use event::Event; +use serde::{Deserialize, Serialize}; use tokio_util::codec::Encoder; use super::SerializeError; +/// Config used to build a `JsonSerializer` +#[derive(Clone, Configurable, Debug, Deserialize, Serialize)] +pub struct JsonSerializerConfig { + /// Whether to use pretty JSON formatting. + #[serde(default)] + pub pretty: bool, +} + /// Serializer that converts an `Event` to bytes using the JSON format. #[derive(Clone, Debug)] -pub struct JsonSerializer; +pub struct JsonSerializer { + /// Whether to use pretty JSON formatting. + pub pretty: bool, +} impl JsonSerializer { /// Creates a new `JsonSerializer` - pub const fn new() -> Self { - JsonSerializer + pub const fn new(pretty: bool) -> Self { + JsonSerializer { pretty } } } @@ -21,10 +34,18 @@ impl Encoder for JsonSerializer { fn encode(&mut self, event: Event, dst: &mut BytesMut) -> Result<(), Self::Error> { let writer = dst.writer(); - match event { - Event::Log(log) => serde_json::to_writer(writer, &log), - Event::Metric(metric) => serde_json::to_writer(writer, &metric), - Event::Trace(trace) => serde_json::to_writer(writer, &trace), + if self.pretty { + match event { + Event::Log(log) => serde_json::to_writer_pretty(writer, &log), + Event::Metric(metric) => serde_json::to_writer_pretty(writer, &metric), + Event::Trace(trace) => serde_json::to_writer_pretty(writer, &trace), + } + } else { + match event { + Event::Log(log) => serde_json::to_writer(writer, &log), + Event::Metric(metric) => serde_json::to_writer(writer, &metric), + Event::Trace(trace) => serde_json::to_writer(writer, &trace), + } } .map_err(Into::into) } @@ -41,7 +62,7 @@ mod tests { let event = Event::from(fields!( "foo" => "bar" )); - let mut serializer = JsonSerializer; + let mut serializer = JsonSerializer::new(false); let mut bytes = BytesMut::new(); serializer.encode(event, &mut bytes).unwrap(); diff --git a/lib/codecs/src/encoding/mod.rs b/lib/codecs/src/encoding/mod.rs index e97459328..b6610bed6 100644 --- a/lib/codecs/src/encoding/mod.rs +++ b/lib/codecs/src/encoding/mod.rs @@ -31,6 +31,7 @@ pub use framing::{ pub use transformer::{TimestampFormat, Transformer}; use super::FramingError; +pub use crate::encoding::format::json::JsonSerializerConfig; /// The error returned when serializing a structured event into bytes. #[derive(Debug)] @@ -82,11 +83,14 @@ impl Display for SerializeError { #[serde(rename_all = "snake_case")] pub enum SerializerConfig { /// Configures the `JsonSerializer` - Json, + Json(JsonSerializerConfig), + /// Configures the `LogfmtSerializer` Logfmt, + /// Configures the `NativeJsonSerializer` NativeJson, + /// Configures the `TextSerializer` Text, } @@ -95,7 +99,7 @@ impl SerializerConfig { /// Build the `Serializer` with this configuration. pub fn build(&self) -> Serializer { match self { - SerializerConfig::Json => Serializer::Json(JsonSerializer::new()), + SerializerConfig::Json(config) => Serializer::Json(JsonSerializer::new(config.pretty)), SerializerConfig::Logfmt => Serializer::Logfmt(LogfmtSerializer::new()), SerializerConfig::NativeJson => Serializer::Native(NativeJsonSerializer::new()), SerializerConfig::Text => Serializer::Text(TextSerializer::new()), diff --git a/lib/framework/src/sink/util/encoding.rs b/lib/framework/src/sink/util/encoding.rs index 0937aca23..1baf4ffa5 100644 --- a/lib/framework/src/sink/util/encoding.rs +++ b/lib/framework/src/sink/util/encoding.rs @@ -178,7 +178,7 @@ mod tests { Transformer::default(), codecs::Encoder::::new( CharacterDelimitedEncoder::new(b',').into(), - JsonSerializer.into(), + JsonSerializer { pretty: false }.into(), ), ); diff --git a/src/sinks/loki/sink.rs b/src/sinks/loki/sink.rs index bb95d2797..6946555e7 100644 --- a/src/sinks/loki/sink.rs +++ b/src/sinks/loki/sink.rs @@ -424,7 +424,7 @@ mod tests { fn encoder_no_labels() { let mut encoder = EventEncoder { key_partitioner: KeyPartitioner::new(None), - encoder: Encoder::<()>::new(JsonSerializer::new().into()), + encoder: Encoder::<()>::new(JsonSerializer::new(false).into()), transformer: Transformer::default(), labels: HashMap::default(), remove_label_fields: false, @@ -460,7 +460,7 @@ mod tests { let mut encoder = EventEncoder { key_partitioner: KeyPartitioner::new(None), - encoder: Encoder::<()>::new(JsonSerializer::new().into()), + encoder: Encoder::<()>::new(JsonSerializer::new(false).into()), transformer: Transformer::default(), labels, remove_label_fields: false, @@ -485,7 +485,7 @@ mod tests { fn encoder_no_ts() { let mut encoder = EventEncoder { key_partitioner: KeyPartitioner::new(None), - encoder: Encoder::<()>::new(JsonSerializer::new().into()), + encoder: Encoder::<()>::new(JsonSerializer::new(false).into()), transformer: Transformer::default(), labels: HashMap::default(), remove_label_fields: false, @@ -514,7 +514,7 @@ mod tests { let mut encoder = EventEncoder { key_partitioner: KeyPartitioner::new(None), - encoder: Encoder::<()>::new(JsonSerializer::new().into()), + encoder: Encoder::<()>::new(JsonSerializer::new(false).into()), transformer: Transformer::default(), labels, remove_label_fields: true, @@ -533,7 +533,7 @@ mod tests { async fn filter_encoder_drop() { let mut encoder = EventEncoder { key_partitioner: KeyPartitioner::new(None), - encoder: Encoder::<()>::new(JsonSerializer::new().into()), + encoder: Encoder::<()>::new(JsonSerializer::new(false).into()), transformer: Transformer::default(), labels: HashMap::default(), remove_label_fields: false, diff --git a/tests/syslog.rs b/tests/syslog.rs index b2bc46300..97ef13646 100644 --- a/tests/syslog.rs +++ b/tests/syslog.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use std::fmt; use std::str::FromStr; -use codecs::encoding::{FramingConfig, SerializerConfig}; +use codecs::encoding::{FramingConfig, JsonSerializerConfig, SerializerConfig}; use codecs::EncodingConfigWithFraming; use framework::sink::util::tcp::TcpSinkConfig; use framework::testing::CountReceiver; @@ -165,7 +165,7 @@ fn tcp_json_sink(address: String) -> Config { socket::Mode::Tcp(TcpSinkConfig::from_address(address)), EncodingConfigWithFraming::new( Some(FramingConfig::NewlineDelimited), - SerializerConfig::Json, + SerializerConfig::Json(JsonSerializerConfig { pretty: false }), Default::default(), ), )