From a049e2084c380619065569b51ac86d62a2ce0a52 Mon Sep 17 00:00:00 2001 From: teor Date: Tue, 4 Apr 2023 07:23:11 +1000 Subject: [PATCH] Add a config for writing logs to a file (#6449) --- zebrad/src/components/tracing.rs | 5 +++++ zebrad/src/components/tracing/component.rs | 17 ++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/zebrad/src/components/tracing.rs b/zebrad/src/components/tracing.rs index 0fe61787..8fbfa9ba 100644 --- a/zebrad/src/components/tracing.rs +++ b/zebrad/src/components/tracing.rs @@ -101,6 +101,10 @@ pub struct Config { /// replaced with `.folded` and `.svg` for the respective files. pub flamegraph: Option, + /// If set to a path, write the tracing logs to that path. + /// By default, logs are sent to the terminal standard output. + pub log_file: Option, + /// The use_journald flag sends tracing events to systemd-journald, on Linux /// distributions that use systemd. /// @@ -117,6 +121,7 @@ impl Default for Config { buffer_limit: 128_000, endpoint_addr: None, flamegraph: None, + log_file: None, use_journald: false, } } diff --git a/zebrad/src/components/tracing/component.rs b/zebrad/src/components/tracing/component.rs index 35d26caa..f943e9fb 100644 --- a/zebrad/src/components/tracing/component.rs +++ b/zebrad/src/components/tracing/component.rs @@ -1,5 +1,7 @@ //! The Abscissa component for Zebra's `tracing` implementation. +use std::{fs::File, io::Write}; + use abscissa_core::{Component, FrameworkError, Shutdown}; use tracing_error::ErrorLayer; use tracing_subscriber::{ @@ -17,6 +19,9 @@ use crate::{application::app_version, components::tracing::Config}; #[cfg(feature = "flamegraph")] use super::flame; +/// A type-erased boxed writer that can be sent between threads safely. +pub type BoxWrite = Box; + /// Abscissa component for initializing the `tracing` subsystem pub struct Tracing { /// The installed filter reloading handle, if enabled. @@ -43,16 +48,26 @@ pub struct Tracing { impl Tracing { /// Try to create a new [`Tracing`] component with the given `filter`. + #[allow(clippy::print_stdout, clippy::print_stderr)] pub fn new(config: Config) -> Result { let filter = config.filter.unwrap_or_default(); let flame_root = &config.flamegraph; + let writer = if let Some(log_file) = config.log_file.as_ref() { + println!("running zebra, sending logs to {log_file:?}..."); + let log_file = File::options().append(true).create(true).open(log_file)?; + Box::new(log_file) as BoxWrite + } else { + let stdout = std::io::stdout(); + Box::new(stdout) as BoxWrite + }; + // Builds a lossy NonBlocking logger with a default line limit of 128_000 or an explicit buffer_limit. // The write method queues lines down a bounded channel with this capacity to a worker thread that writes to stdout. // Increments error_counter and drops lines when the buffer is full. let (non_blocking, _guard) = NonBlockingBuilder::default() .buffered_lines_limit(config.buffer_limit.max(100)) - .finish(std::io::stdout()); + .finish(writer); // Only use color if tracing output is being sent to a terminal or if it was explicitly // forced to.