Skip to content

Add test to validate log shutdown #1620

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

Merged
Merged
Changes from 5 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
96 changes: 96 additions & 0 deletions opentelemetry-sdk/src/logs/log_emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,99 @@ impl opentelemetry::logs::Logger for Logger {
enabled
}
}

#[cfg(test)]
mod tests {
use super::*;
use opentelemetry::global::{logger, set_logger_provider, shutdown_logger_provider};
use opentelemetry::logs::Logger;
use std::sync::{Arc, Mutex};

#[test]
fn shutdown_test() {
// cargo test shutdown_test --features=logs

// Arrange
let shutdown_called = Arc::new(Mutex::new(false));
let flush_called = Arc::new(Mutex::new(false));
let logger_provider = LoggerProvider::builder()
.with_log_processor(LazyLogProcessor::new(
shutdown_called.clone(),
flush_called.clone(),
))
.build();
set_logger_provider(logger_provider);

// Act
let logger1 = logger("test-logger1");
let logger2 = logger("test-logger2");
logger1.emit(LogRecord::default());
logger2.emit(LogRecord::default());

// Intentionally *not* calling shutdown/flush on the provider, but
// instead relying on shutdown_logger_provider which causes the global
// provider to be dropped, leading to the sdk logger provider's drop to
// be called, which is expected to call shutdown on processors.
shutdown_logger_provider();

// Assert

// shutdown_logger_provider is necessary but not sufficient, as loggers
// hold on to the the provider (via inner provider clones).
assert!(!*shutdown_called.lock().unwrap());

// flush is never called by the sdk.
assert!(!*flush_called.lock().unwrap());

// Drop one of the logger. Still not enough!
drop(logger1);
assert!(!*shutdown_called.lock().unwrap());

// drop logger2, which is the only remaining logger, and this will
// finally drop the inner provider, triggering shutdown.
drop(logger2);
assert!(*shutdown_called.lock().unwrap());

// flush is never called by the sdk.
assert!(!*flush_called.lock().unwrap());
}

#[derive(Debug)]
pub(crate) struct LazyLogProcessor {
shutdown_called: Arc<Mutex<bool>>,
flush_called: Arc<Mutex<bool>>,
}

impl LazyLogProcessor {
pub(crate) fn new(
shutdown_called: Arc<Mutex<bool>>,
flush_called: Arc<Mutex<bool>>,
) -> Self {
LazyLogProcessor {
shutdown_called,
flush_called,
}
}
}

impl LogProcessor for LazyLogProcessor {
fn emit(&self, _data: LogData) {
// nothing to do.
}

fn force_flush(&self) -> LogResult<()> {
*self.flush_called.lock().unwrap() = true;
Ok(())
}

fn shutdown(&mut self) -> LogResult<()> {
*self.shutdown_called.lock().unwrap() = true;
Ok(())
}

#[cfg(feature = "logs_level_enabled")]
fn event_enabled(&self, _level: Severity, _target: &str, _name: &str) -> bool {
true
}
}
}