@@ -208,17 +208,20 @@ const fn severity_of_level(level: &Level) -> Severity {
208208#[ cfg( test) ]
209209mod tests {
210210 use crate :: layer;
211- use opentelemetry:: logs:: Severity ;
211+ use async_trait:: async_trait;
212+ use opentelemetry:: logs:: { LogResult , Severity } ;
212213 use opentelemetry:: trace:: TracerProvider as _;
213214 use opentelemetry:: trace:: { TraceContextExt , TraceFlags , Tracer } ;
214215 use opentelemetry:: { logs:: AnyValue , Key } ;
216+ use opentelemetry_sdk:: export:: logs:: { LogBatch , LogExporter } ;
215217 use opentelemetry_sdk:: logs:: { LogRecord , LoggerProvider } ;
216218 use opentelemetry_sdk:: testing:: logs:: InMemoryLogsExporter ;
217219 use opentelemetry_sdk:: trace;
218220 use opentelemetry_sdk:: trace:: { Sampler , TracerProvider } ;
219- use tracing:: error;
221+ use tracing:: { error, warn } ;
220222 use tracing_subscriber:: prelude:: __tracing_subscriber_SubscriberExt;
221- use tracing_subscriber:: Layer ;
223+ use tracing_subscriber:: util:: SubscriberInitExt ;
224+ use tracing_subscriber:: { EnvFilter , Layer } ;
222225
223226 pub fn attributes_contains ( log_record : & LogRecord , key : & Key , value : & AnyValue ) -> bool {
224227 log_record
@@ -238,6 +241,70 @@ mod tests {
238241 }
239242
240243 // cargo test --features=testing
244+
245+ #[ derive( Clone , Debug , Default ) ]
246+ struct ReentrantLogExporter ;
247+
248+ #[ async_trait]
249+ impl LogExporter for ReentrantLogExporter {
250+ async fn export ( & mut self , _batch : LogBatch < ' _ > ) -> LogResult < ( ) > {
251+ // This will cause a deadlock as the export itself creates a log
252+ // while still within the lock of the SimpleLogProcessor.
253+ warn ! ( name
: "my-event-name" , target
: "reentrant" , event_id =
20 , user_name =
"otel" , user_email =
"[email protected] " ) ; 254+ Ok ( ( ) )
255+ }
256+ }
257+
258+ #[ test]
259+ #[ ignore = "See issue: https://github.com/open-telemetry/opentelemetry-rust/issues/1745" ]
260+ fn simple_processor_deadlock ( ) {
261+ let exporter: ReentrantLogExporter = ReentrantLogExporter ;
262+ let logger_provider = LoggerProvider :: builder ( )
263+ . with_simple_exporter ( exporter. clone ( ) )
264+ . build ( ) ;
265+
266+ let layer = layer:: OpenTelemetryTracingBridge :: new ( & logger_provider) ;
267+
268+ // Setting subscriber as global as that is the only way to test this scenario.
269+ tracing_subscriber:: registry ( ) . with ( layer) . init ( ) ;
270+ warn ! ( name
: "my-event-name" , target
: "my-system" , event_id =
20 , user_name =
"otel" , user_email =
"[email protected] " ) ; 271+ }
272+
273+ #[ test]
274+ #[ ignore = "While this test runs fine, this uses global subscriber and does not play well with other tests." ]
275+ fn simple_processor_no_deadlock ( ) {
276+ let exporter: ReentrantLogExporter = ReentrantLogExporter ;
277+ let logger_provider = LoggerProvider :: builder ( )
278+ . with_simple_exporter ( exporter. clone ( ) )
279+ . build ( ) ;
280+
281+ let layer = layer:: OpenTelemetryTracingBridge :: new ( & logger_provider) ;
282+
283+ // This filter will prevent the deadlock as the reentrant log will be
284+ // ignored.
285+ let filter = EnvFilter :: new ( "debug" ) . add_directive ( "reentrant=error" . parse ( ) . unwrap ( ) ) ;
286+ // Setting subscriber as global as that is the only way to test this scenario.
287+ tracing_subscriber:: registry ( )
288+ . with ( filter)
289+ . with ( layer)
290+ . init ( ) ;
291+ warn ! ( name
: "my-event-name" , target
: "my-system" , event_id =
20 , user_name =
"otel" , user_email =
"[email protected] " ) ; 292+ }
293+
294+ #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
295+ #[ ignore = "While this test runs fine, this uses global subscriber and does not play well with other tests." ]
296+ async fn batch_processor_no_deadlock ( ) {
297+ let exporter: ReentrantLogExporter = ReentrantLogExporter ;
298+ let logger_provider = LoggerProvider :: builder ( )
299+ . with_batch_exporter ( exporter. clone ( ) , opentelemetry_sdk:: runtime:: Tokio )
300+ . build ( ) ;
301+
302+ let layer = layer:: OpenTelemetryTracingBridge :: new ( & logger_provider) ;
303+
304+ tracing_subscriber:: registry ( ) . with ( layer) . init ( ) ;
305+ warn ! ( name
: "my-event-name" , target
: "my-system" , event_id =
20 , user_name =
"otel" , user_email =
"[email protected] " ) ; 306+ }
307+
241308 #[ test]
242309 fn tracing_appender_standalone ( ) {
243310 // Arrange
0 commit comments