1616from __future__ import annotations
1717
1818import logging
19+ import logging .config
1920from logging import WARNING , getLogger
2021from os import environ
2122from typing import Iterable , Optional , Sequence
@@ -680,62 +681,65 @@ def tearDown(self):
680681 ]
681682
682683 def test_logging_init_empty (self ):
683- auto_resource = Resource .create (
684- {
685- "telemetry.auto.version" : "auto-version" ,
686- }
687- )
688- _init_logging ({}, resource = auto_resource )
689- self .assertEqual (self .set_provider_mock .call_count , 1 )
690- provider = self .set_provider_mock .call_args [0 ][0 ]
691- self .assertIsInstance (provider , DummyLoggerProvider )
692- self .assertIsInstance (provider .resource , Resource )
693- self .assertEqual (
694- provider .resource .attributes .get ("telemetry.auto.version" ),
695- "auto-version" ,
696- )
697- self .event_logger_provider_mock .assert_called_once_with (
698- logger_provider = provider
699- )
700- self .set_event_logger_provider_mock .assert_called_once_with (
701- self .event_logger_provider_instance_mock
702- )
684+ with ResetGlobalLoggingState ():
685+ auto_resource = Resource .create (
686+ {
687+ "telemetry.auto.version" : "auto-version" ,
688+ }
689+ )
690+ _init_logging ({}, resource = auto_resource )
691+ self .assertEqual (self .set_provider_mock .call_count , 1 )
692+ provider = self .set_provider_mock .call_args [0 ][0 ]
693+ self .assertIsInstance (provider , DummyLoggerProvider )
694+ self .assertIsInstance (provider .resource , Resource )
695+ self .assertEqual (
696+ provider .resource .attributes .get ("telemetry.auto.version" ),
697+ "auto-version" ,
698+ )
699+ self .event_logger_provider_mock .assert_called_once_with (
700+ logger_provider = provider
701+ )
702+ self .set_event_logger_provider_mock .assert_called_once_with (
703+ self .event_logger_provider_instance_mock
704+ )
703705
704706 @patch .dict (
705707 environ ,
706708 {"OTEL_RESOURCE_ATTRIBUTES" : "service.name=otlp-service" },
707709 )
708710 def test_logging_init_exporter (self ):
709- resource = Resource .create ({})
710- _init_logging ({"otlp" : DummyOTLPLogExporter }, resource = resource )
711- self .assertEqual (self .set_provider_mock .call_count , 1 )
712- provider = self .set_provider_mock .call_args [0 ][0 ]
713- self .assertIsInstance (provider , DummyLoggerProvider )
714- self .assertIsInstance (provider .resource , Resource )
715- self .assertEqual (
716- provider .resource .attributes .get ("service.name" ),
717- "otlp-service" ,
718- )
719- self .assertIsInstance (provider .processor , DummyLogRecordProcessor )
720- self .assertIsInstance (
721- provider .processor .exporter , DummyOTLPLogExporter
722- )
723- getLogger (__name__ ).error ("hello" )
724- self .assertTrue (provider .processor .exporter .export_called )
711+ with ResetGlobalLoggingState ():
712+ resource = Resource .create ({})
713+ _init_logging ({"otlp" : DummyOTLPLogExporter }, resource = resource )
714+ self .assertEqual (self .set_provider_mock .call_count , 1 )
715+ provider = self .set_provider_mock .call_args [0 ][0 ]
716+ self .assertIsInstance (provider , DummyLoggerProvider )
717+ self .assertIsInstance (provider .resource , Resource )
718+ self .assertEqual (
719+ provider .resource .attributes .get ("service.name" ),
720+ "otlp-service" ,
721+ )
722+ self .assertIsInstance (provider .processor , DummyLogRecordProcessor )
723+ self .assertIsInstance (
724+ provider .processor .exporter , DummyOTLPLogExporter
725+ )
726+ getLogger (__name__ ).error ("hello" )
727+ self .assertTrue (provider .processor .exporter .export_called )
725728
726729 def test_logging_init_exporter_uses_exporter_args_map (self ):
727- resource = Resource .create ({})
728- _init_logging (
729- {"otlp" : DummyOTLPLogExporter },
730- resource = resource ,
731- exporter_args_map = {
732- DummyOTLPLogExporter : {"compression" : "gzip" },
733- DummyOTLPMetricExporter : {"compression" : "no" },
734- },
735- )
736- self .assertEqual (self .set_provider_mock .call_count , 1 )
737- provider = self .set_provider_mock .call_args [0 ][0 ]
738- self .assertEqual (provider .processor .exporter .compression , "gzip" )
730+ with ResetGlobalLoggingState ():
731+ resource = Resource .create ({})
732+ _init_logging (
733+ {"otlp" : DummyOTLPLogExporter },
734+ resource = resource ,
735+ exporter_args_map = {
736+ DummyOTLPLogExporter : {"compression" : "gzip" },
737+ DummyOTLPMetricExporter : {"compression" : "no" },
738+ },
739+ )
740+ self .assertEqual (self .set_provider_mock .call_count , 1 )
741+ provider = self .set_provider_mock .call_args [0 ][0 ]
742+ self .assertEqual (provider .processor .exporter .compression , "gzip" )
739743
740744 @patch .dict (
741745 environ ,
@@ -925,7 +929,7 @@ def test_initialize_components_kwargs(
925929 )
926930
927931 def test_basicConfig_works_with_otel_handler (self ):
928- with ClearLoggingHandlers ():
932+ with ResetGlobalLoggingState ():
929933 _init_logging (
930934 {"otlp" : DummyOTLPLogExporter },
931935 Resource .create ({}),
@@ -947,7 +951,7 @@ def test_basicConfig_works_with_otel_handler(self):
947951 )
948952
949953 def test_basicConfig_preserves_otel_handler (self ):
950- with ClearLoggingHandlers ():
954+ with ResetGlobalLoggingState ():
951955 _init_logging (
952956 {"otlp" : DummyOTLPLogExporter },
953957 Resource .create ({}),
@@ -962,7 +966,6 @@ def test_basicConfig_preserves_otel_handler(self):
962966 )
963967 handler = root_logger .handlers [0 ]
964968 self .assertIsInstance (handler , LoggingHandler )
965-
966969 logging .basicConfig ()
967970
968971 self .assertGreater (len (root_logger .handlers ), 1 )
@@ -978,6 +981,49 @@ def test_basicConfig_preserves_otel_handler(self):
978981 "Should still have exactly one OpenTelemetry LoggingHandler" ,
979982 )
980983
984+ def test_dictConfig_preserves_otel_handler (self ):
985+ with ResetGlobalLoggingState ():
986+ _init_logging (
987+ {"otlp" : DummyOTLPLogExporter },
988+ Resource .create ({}),
989+ setup_logging_handler = True ,
990+ )
991+
992+ root = logging .getLogger ()
993+ self .assertEqual (
994+ len (root .handlers ),
995+ 1 ,
996+ "Should be exactly one OpenTelemetry LoggingHandler" ,
997+ )
998+ logging .config .dictConfig (
999+ {
1000+ "version" : 1 ,
1001+ "disable_existing_loggers" : False , # If this is True all loggers are disabled. Many unit tests assert loggers emit logs.
1002+ "handlers" : {
1003+ "console" : {
1004+ "class" : "logging.StreamHandler" ,
1005+ "level" : "DEBUG" ,
1006+ "stream" : "ext://sys.stdout" ,
1007+ },
1008+ },
1009+ "loggers" : {
1010+ "" : { # root logger
1011+ "handlers" : ["console" ],
1012+ },
1013+ },
1014+ }
1015+ )
1016+ self .assertEqual (len (root .handlers ), 2 )
1017+
1018+ logging_handlers = [
1019+ h for h in root .handlers if isinstance (h , LoggingHandler )
1020+ ]
1021+ self .assertEqual (
1022+ len (logging_handlers ),
1023+ 1 ,
1024+ "Should still have exactly one OpenTelemetry LoggingHandler" ,
1025+ )
1026+
9811027
9821028class TestMetricsInit (TestCase ):
9831029 def setUp (self ):
@@ -1229,8 +1275,14 @@ def test_custom_configurator(self, mock_init_comp):
12291275 mock_init_comp .assert_called_once_with (** kwargs )
12301276
12311277
1232- class ClearLoggingHandlers :
1278+ # Any test that calls _init_logging with setup_logging_handler=True
1279+ # should call _init_logging within this context manager, to
1280+ # ensure the global logging state is reset after the test.
1281+ class ResetGlobalLoggingState :
12331282 def __init__ (self ):
1283+ self .original_basic_config = logging .basicConfig
1284+ self .original_dict_config = logging .config .dictConfig
1285+ self .original_file_config = logging .config .fileConfig
12341286 self .root_logger = getLogger ()
12351287 self .original_handlers = None
12361288
@@ -1243,6 +1295,9 @@ def __exit__(self, exc_type, exc_val, exc_tb):
12431295 self .root_logger .handlers = []
12441296 for handler in self .original_handlers :
12451297 self .root_logger .addHandler (handler )
1298+ logging .basicConfig = self .original_basic_config
1299+ logging .config .dictConfig = self .original_dict_config
1300+ logging .config .fileConfig = self .original_file_config
12461301
12471302
12481303class TestClearLoggingHandlers (TestCase ):
@@ -1254,7 +1309,7 @@ def test_preserves_handlers(self):
12541309 root_logger .addHandler (test_handler )
12551310 expected_handlers = initial_handlers + [test_handler ]
12561311
1257- with ClearLoggingHandlers ():
1312+ with ResetGlobalLoggingState ():
12581313 self .assertEqual (len (root_logger .handlers ), 0 )
12591314 temp_handler = logging .StreamHandler ()
12601315 root_logger .addHandler (temp_handler )
@@ -1264,3 +1319,15 @@ def test_preserves_handlers(self):
12641319 self .assertIs (h1 , h2 )
12651320
12661321 root_logger .removeHandler (test_handler )
1322+
1323+ def test_preserves_original_logging_fns (self ):
1324+ def f (x ):
1325+ print ("f" )
1326+
1327+ with ResetGlobalLoggingState ():
1328+ logging .basicConfig = f
1329+ logging .config .dictConfig = f
1330+ logging .config .fileConfig = f
1331+ self .assertEqual (logging .config .dictConfig .__name__ , "dictConfig" )
1332+ self .assertEqual (logging .basicConfig .__name__ , "basicConfig" )
1333+ self .assertEqual (logging .config .fileConfig .__name__ , "fileConfig" )
0 commit comments