Skip to content

Commit

Permalink
Add OpenTelemetry LoggingHandler conditionally (Azure#38549)
Browse files Browse the repository at this point in the history
  • Loading branch information
lzchen authored and allenkim0129 committed Nov 18, 2024
1 parent 8b29b72 commit ae91385
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 8 deletions.
2 changes: 2 additions & 0 deletions sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

### Features Added

- Only add OpenTelemetry LoggingHandler if current logger does not have it
([#38549](https://github.com/Azure/azure-sdk-for-python/pull/38549))
- Distro to automatically configure event logger provider
([#38543](https://github.com/Azure/azure-sdk-for-python/pull/38543))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,13 @@ def _setup_logging(configurations: Dict[str, ConfigurationValue]):
)
logger_provider.add_log_record_processor(log_record_processor)
set_logger_provider(logger_provider)
handler = LoggingHandler(logger_provider=logger_provider)
logger_name: str = configurations[LOGGER_NAME_ARG] # type: ignore
getLogger(logger_name).addHandler(handler)
logger = getLogger(logger_name)
# Only add OpenTelemetry LoggingHandler if logger does not already have the handler
# This is to prevent most duplicate logging telemetry
if not any(isinstance(handler, LoggingHandler) for handler in logger.handlers):
handler = LoggingHandler(logger_provider=logger_provider)
logger.addHandler(handler)

# Setup EventLoggerProvider
event_provider = EventLoggerProvider(logger_provider)
Expand Down
12 changes: 6 additions & 6 deletions sdk/monitor/azure-monitor-opentelemetry/samples/logging/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@
logger.warning("warning log")
logger.error("error log")

logger.info("info log")
logger.warning("warning log")
logger.error("error log")
logger_child.info("Child: info log")
logger_child.warning("Child: warning log")
logger_child.error("Child: error log")

logger_not_tracked.info("info log2")
logger_not_tracked.warning("warning log2")
logger_not_tracked.error("error log2")
logger_not_tracked.info("Not tracked: info log")
logger_not_tracked.warning("Not tracked: warning log")
logger_not_tracked.error("Not tracked: error log")

input()
55 changes: 55 additions & 0 deletions sdk/monitor/azure-monitor-opentelemetry/tests/test_configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import unittest
from unittest.mock import Mock, call, patch

from opentelemetry.sdk._logs import LoggingHandler
from opentelemetry.sdk.resources import Resource

from azure.core.tracing.ext.opentelemetry_span import OpenTelemetrySpan
Expand Down Expand Up @@ -351,6 +352,7 @@ def test_setup_logging(
logging_handler_init_mock = Mock()
logging_handler_mock.return_value = logging_handler_init_mock
logger_mock = Mock()
logger_mock.handlers = []
get_logger_mock.return_value = logger_mock

configurations = {
Expand All @@ -373,6 +375,59 @@ def test_setup_logging(
elp_mock.assert_called_once_with(lp_init_mock)
set_elp_mock.assert_called_once_with(elp_init_mock)

@patch(
"azure.monitor.opentelemetry._configure.getLogger",
)
@patch(
"azure.monitor.opentelemetry._configure.BatchLogRecordProcessor",
)
@patch(
"azure.monitor.opentelemetry._configure.AzureMonitorLogExporter",
)
@patch(
"azure.monitor.opentelemetry._configure.set_logger_provider",
)
@patch(
"azure.monitor.opentelemetry._configure.LoggerProvider",
autospec=True,
)
def test_setup_logging_duplicate_logger(
self,
lp_mock,
set_logger_provider_mock,
log_exporter_mock,
blrp_mock,
get_logger_mock,
):
lp_init_mock = Mock()
lp_mock.return_value = lp_init_mock
log_exp_init_mock = Mock()
log_exporter_mock.return_value = log_exp_init_mock
blrp_init_mock = Mock()
blrp_mock.return_value = blrp_init_mock
logging_handler_init_mock = Mock(spec=LoggingHandler)
logger_mock = Mock()
logger_mock.handlers = [logging_handler_init_mock]
get_logger_mock.return_value = logger_mock

configurations = {
"connection_string": "test_cs",
"logger_name": "test",
"resource": TEST_RESOURCE,
}
_setup_logging(configurations)

lp_mock.assert_called_once_with(resource=TEST_RESOURCE)
set_logger_provider_mock.assert_called_once_with(lp_init_mock)
log_exporter_mock.assert_called_once_with(**configurations)
blrp_mock.assert_called_once_with(
log_exp_init_mock,
)
lp_init_mock.add_log_record_processor.assert_called_once_with(blrp_init_mock)
# logging_handler_mock.assert_not_called()
get_logger_mock.assert_called_once_with("test")
logger_mock.addHandler.assert_not_called()

@patch(
"azure.monitor.opentelemetry._configure.PeriodicExportingMetricReader",
)
Expand Down

0 comments on commit ae91385

Please sign in to comment.