qlog: add optional pretty-printing for JSON-SEQ streaming One of the features of JSON-SEQ is that it can support newlines embedded in records. Prior to this commit, the qlog streamer only supported a "condensed mode" of writing events on a single JSON line, which can affect the usability in some circumstances. This change adds support for discretionary logging of each individual event using condensed or pretty formats. A new set of "_pretty" suffixed methods are provided to allow callers to select the format, without breaking backwards capability. This design also mimics serde's approach.
diff --git a/qlog/src/streamer.rs b/qlog/src/streamer.rs index 16761b3..27063b8 100644 --- a/qlog/src/streamer.rs +++ b/qlog/src/streamer.rs
@@ -146,10 +146,34 @@ self.add_event_with_instant(event, now) } + /// Writes a serializable to a pretty-printed JSON-SEQ record using + /// [std::time::Instant::now()]. + pub fn add_event_now_pretty<E: Serialize + Eventable>( + &mut self, event: E, + ) -> Result<()> { + let now = std::time::Instant::now(); + + self.add_event_with_instant_pretty(event, now) + } + /// Writes a serializable to a JSON-SEQ record using the provided /// [std::time::Instant]. pub fn add_event_with_instant<E: Serialize + Eventable>( - &mut self, mut event: E, now: std::time::Instant, + &mut self, event: E, now: std::time::Instant, + ) -> Result<()> { + self.event_with_instant(event, now, false) + } + + /// Writes a serializable to a pretty-printed JSON-SEQ record using the + /// provided [std::time::Instant]. + pub fn add_event_with_instant_pretty<E: Serialize + Eventable>( + &mut self, event: E, now: std::time::Instant, + ) -> Result<()> { + self.event_with_instant(event, now, true) + } + + fn event_with_instant<E: Serialize + Eventable>( + &mut self, mut event: E, now: std::time::Instant, pretty: bool, ) -> Result<()> { if self.state != StreamerState::Ready { return Err(Error::InvalidState); @@ -168,7 +192,11 @@ let rel_time = dur.as_secs_f32() * 1000.0; event.set_time(rel_time); - self.add_event(event) + if pretty { + self.add_event_pretty(event) + } else { + self.add_event(event) + } } /// Writes an [Event] based on the provided [EventData] to a JSON-SEQ record @@ -177,6 +205,14 @@ self.add_event_data_ex_now(event_data, Default::default()) } + /// Writes an [Event] based on the provided [EventData] to a pretty-printed + /// JSON-SEQ record at time [std::time::Instant::now()]. + pub fn add_event_data_now_pretty( + &mut self, event_data: EventData, + ) -> Result<()> { + self.add_event_data_ex_now_pretty(event_data, Default::default()) + } + /// Writes an [Event] based on the provided [EventData] and [ExData] to a /// JSON-SEQ record at time [std::time::Instant::now()]. pub fn add_event_data_ex_now( @@ -187,6 +223,16 @@ self.add_event_data_ex_with_instant(event_data, ex_data, now) } + /// Writes an [Event] based on the provided [EventData] and [ExData] to a + /// pretty-printed JSON-SEQ record at time [std::time::Instant::now()]. + pub fn add_event_data_ex_now_pretty( + &mut self, event_data: EventData, ex_data: ExData, + ) -> Result<()> { + let now = std::time::Instant::now(); + + self.add_event_data_ex_with_instant_pretty(event_data, ex_data, now) + } + /// Writes an [Event] based on the provided [EventData] and /// [std::time::Instant] to a JSON-SEQ record. pub fn add_event_data_with_instant( @@ -195,12 +241,40 @@ self.add_event_data_ex_with_instant(event_data, Default::default(), now) } + /// Writes an [Event] based on the provided [EventData] and + /// [std::time::Instant] to a pretty-printed JSON-SEQ record. + pub fn add_event_data_with_instant_pretty( + &mut self, event_data: EventData, now: std::time::Instant, + ) -> Result<()> { + self.add_event_data_ex_with_instant_pretty( + event_data, + Default::default(), + now, + ) + } + /// Writes an [Event] based on the provided [EventData], [ExData], and /// [std::time::Instant] to a JSON-SEQ record. pub fn add_event_data_ex_with_instant( &mut self, event_data: EventData, ex_data: ExData, now: std::time::Instant, ) -> Result<()> { + self.event_data_ex_with_instant(event_data, ex_data, now, false) + } + + // Writes an [Event] based on the provided [EventData], [ExData], and + /// [std::time::Instant] to a pretty-printed JSON-SEQ record. + pub fn add_event_data_ex_with_instant_pretty( + &mut self, event_data: EventData, ex_data: ExData, + now: std::time::Instant, + ) -> Result<()> { + self.event_data_ex_with_instant(event_data, ex_data, now, true) + } + + fn event_data_ex_with_instant( + &mut self, event_data: EventData, ex_data: ExData, + now: std::time::Instant, pretty: bool, + ) -> Result<()> { if self.state != StreamerState::Ready { return Err(Error::InvalidState); } @@ -219,13 +293,32 @@ let rel_time = dur.as_secs_f32() * 1000.0; let event = Event::with_time_ex(rel_time, event_data, ex_data); - self.add_event(event) + if pretty { + self.add_event_pretty(event) + } else { + self.add_event(event) + } } /// Writes a JSON-SEQ-serialized [Event] using the provided [Event]. pub fn add_event<E: Serialize + Eventable>( &mut self, event: E, ) -> Result<()> { + self.write_event(event, false) + } + + /// Writes a pretty-printed JSON-SEQ-serialized [Event] using the provided + /// [Event]. + pub fn add_event_pretty<E: Serialize + Eventable>( + &mut self, event: E, + ) -> Result<()> { + self.write_event(event, true) + } + + /// Writes a JSON-SEQ-serialized [Event] using the provided [Event]. + fn write_event<E: Serialize + Eventable>( + &mut self, event: E, pretty: bool, + ) -> Result<()> { if self.state != StreamerState::Ready { return Err(Error::InvalidState); } @@ -235,8 +328,13 @@ } self.writer.as_mut().write_all(b"")?; - serde_json::to_writer(self.writer.as_mut(), &event) - .map_err(|_| Error::Done)?; + if pretty { + serde_json::to_writer_pretty(self.writer.as_mut(), &event) + .map_err(|_| Error::Done)?; + } else { + serde_json::to_writer(self.writer.as_mut(), &event) + .map_err(|_| Error::Done)?; + } self.writer.as_mut().write_all(b"\n")?; Ok(())