@@ -208,17 +208,20 @@ const fn severity_of_level(level: &Level) -> Severity {
208
208
#[ cfg( test) ]
209
209
mod tests {
210
210
use crate :: layer;
211
- use opentelemetry:: logs:: Severity ;
211
+ use async_trait:: async_trait;
212
+ use opentelemetry:: logs:: { LogResult , Severity } ;
212
213
use opentelemetry:: trace:: TracerProvider as _;
213
214
use opentelemetry:: trace:: { TraceContextExt , TraceFlags , Tracer } ;
214
215
use opentelemetry:: { logs:: AnyValue , Key } ;
216
+ use opentelemetry_sdk:: export:: logs:: { LogBatch , LogExporter } ;
215
217
use opentelemetry_sdk:: logs:: { LogRecord , LoggerProvider } ;
216
218
use opentelemetry_sdk:: testing:: logs:: InMemoryLogsExporter ;
217
219
use opentelemetry_sdk:: trace;
218
220
use opentelemetry_sdk:: trace:: { Sampler , TracerProvider } ;
219
- use tracing:: error;
221
+ use tracing:: { error, warn } ;
220
222
use tracing_subscriber:: prelude:: __tracing_subscriber_SubscriberExt;
221
- use tracing_subscriber:: Layer ;
223
+ use tracing_subscriber:: util:: SubscriberInitExt ;
224
+ use tracing_subscriber:: { EnvFilter , Layer } ;
222
225
223
226
pub fn attributes_contains ( log_record : & LogRecord , key : & Key , value : & AnyValue ) -> bool {
224
227
log_record
@@ -238,6 +241,70 @@ mod tests {
238
241
}
239
242
240
243
// 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 = "otel@opentelemetry.io" ) ;
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 = "otel@opentelemetry.io" ) ;
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 = "otel@opentelemetry.io" ) ;
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 = "otel@opentelemetry.io" ) ;
306
+ }
307
+
241
308
#[ test]
242
309
fn tracing_appender_standalone ( ) {
243
310
// Arrange
0 commit comments