| 
21 | 21 | import unittest  | 
22 | 22 | import weakref  | 
23 | 23 | from concurrent.futures import ThreadPoolExecutor  | 
 | 24 | +from sys import version_info  | 
24 | 25 | from unittest.mock import Mock, patch  | 
25 | 26 | 
 
  | 
 | 27 | +from pytest import mark  | 
 | 28 | + | 
26 | 29 | from opentelemetry._logs import SeverityNumber  | 
27 | 30 | from opentelemetry.sdk import trace  | 
28 | 31 | from opentelemetry.sdk._logs import (  | 
@@ -347,6 +350,39 @@ def test_emit_call_log_record(self):  | 
347 | 350 |         logger.error("error")  | 
348 | 351 |         self.assertEqual(log_record_processor.emit.call_count, 1)  | 
349 | 352 | 
 
  | 
 | 353 | +    @mark.skipif(  | 
 | 354 | +        version_info < (3, 10),  | 
 | 355 | +        reason="assertNoLogs only exists in python 3.10+.",  | 
 | 356 | +    )  | 
 | 357 | +    def test_logging_lib_not_invoked_in_batch_log_record_emit(self):  # pylint: disable=no-self-use  | 
 | 358 | +        # See https://github.com/open-telemetry/opentelemetry-python/issues/4261  | 
 | 359 | +        exporter = Mock()  | 
 | 360 | +        processor = BatchLogRecordProcessor(exporter)  | 
 | 361 | +        logger_provider = LoggerProvider(  | 
 | 362 | +            resource=SDKResource.create(  | 
 | 363 | +                {  | 
 | 364 | +                    "service.name": "shoppingcart",  | 
 | 365 | +                    "service.instance.id": "instance-12",  | 
 | 366 | +                }  | 
 | 367 | +            ),  | 
 | 368 | +        )  | 
 | 369 | +        logger_provider.add_log_record_processor(processor)  | 
 | 370 | +        handler = LoggingHandler(  | 
 | 371 | +            level=logging.INFO, logger_provider=logger_provider  | 
 | 372 | +        )  | 
 | 373 | +        sdk_logger = logging.getLogger("opentelemetry.sdk")  | 
 | 374 | +        # Attach OTLP handler to SDK logger  | 
 | 375 | +        sdk_logger.addHandler(handler)  | 
 | 376 | +        # If `emit` calls logging.log then this test will throw a maximum recursion depth exceeded exception and fail.  | 
 | 377 | +        try:  | 
 | 378 | +            with self.assertNoLogs(sdk_logger, logging.NOTSET):  | 
 | 379 | +                processor.emit(EMPTY_LOG)  | 
 | 380 | +            processor.shutdown()  | 
 | 381 | +            with self.assertNoLogs(sdk_logger, logging.NOTSET):  | 
 | 382 | +                processor.emit(EMPTY_LOG)  | 
 | 383 | +        finally:  | 
 | 384 | +            sdk_logger.removeHandler(handler)  | 
 | 385 | + | 
350 | 386 |     def test_args(self):  | 
351 | 387 |         exporter = InMemoryLogExporter()  | 
352 | 388 |         log_record_processor = BatchLogRecordProcessor(  | 
@@ -517,12 +553,6 @@ def test_logs_flushed_before_shutdown_and_dropped_after_shutdown(self):  | 
517 | 553 |         exporter.export.assert_called_once_with([EMPTY_LOG])  | 
518 | 554 |         self.assertTrue(exporter._stopped)  | 
519 | 555 | 
 
  | 
520 |  | -        with self.assertLogs(level="INFO") as log:  | 
521 |  | -            # This log should not be flushed.  | 
522 |  | -            log_record_processor.emit(EMPTY_LOG)  | 
523 |  | -            self.assertEqual(len(log.output), 1)  | 
524 |  | -            self.assertEqual(len(log.records), 1)  | 
525 |  | -            self.assertIn("Shutdown called, ignoring log.", log.output[0])  | 
526 | 556 |         exporter.export.assert_called_once()  | 
527 | 557 | 
 
  | 
528 | 558 |     # pylint: disable=no-self-use  | 
 | 
0 commit comments