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

refactor: layouts and encoders should be nested to appenders #64

Merged
merged 9 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
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
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ fn main() {
Logger::new().dispatch(
Dispatch::new()
.filter(LevelFilter::Trace)
.layout(TextLayout::default())
.append(append::Stdout),
.append(append::Stdout::default()),
)
.apply()
.unwrap();
Expand Down
4 changes: 1 addition & 3 deletions examples/env_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

use logforth::append;
use logforth::filter::EnvFilter;
use logforth::layout::TextLayout;
use logforth::Dispatch;
use logforth::Logger;

Expand All @@ -23,8 +22,7 @@ fn main() {
.dispatch(
Dispatch::new()
.filter(EnvFilter::from_default_env())
.layout(TextLayout::default())
.append(append::Stdout),
.append(append::Stdout::default()),
)
.apply()
.unwrap();
Expand Down
9 changes: 5 additions & 4 deletions examples/fn_layout_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ fn main() {
FilterResult::Reject
}
}))
.layout(CustomLayout::new(|record, f| {
f(format_args!("[system alert] {}", record.args()))
}))
.append(append::Stdout),
.append(
append::Stdout::default().with_layout(CustomLayout::new(|record| {
Ok(format!("[system alert] {}", record.args()).into_bytes())
})),
),
)
.apply()
.unwrap();
Expand Down
3 changes: 1 addition & 2 deletions examples/json_stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ fn main() {
.dispatch(
Dispatch::new()
.filter(LevelFilter::Trace)
.layout(JsonLayout::default())
.append(append::Stdout),
.append(append::Stdout::default().with_layout(JsonLayout::default())),
)
.apply()
.unwrap();
Expand Down
6 changes: 2 additions & 4 deletions examples/rolling_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use logforth::append::rolling_file::RollingFileWriter;
use logforth::append::rolling_file::Rotation;
use logforth::append::Stdout;
use logforth::layout::JsonLayout;
use logforth::layout::TextLayout;
use logforth::Dispatch;
use logforth::Logger;

Expand All @@ -38,10 +37,9 @@ fn main() {
.dispatch(
Dispatch::new()
.filter(LevelFilter::Trace)
.layout(JsonLayout::default())
.append(RollingFile::new(writer)),
.append(RollingFile::new(writer).with_layout(JsonLayout::default()))
.append(Stdout::default()),
)
.dispatch(Dispatch::new().layout(TextLayout::default()).append(Stdout))
.apply()
.unwrap();

Expand Down
11 changes: 2 additions & 9 deletions examples/simple_stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

use log::LevelFilter;
use logforth::append;
use logforth::layout::TextLayout;
use logforth::Dispatch;
use logforth::Logger;

Expand All @@ -23,14 +22,8 @@ fn main() {
.dispatch(
Dispatch::new()
.filter(LevelFilter::Trace)
.layout(TextLayout::default())
.append(append::Stdout),
)
.dispatch(
Dispatch::new()
.filter(LevelFilter::Trace)
.layout(TextLayout::default().no_color())
.append(append::Stderr),
.append(append::Stdout::default())
.append(append::Stderr::default()),
)
.apply()
.unwrap();
Expand Down
4 changes: 3 additions & 1 deletion src/append/fastrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ use crate::layout::collect_kvs;

/// An appender that adds log records to fastrace as an event associated to the current span.
#[derive(Default, Debug, Clone)]
pub struct FastraceEvent;
pub struct FastraceEvent {
_private: (), // suppress structure literal syntax
}

impl Append for FastraceEvent {
fn append(&self, record: &Record) -> anyhow::Result<()> {
Expand Down
8 changes: 0 additions & 8 deletions src/append/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ pub use self::opentelemetry::OpentelemetryLog;
pub use self::rolling_file::RollingFile;
pub use self::stdio::Stderr;
pub use self::stdio::Stdout;
use crate::layout::IdenticalLayout;
use crate::layout::Layout;

#[cfg(feature = "fastrace")]
mod fastrace;
Expand All @@ -41,10 +39,4 @@ pub trait Append: fmt::Debug + Send + Sync + 'static {

/// Flushes any buffered records.
fn flush(&self) {}

/// Default layout to use when [`Dispatch`][crate::logger::Dispatch] does not configure a
/// preferred layout.
fn default_layout(&self) -> Layout {
Layout::Identical(IdenticalLayout)
}
}
49 changes: 32 additions & 17 deletions src/append/opentelemetry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use opentelemetry_sdk::logs::LogRecord;
use opentelemetry_sdk::logs::LoggerProvider;

use crate::append::Append;
use crate::Layout;

/// The communication protocol to opentelemetry that used when exporting data.
///
Expand All @@ -52,6 +53,7 @@ pub struct OpentelemetryLogBuilder {
endpoint: String,
protocol: Protocol,
labels: Vec<(Cow<'static, str>, Cow<'static, str>)>,
layout: Option<Layout>,
}

impl OpentelemetryLogBuilder {
Expand All @@ -62,6 +64,7 @@ impl OpentelemetryLogBuilder {
endpoint: otlp_endpoint.into(),
protocol: Protocol::Grpc,
labels: vec![],
layout: None,
}
}

Expand Down Expand Up @@ -100,13 +103,20 @@ impl OpentelemetryLogBuilder {
self
}

/// Set the layout to use when formatting log records.
pub fn layout(mut self, layout: impl Into<Layout>) -> Self {
self.layout = Some(layout.into());
self
}

/// Build the [`OpentelemetryLog`] appender.
pub fn build(self) -> Result<OpentelemetryLog, opentelemetry::logs::LogError> {
let OpentelemetryLogBuilder {
name,
endpoint,
protocol,
labels,
layout,
} = self;

let collector_timeout =
Expand Down Expand Up @@ -140,6 +150,7 @@ impl OpentelemetryLogBuilder {

Ok(OpentelemetryLog {
name,
layout,
library,
provider,
})
Expand All @@ -150,30 +161,34 @@ impl OpentelemetryLogBuilder {
#[derive(Debug)]
pub struct OpentelemetryLog {
name: String,
layout: Option<Layout>,
library: Arc<InstrumentationLibrary>,
provider: LoggerProvider,
}

impl Append for OpentelemetryLog {
fn append(&self, log_record: &Record) -> anyhow::Result<()> {
fn append(&self, record: &Record) -> anyhow::Result<()> {
let provider = self.provider.clone();
let logger = provider.library_logger(self.library.clone());

let mut record = LogRecord::default();
record.observed_timestamp = Some(SystemTime::now());
record.severity_number = Some(log_level_to_otel_severity(log_record.level()));
record.severity_text = Some(log_record.level().as_str());
record.target = Some(log_record.target().to_string().into());
record.body = Some(AnyValue::from(log_record.args().to_string()));

if let Some(module_path) = log_record.module_path() {
record.add_attribute("module_path", module_path.to_string());
let mut log_record_ = LogRecord::default();
log_record_.observed_timestamp = Some(SystemTime::now());
log_record_.severity_number = Some(log_level_to_otel_severity(record.level()));
log_record_.severity_text = Some(record.level().as_str());
log_record_.target = Some(record.target().to_string().into());
log_record_.body = Some(AnyValue::Bytes(Box::new(match self.layout.as_ref() {
None => record.args().to_string().into_bytes(),
Some(layout) => layout.format(record)?,
})));

if let Some(module_path) = record.module_path() {
log_record_.add_attribute("module_path", module_path.to_string());
}
if let Some(file) = log_record.file() {
record.add_attribute("file", file.to_string());
if let Some(file) = record.file() {
log_record_.add_attribute("file", file.to_string());
}
if let Some(line) = log_record.line() {
record.add_attribute("line", line);
if let Some(line) = record.line() {
log_record_.add_attribute("line", line);
}

struct KvExtractor<'a> {
Expand All @@ -193,11 +208,11 @@ impl Append for OpentelemetryLog {
}

let mut extractor = KvExtractor {
record: &mut record,
record: &mut log_record_,
};
log_record.key_values().visit(&mut extractor).ok();
record.key_values().visit(&mut extractor).ok();

logger.emit(record);
logger.emit(log_record_);
Ok(())
}

Expand Down
20 changes: 18 additions & 2 deletions src/append/rolling_file/append.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,39 @@ use log::Record;

use crate::append::rolling_file::non_blocking::NonBlocking;
use crate::append::Append;
use crate::layout::TextLayout;
use crate::Layout;

/// An appender that writes log records to a file that rolls over when it reaches a certain date
/// time.
#[derive(Debug)]
pub struct RollingFile {
layout: Layout,
writer: NonBlocking,
}

impl RollingFile {
/// Creates a new `RollingFile` appender that writes log records to the given writer.
///
/// This appender by default uses [`TextLayout`] to format log records as bytes.
pub fn new(writer: NonBlocking) -> Self {
Self { writer }
Self {
layout: TextLayout::default().no_color().into(),
writer,
}
}

/// Sets the layout used to format log records as bytes.
pub fn with_layout(mut self, layout: impl Into<Layout>) -> Self {
self.layout = layout.into();
self
}
}

impl Append for RollingFile {
fn append(&self, record: &Record) -> anyhow::Result<()> {
let bytes = format!("{}\n", record.args()).into_bytes();
let mut bytes = self.layout.format(record)?;
bytes.push(b'\n');
self.writer.send(bytes)?;
Ok(())
}
Expand Down
52 changes: 46 additions & 6 deletions src/append/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,35 @@
use std::io::Write;

use crate::append::Append;
use crate::layout::TextLayout;
use crate::Layout;

/// An appender that prints log records to stdout.
#[derive(Default, Debug)]
pub struct Stdout;
#[derive(Debug)]
pub struct Stdout {
layout: Layout,
}

impl Default for Stdout {
fn default() -> Self {
Self {
layout: TextLayout::default().into(),
}
}
}

impl Stdout {
/// Creates a new `Stdout` appender with the given layout.
pub fn with_layout(mut self, layout: impl Into<Layout>) -> Self {
self.layout = layout.into();
self
}
}

impl Append for Stdout {
fn append(&self, record: &log::Record) -> anyhow::Result<()> {
let bytes = format!("{}\n", record.args()).into_bytes();
let mut bytes = self.layout.format(record)?;
bytes.push(b'\n');
std::io::stdout().write_all(&bytes)?;
Ok(())
}
Expand All @@ -33,12 +54,31 @@ impl Append for Stdout {
}

/// An appender that prints log records to stderr.
#[derive(Default, Debug)]
pub struct Stderr;
#[derive(Debug)]
pub struct Stderr {
layout: Layout,
}

impl Default for Stderr {
fn default() -> Self {
Self {
layout: TextLayout::default().into(),
}
}
}

impl Stderr {
/// Creates a new `Stderr` appender with the given layout.
pub fn with_layout(mut self, encoder: impl Into<Layout>) -> Self {
self.layout = encoder.into();
self
}
}

impl Append for Stderr {
fn append(&self, record: &log::Record) -> anyhow::Result<()> {
let bytes = format!("{}\n", record.args()).into_bytes();
let mut bytes = self.layout.format(record)?;
bytes.push(b'\n');
std::io::stderr().write_all(&bytes)?;
Ok(())
}
Expand Down
Loading