|
16 | 16 | from __future__ import annotations |
17 | 17 |
|
18 | 18 | import logging |
19 | | -from logging import getLogger, WARNING |
| 19 | +from logging import WARNING, getLogger |
20 | 20 | from os import environ |
21 | 21 | from typing import Iterable, Optional, Sequence |
22 | | -from unittest import mock, TestCase |
| 22 | +from unittest import TestCase, mock |
23 | 23 | from unittest.mock import Mock, patch |
24 | 24 |
|
25 | 25 | from pytest import raises |
|
60 | 60 | MetricReader, |
61 | 61 | ) |
62 | 62 | from opentelemetry.sdk.metrics.view import Aggregation |
63 | | -from opentelemetry.sdk.resources import Resource, SERVICE_NAME |
| 63 | +from opentelemetry.sdk.resources import SERVICE_NAME, Resource |
64 | 64 | from opentelemetry.sdk.trace.export import ConsoleSpanExporter |
65 | 65 | from opentelemetry.sdk.trace.id_generator import IdGenerator, RandomIdGenerator |
66 | 66 | from opentelemetry.sdk.trace.sampling import ( |
@@ -845,30 +845,58 @@ def test_initialize_components_kwargs( |
845 | 845 |
|
846 | 846 | def test_basicConfig_works_with_otel_handler(self): |
847 | 847 | with ClearLoggingHandlers(): |
848 | | - # Initialize auto-instrumentation with logging enabled |
849 | 848 | _init_logging( |
850 | 849 | {"otlp": DummyOTLPLogExporter}, |
851 | 850 | Resource.create({}), |
852 | 851 | setup_logging_handler=True, |
853 | 852 | ) |
854 | 853 |
|
855 | | - # Call basicConfig - this should work despite OTel handler being present |
856 | 854 | logging.basicConfig(level=logging.INFO) |
857 | 855 |
|
858 | | - # Verify a StreamHandler was added |
859 | 856 | root_logger = logging.getLogger() |
860 | 857 | stream_handlers = [ |
861 | 858 | h |
862 | 859 | for h in root_logger.handlers |
863 | 860 | if isinstance(h, logging.StreamHandler) |
864 | | - and not isinstance(h, LoggingHandler) |
865 | 861 | ] |
866 | 862 | self.assertEqual( |
867 | 863 | len(stream_handlers), |
868 | 864 | 1, |
869 | 865 | "basicConfig should add a StreamHandler even when OTel handler exists", |
870 | 866 | ) |
871 | 867 |
|
| 868 | + def test_basicConfig_preserves_otel_handler(self): |
| 869 | + with ClearLoggingHandlers(): |
| 870 | + _init_logging( |
| 871 | + {"otlp": DummyOTLPLogExporter}, |
| 872 | + Resource.create({}), |
| 873 | + setup_logging_handler=True, |
| 874 | + ) |
| 875 | + |
| 876 | + root_logger = logging.getLogger() |
| 877 | + self.assertEqual( |
| 878 | + len(root_logger.handlers), |
| 879 | + 1, |
| 880 | + "Should be exactly one OpenTelemetry LoggingHandler", |
| 881 | + ) |
| 882 | + handler = root_logger.handlers[0] |
| 883 | + self.assertIsInstance(handler, LoggingHandler) |
| 884 | + |
| 885 | + logging.basicConfig() |
| 886 | + |
| 887 | + self.assertGreater(len(root_logger.handlers), 1) |
| 888 | + |
| 889 | + logging_handlers = [ |
| 890 | + h |
| 891 | + for h in root_logger.handlers |
| 892 | + if isinstance(h, LoggingHandler) |
| 893 | + ] |
| 894 | + self.assertEqual( |
| 895 | + len(logging_handlers), |
| 896 | + 1, |
| 897 | + "Should still have exactly one OpenTelemetry LoggingHandler", |
| 898 | + ) |
| 899 | + |
872 | 900 |
|
873 | 901 | class TestMetricsInit(TestCase): |
874 | 902 | def setUp(self): |
@@ -1112,43 +1140,32 @@ def __init__(self): |
1112 | 1140 | self.original_handlers = None |
1113 | 1141 |
|
1114 | 1142 | def __enter__(self): |
1115 | | - # Save original state |
1116 | 1143 | self.original_handlers = self.root_logger.handlers[:] |
1117 | | - # Remove all handlers |
1118 | 1144 | self.root_logger.handlers = [] |
1119 | 1145 | return self |
1120 | 1146 |
|
1121 | 1147 | def __exit__(self, exc_type, exc_val, exc_tb): |
1122 | | - # Restore original state |
1123 | 1148 | self.root_logger.handlers = [] |
1124 | 1149 | for handler in self.original_handlers: |
1125 | 1150 | self.root_logger.addHandler(handler) |
1126 | 1151 |
|
1127 | 1152 |
|
1128 | 1153 | class TestClearLoggingHandlers(TestCase): |
1129 | 1154 | def test_preserves_handlers(self): |
1130 | | - root_logger = getLogger() # Get the root logger |
1131 | | - initial_handlers = root_logger.handlers[ |
1132 | | - : |
1133 | | - ] # Save initial test environment handlers |
| 1155 | + root_logger = getLogger() |
| 1156 | + initial_handlers = root_logger.handlers[:] |
1134 | 1157 |
|
1135 | | - # Add our test handler |
1136 | 1158 | test_handler = logging.StreamHandler() |
1137 | 1159 | root_logger.addHandler(test_handler) |
1138 | 1160 | expected_handlers = initial_handlers + [test_handler] |
1139 | 1161 |
|
1140 | 1162 | with ClearLoggingHandlers(): |
1141 | | - # Should have no handlers during the test |
1142 | 1163 | self.assertEqual(len(root_logger.handlers), 0) |
1143 | | - |
1144 | | - # Add a temporary handler that should get cleaned up |
1145 | 1164 | temp_handler = logging.StreamHandler() |
1146 | 1165 | root_logger.addHandler(temp_handler) |
1147 | 1166 |
|
1148 | | - # After the test, should be back to initial handlers plus our test handler |
1149 | 1167 | self.assertEqual(len(root_logger.handlers), len(expected_handlers)) |
1150 | 1168 | for h1, h2 in zip(root_logger.handlers, expected_handlers): |
1151 | 1169 | self.assertIs(h1, h2) |
1152 | 1170 |
|
1153 | | - # Cleanup our test handler |
1154 | 1171 | root_logger.removeHandler(test_handler) |
0 commit comments