16
16
from __future__ import annotations
17
17
18
18
import logging
19
+ import logging .config
19
20
from logging import WARNING , getLogger
20
21
from os import environ
21
22
from typing import Iterable , Optional , Sequence
@@ -641,62 +642,65 @@ def tearDown(self):
641
642
]
642
643
643
644
def test_logging_init_empty (self ):
644
- auto_resource = Resource .create (
645
- {
646
- "telemetry.auto.version" : "auto-version" ,
647
- }
648
- )
649
- _init_logging ({}, resource = auto_resource )
650
- self .assertEqual (self .set_provider_mock .call_count , 1 )
651
- provider = self .set_provider_mock .call_args [0 ][0 ]
652
- self .assertIsInstance (provider , DummyLoggerProvider )
653
- self .assertIsInstance (provider .resource , Resource )
654
- self .assertEqual (
655
- provider .resource .attributes .get ("telemetry.auto.version" ),
656
- "auto-version" ,
657
- )
658
- self .event_logger_provider_mock .assert_called_once_with (
659
- logger_provider = provider
660
- )
661
- self .set_event_logger_provider_mock .assert_called_once_with (
662
- self .event_logger_provider_instance_mock
663
- )
645
+ with ResetGlobalLoggingState ():
646
+ auto_resource = Resource .create (
647
+ {
648
+ "telemetry.auto.version" : "auto-version" ,
649
+ }
650
+ )
651
+ _init_logging ({}, resource = auto_resource )
652
+ self .assertEqual (self .set_provider_mock .call_count , 1 )
653
+ provider = self .set_provider_mock .call_args [0 ][0 ]
654
+ self .assertIsInstance (provider , DummyLoggerProvider )
655
+ self .assertIsInstance (provider .resource , Resource )
656
+ self .assertEqual (
657
+ provider .resource .attributes .get ("telemetry.auto.version" ),
658
+ "auto-version" ,
659
+ )
660
+ self .event_logger_provider_mock .assert_called_once_with (
661
+ logger_provider = provider
662
+ )
663
+ self .set_event_logger_provider_mock .assert_called_once_with (
664
+ self .event_logger_provider_instance_mock
665
+ )
664
666
665
667
@patch .dict (
666
668
environ ,
667
669
{"OTEL_RESOURCE_ATTRIBUTES" : "service.name=otlp-service" },
668
670
)
669
671
def test_logging_init_exporter (self ):
670
- resource = Resource .create ({})
671
- _init_logging ({"otlp" : DummyOTLPLogExporter }, resource = resource )
672
- self .assertEqual (self .set_provider_mock .call_count , 1 )
673
- provider = self .set_provider_mock .call_args [0 ][0 ]
674
- self .assertIsInstance (provider , DummyLoggerProvider )
675
- self .assertIsInstance (provider .resource , Resource )
676
- self .assertEqual (
677
- provider .resource .attributes .get ("service.name" ),
678
- "otlp-service" ,
679
- )
680
- self .assertIsInstance (provider .processor , DummyLogRecordProcessor )
681
- self .assertIsInstance (
682
- provider .processor .exporter , DummyOTLPLogExporter
683
- )
684
- getLogger (__name__ ).error ("hello" )
685
- self .assertTrue (provider .processor .exporter .export_called )
672
+ with ResetGlobalLoggingState ():
673
+ resource = Resource .create ({})
674
+ _init_logging ({"otlp" : DummyOTLPLogExporter }, resource = resource )
675
+ self .assertEqual (self .set_provider_mock .call_count , 1 )
676
+ provider = self .set_provider_mock .call_args [0 ][0 ]
677
+ self .assertIsInstance (provider , DummyLoggerProvider )
678
+ self .assertIsInstance (provider .resource , Resource )
679
+ self .assertEqual (
680
+ provider .resource .attributes .get ("service.name" ),
681
+ "otlp-service" ,
682
+ )
683
+ self .assertIsInstance (provider .processor , DummyLogRecordProcessor )
684
+ self .assertIsInstance (
685
+ provider .processor .exporter , DummyOTLPLogExporter
686
+ )
687
+ getLogger (__name__ ).error ("hello" )
688
+ self .assertTrue (provider .processor .exporter .export_called )
686
689
687
690
def test_logging_init_exporter_uses_exporter_args_map (self ):
688
- resource = Resource .create ({})
689
- _init_logging (
690
- {"otlp" : DummyOTLPLogExporter },
691
- resource = resource ,
692
- exporter_args_map = {
693
- DummyOTLPLogExporter : {"compression" : "gzip" },
694
- DummyOTLPMetricExporter : {"compression" : "no" },
695
- },
696
- )
697
- self .assertEqual (self .set_provider_mock .call_count , 1 )
698
- provider = self .set_provider_mock .call_args [0 ][0 ]
699
- self .assertEqual (provider .processor .exporter .compression , "gzip" )
691
+ with ResetGlobalLoggingState ():
692
+ resource = Resource .create ({})
693
+ _init_logging (
694
+ {"otlp" : DummyOTLPLogExporter },
695
+ resource = resource ,
696
+ exporter_args_map = {
697
+ DummyOTLPLogExporter : {"compression" : "gzip" },
698
+ DummyOTLPMetricExporter : {"compression" : "no" },
699
+ },
700
+ )
701
+ self .assertEqual (self .set_provider_mock .call_count , 1 )
702
+ provider = self .set_provider_mock .call_args [0 ][0 ]
703
+ self .assertEqual (provider .processor .exporter .compression , "gzip" )
700
704
701
705
@patch .dict (
702
706
environ ,
@@ -883,7 +887,7 @@ def test_initialize_components_kwargs(
883
887
)
884
888
885
889
def test_basicConfig_works_with_otel_handler (self ):
886
- with ClearLoggingHandlers ():
890
+ with ResetGlobalLoggingState ():
887
891
_init_logging (
888
892
{"otlp" : DummyOTLPLogExporter },
889
893
Resource .create ({}),
@@ -905,7 +909,7 @@ def test_basicConfig_works_with_otel_handler(self):
905
909
)
906
910
907
911
def test_basicConfig_preserves_otel_handler (self ):
908
- with ClearLoggingHandlers ():
912
+ with ResetGlobalLoggingState ():
909
913
_init_logging (
910
914
{"otlp" : DummyOTLPLogExporter },
911
915
Resource .create ({}),
@@ -920,7 +924,6 @@ def test_basicConfig_preserves_otel_handler(self):
920
924
)
921
925
handler = root_logger .handlers [0 ]
922
926
self .assertIsInstance (handler , LoggingHandler )
923
-
924
927
logging .basicConfig ()
925
928
926
929
self .assertGreater (len (root_logger .handlers ), 1 )
@@ -936,6 +939,49 @@ def test_basicConfig_preserves_otel_handler(self):
936
939
"Should still have exactly one OpenTelemetry LoggingHandler" ,
937
940
)
938
941
942
+ def test_dictConfig_preserves_otel_handler (self ):
943
+ with ResetGlobalLoggingState ():
944
+ _init_logging (
945
+ {"otlp" : DummyOTLPLogExporter },
946
+ Resource .create ({}),
947
+ setup_logging_handler = True ,
948
+ )
949
+
950
+ root = logging .getLogger ()
951
+ self .assertEqual (
952
+ len (root .handlers ),
953
+ 1 ,
954
+ "Should be exactly one OpenTelemetry LoggingHandler" ,
955
+ )
956
+ logging .config .dictConfig (
957
+ {
958
+ "version" : 1 ,
959
+ "disable_existing_loggers" : False , # If this is True all loggers are disabled. Many unit tests assert loggers emit logs.
960
+ "handlers" : {
961
+ "console" : {
962
+ "class" : "logging.StreamHandler" ,
963
+ "level" : "DEBUG" ,
964
+ "stream" : "ext://sys.stdout" ,
965
+ },
966
+ },
967
+ "loggers" : {
968
+ "" : { # root logger
969
+ "handlers" : ["console" ],
970
+ },
971
+ },
972
+ }
973
+ )
974
+ self .assertEqual (len (root .handlers ), 2 )
975
+
976
+ logging_handlers = [
977
+ h for h in root .handlers if isinstance (h , LoggingHandler )
978
+ ]
979
+ self .assertEqual (
980
+ len (logging_handlers ),
981
+ 1 ,
982
+ "Should still have exactly one OpenTelemetry LoggingHandler" ,
983
+ )
984
+
939
985
940
986
class TestMetricsInit (TestCase ):
941
987
def setUp (self ):
@@ -1187,8 +1233,14 @@ def test_custom_configurator(self, mock_init_comp):
1187
1233
mock_init_comp .assert_called_once_with (** kwargs )
1188
1234
1189
1235
1190
- class ClearLoggingHandlers :
1236
+ # Any test that calls _init_logging with setup_logging_handler=True
1237
+ # should call _init_logging within this context manager, to
1238
+ # ensure the global logging state is reset after the test.
1239
+ class ResetGlobalLoggingState :
1191
1240
def __init__ (self ):
1241
+ self .original_basic_config = logging .basicConfig
1242
+ self .original_dict_config = logging .config .dictConfig
1243
+ self .original_file_config = logging .config .fileConfig
1192
1244
self .root_logger = getLogger ()
1193
1245
self .original_handlers = None
1194
1246
@@ -1201,6 +1253,9 @@ def __exit__(self, exc_type, exc_val, exc_tb):
1201
1253
self .root_logger .handlers = []
1202
1254
for handler in self .original_handlers :
1203
1255
self .root_logger .addHandler (handler )
1256
+ logging .basicConfig = self .original_basic_config
1257
+ logging .config .dictConfig = self .original_dict_config
1258
+ logging .config .fileConfig = self .original_file_config
1204
1259
1205
1260
1206
1261
class TestClearLoggingHandlers (TestCase ):
@@ -1212,7 +1267,7 @@ def test_preserves_handlers(self):
1212
1267
root_logger .addHandler (test_handler )
1213
1268
expected_handlers = initial_handlers + [test_handler ]
1214
1269
1215
- with ClearLoggingHandlers ():
1270
+ with ResetGlobalLoggingState ():
1216
1271
self .assertEqual (len (root_logger .handlers ), 0 )
1217
1272
temp_handler = logging .StreamHandler ()
1218
1273
root_logger .addHandler (temp_handler )
@@ -1222,3 +1277,15 @@ def test_preserves_handlers(self):
1222
1277
self .assertIs (h1 , h2 )
1223
1278
1224
1279
root_logger .removeHandler (test_handler )
1280
+
1281
+ def test_preserves_original_logging_fns (self ):
1282
+ def f (x ):
1283
+ print ("f" )
1284
+
1285
+ with ResetGlobalLoggingState ():
1286
+ logging .basicConfig = f
1287
+ logging .config .dictConfig = f
1288
+ logging .config .fileConfig = f
1289
+ self .assertEqual (logging .config .dictConfig .__name__ , "dictConfig" )
1290
+ self .assertEqual (logging .basicConfig .__name__ , "basicConfig" )
1291
+ self .assertEqual (logging .config .fileConfig .__name__ , "fileConfig" )
0 commit comments