1313# limitations under the License.
1414# type: ignore
1515
16+ from logging import DEBUG , INFO , NullHandler , getLogger
1617from unittest import TestCase
1718from unittest .mock import Mock , call , patch
1819
@@ -209,27 +210,32 @@ def _instrumentation_failed_to_load_call(entry_point, dependency_conflict):
209210 "Skipping instrumentation %s: %s" , entry_point , dependency_conflict
210211 )
211212
212- def test_writes_diagnostic_output_for_debug_levels (self ):
213+ def test_writes_otel_log_level_output_for_debug_levels (self ):
213214 for log_level in ("debug" , "trace" ):
214215 with (
215216 self .subTest (log_level = log_level ),
216217 patch .dict (
217218 "os.environ" , {"OTEL_LOG_LEVEL" : log_level }, clear = True
218219 ),
219- patch (
220- "opentelemetry.instrumentation.auto_instrumentation._load._logger"
221- ) as logger_mock ,
222220 patch (
223221 "opentelemetry.instrumentation.auto_instrumentation._load.stderr"
224222 ) as stderr_mock ,
225223 ):
224+ logger_mock = Mock ()
226225 logger_mock .isEnabledFor .return_value = True
227- logger_mock .hasHandlers .return_value = False
226+ logger_mock .handlers = []
227+ logger_mock .parent = None
228+ logger_mock .propagate = True
229+ logger_mock .name = (
230+ "opentelemetry.instrumentation."
231+ "auto_instrumentation._load"
232+ )
233+ logger = _load ._OtelLogLevelLoggerAdapter (logger_mock , {})
228234
229- _load . _debug ("Instrumented %s" , "requests" )
235+ logger . debug ("Instrumented %s" , "requests" )
230236
231- logger_mock .debug .assert_called_once_with (
232- "Instrumented %s" , "requests"
237+ logger_mock .log .assert_called_once_with (
238+ DEBUG , "Instrumented %s" , "requests" , extra = {}
233239 )
234240 stderr_mock .write .assert_called_once_with (
235241 "DEBUG:"
@@ -238,37 +244,115 @@ def test_writes_diagnostic_output_for_debug_levels(self):
238244 )
239245 stderr_mock .flush .assert_called_once ()
240246
241- def test_does_not_write_diagnostic_output (self ):
247+ def test_does_not_write_otel_log_level_output (self ):
242248 cases = (
243- ("debug" , True ),
249+ ("debug" , DEBUG ),
244250 ("info" , False ),
245251 ("debug2" , False ),
246252 ("debugger" , False ),
247253 )
248254
249- for log_level , logger_has_handlers in cases :
255+ for log_level , handler_level in cases :
250256 with (
251257 self .subTest (log_level = log_level ),
252258 patch .dict (
253259 "os.environ" , {"OTEL_LOG_LEVEL" : log_level }, clear = True
254260 ),
255- patch (
256- "opentelemetry.instrumentation.auto_instrumentation._load._logger"
257- ) as logger_mock ,
258261 patch (
259262 "opentelemetry.instrumentation.auto_instrumentation._load.stderr"
260263 ) as stderr_mock ,
261264 ):
265+ logger_mock = Mock ()
262266 logger_mock .isEnabledFor .return_value = True
263- logger_mock .hasHandlers .return_value = logger_has_handlers
267+ logger_mock .handlers = (
268+ [Mock (level = handler_level )] if handler_level else []
269+ )
270+ logger_mock .parent = None
271+ logger_mock .propagate = True
272+ logger = _load ._OtelLogLevelLoggerAdapter (logger_mock , {})
273+
274+ logger .debug ("Instrumented %s" , "requests" )
275+
276+ logger_mock .log .assert_called_once_with (
277+ DEBUG , "Instrumented %s" , "requests" , extra = {}
278+ )
279+ stderr_mock .write .assert_not_called ()
280+ stderr_mock .flush .assert_not_called ()
281+
282+ @patch .dict ("os.environ" , {"OTEL_LOG_LEVEL" : "debug" }, clear = True )
283+ def test_otel_log_level_output_uses_logger_hierarchy_handlers (self ):
284+ parent_logger = getLogger ("opentelemetry.test.auto_instrumentation" )
285+ logger = getLogger ("opentelemetry.test.auto_instrumentation.loader" )
286+
287+ original_parent_handlers = parent_logger .handlers [:]
288+ original_parent_level = parent_logger .level
289+ original_parent_propagate = parent_logger .propagate
290+ original_logger_handlers = logger .handlers [:]
291+ original_logger_level = logger .level
292+ original_logger_propagate = logger .propagate
293+
294+ try :
295+ parent_logger .handlers = []
296+ parent_logger .setLevel (DEBUG )
297+ parent_logger .propagate = False
298+ logger .handlers = []
299+ logger .setLevel (DEBUG )
300+ logger .propagate = True
301+
302+ otel_log_level_logger = _load ._OtelLogLevelLoggerAdapter (
303+ logger , {}
304+ )
305+
306+ with patch (
307+ "opentelemetry.instrumentation.auto_instrumentation._load.stderr"
308+ ) as stderr_mock :
309+ otel_log_level_logger .debug ("Instrumented %s" , "requests" )
310+
311+ stderr_mock .write .assert_called_once_with (
312+ "DEBUG:"
313+ "opentelemetry.test.auto_instrumentation.loader:"
314+ "Instrumented 'requests'\n "
315+ )
316+ stderr_mock .flush .assert_called_once ()
317+
318+ handler = NullHandler ()
319+ handler .setLevel (INFO )
320+ parent_logger .addHandler (handler )
321+ otel_log_level_logger = _load ._OtelLogLevelLoggerAdapter (
322+ logger , {}
323+ )
264324
265- _load ._debug ("Instrumented %s" , "requests" )
325+ with patch (
326+ "opentelemetry.instrumentation.auto_instrumentation._load.stderr"
327+ ) as stderr_mock :
328+ otel_log_level_logger .debug ("Instrumented %s" , "requests" )
266329
267- logger_mock .debug .assert_called_once_with (
268- "Instrumented %s" , "requests"
330+ stderr_mock .write .assert_called_once_with (
331+ "DEBUG:"
332+ "opentelemetry.test.auto_instrumentation.loader:"
333+ "Instrumented 'requests'\n "
269334 )
335+ stderr_mock .flush .assert_called_once ()
336+
337+ handler .setLevel (DEBUG )
338+ otel_log_level_logger = _load ._OtelLogLevelLoggerAdapter (
339+ logger , {}
340+ )
341+
342+ with patch (
343+ "opentelemetry.instrumentation.auto_instrumentation._load.stderr"
344+ ) as stderr_mock :
345+ otel_log_level_logger .debug ("Instrumented %s" , "requests" )
346+
270347 stderr_mock .write .assert_not_called ()
271348 stderr_mock .flush .assert_not_called ()
349+ finally :
350+ parent_logger .handlers = original_parent_handlers
351+ parent_logger .setLevel (original_parent_level )
352+ parent_logger .propagate = original_parent_propagate
353+ logger .handlers = original_logger_handlers
354+ logger .setLevel (original_logger_level )
355+ logger .propagate = original_logger_propagate
272356
273357 @patch .dict (
274358 "os.environ" ,
0 commit comments