2020
2121from opentelemetry .instrumentation .logging import ( # pylint: disable=no-name-in-module
2222 DEFAULT_LOGGING_FORMAT ,
23- LoggingInstrumentor ,
23+ LoggingInstrumentor , apply_log_settings ,
2424)
2525from opentelemetry .test .test_base import TestBase
2626from opentelemetry .trace import ProxyTracer , get_tracer
@@ -106,28 +106,28 @@ def test_trace_context_injection(self):
106106 def test_trace_context_injection_without_span (self ):
107107 self .assert_trace_context_injected ("0" , "0" , False )
108108
109- @mock .patch ("logging.basicConfig " )
110- def test_basic_config_called (self , basic_config_mock ):
109+ @mock .patch ("opentelemetry.instrumentation. logging.apply_log_settings " )
110+ def test_basic_config_called (self , apply_log_settings_mock ):
111111 LoggingInstrumentor ().uninstrument ()
112112 LoggingInstrumentor ().instrument ()
113- self .assertFalse ( basic_config_mock .called )
113+ self .assertTrue ( apply_log_settings_mock .called )
114114 LoggingInstrumentor ().uninstrument ()
115115
116116 env_patch = mock .patch .dict (
117117 "os.environ" , {"OTEL_PYTHON_LOG_CORRELATION" : "true" }
118118 )
119119 env_patch .start ()
120120 LoggingInstrumentor ().instrument ()
121- basic_config_mock .assert_called_with (
121+ apply_log_settings_mock .assert_called_with (
122122 format = DEFAULT_LOGGING_FORMAT , level = logging .INFO
123123 )
124124 env_patch .stop ()
125125
126- @mock .patch ("logging.basicConfig " )
127- def test_custom_format_and_level_env (self , basic_config_mock ):
126+ @mock .patch ("opentelemetry.instrumentation. logging.apply_log_settings " )
127+ def test_custom_format_and_level_env (self , apply_log_settings_mock ):
128128 LoggingInstrumentor ().uninstrument ()
129129 LoggingInstrumentor ().instrument ()
130- self .assertFalse ( basic_config_mock .called )
130+ self .assertTrue ( apply_log_settings_mock .called )
131131 LoggingInstrumentor ().uninstrument ()
132132
133133 env_patch = mock .patch .dict (
@@ -140,22 +140,22 @@ def test_custom_format_and_level_env(self, basic_config_mock):
140140 )
141141 env_patch .start ()
142142 LoggingInstrumentor ().instrument ()
143- basic_config_mock .assert_called_with (
143+ apply_log_settings_mock .assert_called_with (
144144 format = "%(message)s %(otelSpanID)s" , level = logging .ERROR
145145 )
146146 env_patch .stop ()
147147
148- @mock .patch ("logging.basicConfig " )
148+ @mock .patch ("opentelemetry.instrumentation. logging.apply_log_settings " )
149149 def test_custom_format_and_level_api (
150- self , basic_config_mock
150+ self , apply_log_settings_mock
151151 ): # pylint: disable=no-self-use
152152 LoggingInstrumentor ().uninstrument ()
153153 LoggingInstrumentor ().instrument (
154154 set_logging_format = True ,
155155 logging_format = "%(message)s span_id=%(otelSpanID)s" ,
156156 log_level = logging .WARNING ,
157157 )
158- basic_config_mock .assert_called_with (
158+ apply_log_settings_mock .assert_called_with (
159159 format = "%(message)s span_id=%(otelSpanID)s" , level = logging .WARNING
160160 )
161161
@@ -207,3 +207,73 @@ def test_uninstrumented(self):
207207 self .assertFalse (hasattr (record , "otelTraceID" ))
208208 self .assertFalse (hasattr (record , "otelServiceName" ))
209209 self .assertFalse (hasattr (record , "otelTraceSampled" ))
210+
211+
212+ class TestLogSetup (TestBase ):
213+ """
214+ Tests the apply_log_settings function
215+ """
216+ def setUp (self ):
217+ super ().setUp ()
218+
219+ def tearDown (self ):
220+ super ().tearDown ()
221+
222+ @mock .patch ("logging.Formatter" )
223+ @mock .patch ("logging.getLogger" )
224+ @mock .patch ("logging.basicConfig" )
225+ def test_apply_log_settings_initialized (self , basic_config_mock , get_logger_mock , formatter_mock ):
226+ """
227+ Tests that apply_log_settings tries to apply format and loglevel to the
228+ configured logging module if the logging module has already been initialized
229+ """
230+ # Prepare
231+ log_level = logging .DEBUG
232+ log_format = "custom %(message)s"
233+ formatter = "formatter"
234+
235+ formatter_mock .return_value = formatter
236+
237+ handler_mock = mock .MagicMock ()
238+
239+ root_logger_mock = mock .MagicMock ()
240+ root_logger_mock .hasHandlers .return_value = True
241+ root_logger_mock .handlers = [handler_mock ]
242+
243+ get_logger_mock .return_value = root_logger_mock
244+
245+ # Act
246+ apply_log_settings (log_format , log_level )
247+
248+ # Assert
249+ get_logger_mock .assert_called_once_with ()
250+ root_logger_mock .hasHandlers .assert_called_once ()
251+ root_logger_mock .setLevel .assert_called_once_with (log_level )
252+ handler_mock .setFormatter .assert_called_once_with (formatter )
253+ formatter_mock .assert_called_once_with (log_format )
254+
255+ self .assertFalse (basic_config_mock .called )
256+
257+ @mock .patch ("logging.getLogger" )
258+ @mock .patch ("logging.basicConfig" )
259+ def test_apply_log_settings_uninitialized (self , basic_config_mock , get_logger_mock ):
260+ """
261+ Tests that apply_log_settings calls logging.basicConfig with the
262+ provided format and level when the logging module has not been
263+ initialized
264+ """
265+ log_level = logging .DEBUG
266+ log_format = "custom %(message)s"
267+
268+ root_logger_mock = mock .MagicMock ()
269+ root_logger_mock .hasHandlers .return_value = False
270+
271+ get_logger_mock .return_value = root_logger_mock
272+
273+ apply_log_settings (log_format , log_level )
274+
275+ root_logger_mock .hasHandlers .assert_called_once ()
276+ get_logger_mock .assert_called_once_with ()
277+ basic_config_mock .assert_called_once_with (
278+ format = log_format , level = log_level
279+ )
0 commit comments