|
15 | 15 | # pylint: skip-file
|
16 | 16 | from __future__ import annotations
|
17 | 17 |
|
| 18 | +import logging |
18 | 19 | from logging import WARNING, getLogger
|
19 | 20 | from os import environ
|
20 | 21 | from typing import Iterable, Optional, Sequence
|
|
44 | 45 | _OTelSDKConfigurator,
|
45 | 46 | )
|
46 | 47 | from opentelemetry.sdk._logs import LoggingHandler
|
| 48 | +from opentelemetry.sdk._logs._internal.export import LogExporter |
47 | 49 | from opentelemetry.sdk._logs.export import ConsoleLogExporter
|
48 | 50 | from opentelemetry.sdk.environment_variables import (
|
49 | 51 | OTEL_TRACES_SAMPLER,
|
@@ -203,7 +205,7 @@ class OTLPSpanExporter:
|
203 | 205 | pass
|
204 | 206 |
|
205 | 207 |
|
206 |
| -class DummyOTLPLogExporter: |
| 208 | +class DummyOTLPLogExporter(LogExporter): |
207 | 209 | def __init__(self, *args, **kwargs):
|
208 | 210 | self.export_called = False
|
209 | 211 |
|
@@ -841,6 +843,60 @@ def test_initialize_components_kwargs(
|
841 | 843 | True,
|
842 | 844 | )
|
843 | 845 |
|
| 846 | + def test_basicConfig_works_with_otel_handler(self): |
| 847 | + with ClearLoggingHandlers(): |
| 848 | + _init_logging( |
| 849 | + {"otlp": DummyOTLPLogExporter}, |
| 850 | + Resource.create({}), |
| 851 | + setup_logging_handler=True, |
| 852 | + ) |
| 853 | + |
| 854 | + logging.basicConfig(level=logging.INFO) |
| 855 | + |
| 856 | + root_logger = logging.getLogger() |
| 857 | + stream_handlers = [ |
| 858 | + h |
| 859 | + for h in root_logger.handlers |
| 860 | + if isinstance(h, logging.StreamHandler) |
| 861 | + ] |
| 862 | + self.assertEqual( |
| 863 | + len(stream_handlers), |
| 864 | + 1, |
| 865 | + "basicConfig should add a StreamHandler even when OTel handler exists", |
| 866 | + ) |
| 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 | + |
844 | 900 |
|
845 | 901 | class TestMetricsInit(TestCase):
|
846 | 902 | def setUp(self):
|
@@ -1076,3 +1132,40 @@ def test_custom_configurator(self, mock_init_comp):
|
1076 | 1132 | "sampler": "TEST_SAMPLER",
|
1077 | 1133 | }
|
1078 | 1134 | mock_init_comp.assert_called_once_with(**kwargs)
|
| 1135 | + |
| 1136 | + |
| 1137 | +class ClearLoggingHandlers: |
| 1138 | + def __init__(self): |
| 1139 | + self.root_logger = getLogger() |
| 1140 | + self.original_handlers = None |
| 1141 | + |
| 1142 | + def __enter__(self): |
| 1143 | + self.original_handlers = self.root_logger.handlers[:] |
| 1144 | + self.root_logger.handlers = [] |
| 1145 | + return self |
| 1146 | + |
| 1147 | + def __exit__(self, exc_type, exc_val, exc_tb): |
| 1148 | + self.root_logger.handlers = [] |
| 1149 | + for handler in self.original_handlers: |
| 1150 | + self.root_logger.addHandler(handler) |
| 1151 | + |
| 1152 | + |
| 1153 | +class TestClearLoggingHandlers(TestCase): |
| 1154 | + def test_preserves_handlers(self): |
| 1155 | + root_logger = getLogger() |
| 1156 | + initial_handlers = root_logger.handlers[:] |
| 1157 | + |
| 1158 | + test_handler = logging.StreamHandler() |
| 1159 | + root_logger.addHandler(test_handler) |
| 1160 | + expected_handlers = initial_handlers + [test_handler] |
| 1161 | + |
| 1162 | + with ClearLoggingHandlers(): |
| 1163 | + self.assertEqual(len(root_logger.handlers), 0) |
| 1164 | + temp_handler = logging.StreamHandler() |
| 1165 | + root_logger.addHandler(temp_handler) |
| 1166 | + |
| 1167 | + self.assertEqual(len(root_logger.handlers), len(expected_handlers)) |
| 1168 | + for h1, h2 in zip(root_logger.handlers, expected_handlers): |
| 1169 | + self.assertIs(h1, h2) |
| 1170 | + |
| 1171 | + root_logger.removeHandler(test_handler) |
0 commit comments