-
Notifications
You must be signed in to change notification settings - Fork 598
Add Unit Tests for Sync and Async Log Exporters - with and without runtime - for SimpleLogProcessor #2218
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 Unit Tests for Sync and Async Log Exporters - with and without runtime - for SimpleLogProcessor #2218
Changes from 5 commits
ef2c68c
4e5c903
b307c27
49944e0
506bfb0
a4ee905
f4c73a4
8f0d005
7ccc90e
052c20d
c88cd7a
0e3c7dd
95ff800
657bc61
5da41dc
8cdfd46
96454b1
9119e22
0ceb999
c7ba0fc
6dea545
a5e8b80
3bbd91a
75e08bd
0ff3c03
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -553,6 +553,7 @@ | |
| use opentelemetry::InstrumentationLibrary; | ||
| use opentelemetry::Key; | ||
| use opentelemetry::{logs::LogResult, KeyValue}; | ||
| use std::panic; | ||
| use std::sync::{Arc, Mutex}; | ||
| use std::time::Duration; | ||
|
|
||
|
|
@@ -994,4 +995,148 @@ | |
| == AnyValue::String("Updated by FirstProcessor".into()) | ||
| ); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_simple_processor_sync_exporter_without_runtime() { | ||
| let exporter = InMemoryLogsExporterBuilder::default() | ||
| .keep_records_on_shutdown() | ||
lalitb marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| .build(); | ||
| let processor = SimpleLogProcessor::new(Box::new(exporter.clone())); | ||
|
|
||
| let mut record: LogRecord = Default::default(); | ||
| let instrumentation: InstrumentationLibrary = Default::default(); | ||
|
|
||
| processor.emit(&mut record, &instrumentation); | ||
| processor.force_flush().unwrap(); | ||
cijothomas marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| processor.shutdown().unwrap(); | ||
|
|
||
| assert_eq!(exporter.get_emitted_logs().unwrap().len(), 1); | ||
| } | ||
|
|
||
| #[tokio::test(flavor = "multi_thread", worker_threads = 1)] | ||
cijothomas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| async fn test_simple_processor_sync_exporter_with_runtime() { | ||
| let exporter = InMemoryLogsExporterBuilder::default() | ||
| .keep_records_on_shutdown() | ||
| .build(); | ||
| let processor = SimpleLogProcessor::new(Box::new(exporter.clone())); | ||
|
|
||
| let mut record: LogRecord = Default::default(); | ||
| let instrumentation: InstrumentationLibrary = Default::default(); | ||
|
|
||
| processor.emit(&mut record, &instrumentation); | ||
| processor.force_flush().unwrap(); | ||
| processor.shutdown().unwrap(); | ||
|
|
||
| assert_eq!(exporter.get_emitted_logs().unwrap().len(), 1); | ||
| } | ||
|
|
||
| #[tokio::test(flavor = "current_thread")] | ||
| async fn test_simple_processor_sync_exporter_with_current_thread_runtime() { | ||
| let exporter = InMemoryLogsExporterBuilder::default() | ||
| .keep_records_on_shutdown() | ||
| .build(); | ||
| let processor = SimpleLogProcessor::new(Box::new(exporter.clone())); | ||
|
|
||
| let mut record: LogRecord = Default::default(); | ||
| let instrumentation: InstrumentationLibrary = Default::default(); | ||
|
|
||
| processor.emit(&mut record, &instrumentation); | ||
| processor.force_flush().unwrap(); | ||
utpilla marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| processor.shutdown().unwrap(); | ||
|
|
||
| assert_eq!(exporter.get_emitted_logs().unwrap().len(), 1); | ||
| } | ||
|
|
||
| #[derive(Debug, Clone)] | ||
| struct AsyncLogExporter { | ||
cijothomas marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| logs: Arc<Mutex<Vec<(LogRecord, InstrumentationLibrary)>>>, | ||
cijothomas marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| #[async_trait::async_trait] | ||
| impl LogExporter for AsyncLogExporter { | ||
| async fn export(&mut self, batch: LogBatch<'_>) -> LogResult<()> { | ||
| let logs = Arc::clone(&self.logs); | ||
|
|
||
| // Collect batch into an owned Vec to ensure the data can be moved into the tokio::spawn task | ||
| let batch_owned: Vec<(LogRecord, InstrumentationLibrary)> = batch | ||
| .iter() | ||
| .map(|(log_record, instrumentation)| (log_record.clone(), instrumentation.clone())) | ||
| .collect(); | ||
|
|
||
| // Spawn a Tokio task to process the log batch asynchronously | ||
| tokio::spawn(async move { | ||
|
||
| let mut logs_lock = logs.lock().unwrap(); | ||
| for (log_record, instrumentation) in batch_owned { | ||
| logs_lock.push((log_record, instrumentation)); | ||
| } | ||
| }) | ||
| .await | ||
| .expect("Task failed"); // Await the task completion. | ||
|
|
||
| Ok(()) | ||
| } | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_simple_processor_async_exporter_without_runtime() { | ||
| // Use `catch_unwind` to catch the panic caused by missing Tokio runtime | ||
utpilla marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| let result = panic::catch_unwind(|| { | ||
| let exporter = AsyncLogExporter { | ||
| logs: Arc::new(Mutex::new(Vec::new())), | ||
| }; | ||
| let processor = SimpleLogProcessor::new(Box::new(exporter.clone())); | ||
|
|
||
| let mut record: LogRecord = Default::default(); | ||
| let instrumentation: InstrumentationLibrary = Default::default(); | ||
|
|
||
| // This will panic because `tokio::spawn` is called without a runtime | ||
| processor.emit(&mut record, &instrumentation); | ||
| processor.force_flush().unwrap(); | ||
cijothomas marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| processor.shutdown().unwrap(); | ||
|
|
||
| // Assert to make sure the failure occurs | ||
| assert_eq!(exporter.logs.lock().unwrap().len(), 1); | ||
cijothomas marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| }); | ||
|
|
||
| // Verify that the panic occurred, indicating the absence of a Tokio runtime | ||
| assert!( | ||
| result.is_err(), | ||
cijothomas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "The test should fail due to missing Tokio runtime, but it did not." | ||
| ); | ||
| } | ||
|
|
||
| #[tokio::test(flavor = "multi_thread", worker_threads = 1)] | ||
cijothomas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| async fn test_simple_processor_async_exporter_with_runtime() { | ||
| let exporter = AsyncLogExporter { | ||
| logs: Arc::new(Mutex::new(Vec::new())), | ||
| }; | ||
| let processor = SimpleLogProcessor::new(Box::new(exporter.clone())); | ||
|
|
||
| let mut record: LogRecord = Default::default(); | ||
| let instrumentation: InstrumentationLibrary = Default::default(); | ||
|
|
||
| processor.emit(&mut record, &instrumentation); | ||
| processor.force_flush().unwrap(); | ||
cijothomas marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| processor.shutdown().unwrap(); | ||
|
|
||
| assert_eq!(exporter.logs.lock().unwrap().len(), 1); | ||
| } | ||
|
|
||
| #[tokio::test(flavor = "current_thread")] | ||
| #[ignore] // This test hangs as of now. | ||
cijothomas marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| async fn test_simple_processor_async_exporter_with_current_thread_runtime() { | ||
| let exporter = AsyncLogExporter { | ||
| logs: Arc::new(Mutex::new(Vec::new())), | ||
| }; | ||
| let processor = SimpleLogProcessor::new(Box::new(exporter.clone())); | ||
|
|
||
| let mut record: LogRecord = Default::default(); | ||
| let instrumentation: InstrumentationLibrary = Default::default(); | ||
|
|
||
| processor.emit(&mut record, &instrumentation); | ||
| processor.force_flush().unwrap(); | ||
| processor.shutdown().unwrap(); | ||
|
|
||
| assert_eq!(exporter.logs.lock().unwrap().len(), 1); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: We can write a helper and call them for all the cominations:
we can eventually prepare a test matrix.md file for quick visualization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, good to have a test matrix. Will do it after adding tests for batch.