Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to provide custom writer to the logger backend #518

Merged
merged 2 commits into from
Nov 7, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions nomos-services/log/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// std
use futures::StreamExt;
use std::fmt::{Debug, Formatter};
use std::io::Write;
use std::net::SocketAddr;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
// crates
use serde::{Deserialize, Serialize};
use tracing::{error, Level};
Expand All @@ -21,6 +24,37 @@ pub struct Logger {
worker_guard: Option<WorkerGuard>,
}

/// This is a wrapper around a writer to allow cloning which is
/// required by contract by Overwatch for a configuration struct
#[derive(Clone)]
pub struct SharedWriter {
inner: Arc<Mutex<Box<dyn Write + Send + Sync>>>,
}

impl Write for SharedWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.inner.lock().unwrap().write(buf)
}

fn flush(&mut self) -> std::io::Result<()> {
self.inner.lock().unwrap().flush()
}
}

impl SharedWriter {
pub fn new<W: Write + Send + Sync + 'static>(writer: W) -> Self {
Self {
inner: Arc::new(Mutex::new(Box::new(writer))),
}
}
}

impl Debug for SharedWriter {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SharedWriter").finish()
}
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum LoggerBackend {
Gelf {
Expand All @@ -32,6 +66,8 @@ pub enum LoggerBackend {
},
Stdout,
Stderr,
#[serde(skip)]
Writer(SharedWriter),
}

#[derive(Clone, Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -121,6 +157,7 @@ impl ServiceCore for Logger {
}
LoggerBackend::Stdout => tracing_appender::non_blocking(std::io::stdout()),
LoggerBackend::Stderr => tracing_appender::non_blocking(std::io::stderr()),
LoggerBackend::Writer(writer) => tracing_appender::non_blocking(writer),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you elaborate on the use case of this writer? For example, sending logs via network to fluentd?

Copy link
Contributor Author

@zeegomo zeegomo Nov 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Main reason was because I wanted to collect logs in the chat app but at the same time control how those are printed to stdout.
I think it could also be useful in tests where instead of dumping logs into a file and then reading you could directly read them on the fly.
This is general enough that it can be used in multiple ways I think

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get it. Thank you for your comment!

};

let layer = tracing_subscriber::fmt::Layer::new()
Expand Down
Loading