diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_performance_counters/_manager.py b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_performance_counters/_manager.py index a09ad4ab0579..beb9591e1fe1 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_performance_counters/_manager.py +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_performance_counters/_manager.py @@ -597,7 +597,6 @@ def __init__(self, meter_provider=None): try: # Note: ProcessIORate may not be available on all platforms if metric_class == ProcessIORate and not _IO_AVAILABLE: - _logger.warning("Process I/O Rate performance counter is not available on this platform.") continue performance_counter = metric_class(self._meter) self._performance_counters.append(performance_counter) diff --git a/sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md b/sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md index c88457fdd1aa..2728ef1dd242 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md +++ b/sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md @@ -9,6 +9,8 @@ ### Bugs Fixed - Fix the format of the fixed percentage sampler constant and ensure backward compatability ([#44656](https://github.com/Azure/azure-sdk-for-python/pull/44656)) +- Only add PerformanceCounter Processors after PerformanceCounter setup to avoid circular dependency. + ([#44661](https://github.com/Azure/azure-sdk-for-python/pull/44661)) ### Other Changes diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_configure.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_configure.py index 2d84f9565214..e0013ae3bd11 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_configure.py +++ b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_configure.py @@ -133,25 +133,28 @@ def configure_azure_monitor(**kwargs) -> None: # pylint: disable=C4758 disable_metrics = configurations[DISABLE_METRICS_ARG] enable_live_metrics_config = configurations[ENABLE_LIVE_METRICS_ARG] - # Setup live metrics + # Set up metrics pipeline + # Set up metrics with Performance Counters before _PerformanceCountersSpanProcessor and + # _PerformanceCountersLogRecordProcessor. This avoids a circular dependency in the case that Performance Counter + # setup produces a log. + if not disable_metrics: + _setup_metrics(configurations) + + # Set up live metrics if enable_live_metrics_config: _setup_live_metrics(configurations) - # Setup tracing pipeline + # Set up tracing pipeline if not disable_tracing: _setup_tracing(configurations) - # Setup logging pipeline + # Set up logging pipeline if not disable_logging: _setup_logging(configurations) - # Setup metrics pipeline - if not disable_metrics: - _setup_metrics(configurations) - - # Setup instrumentations - # Instrumentations need to be setup last so to use the global providers - # instanstiated in the other setup steps + # Set up instrumentations + # Instrumentations need to be set up last so to use the global providers + # instantiated in the other setup steps _setup_instrumentations(configurations) diff --git a/sdk/monitor/azure-monitor-opentelemetry/tests/test_configure.py b/sdk/monitor/azure-monitor-opentelemetry/tests/test_configure.py index 06e959130980..04cb3b402d06 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/tests/test_configure.py +++ b/sdk/monitor/azure-monitor-opentelemetry/tests/test_configure.py @@ -114,12 +114,19 @@ def test_configure_azure_monitor_disable_tracing( "resource": TEST_RESOURCE, } config_mock.return_value = configurations + # Track call order using side_effect + call_order = [] + metrics_mock.side_effect = lambda *args, **kwargs: call_order.append("metrics") + logging_mock.side_effect = lambda *args, **kwargs: call_order.append("logging") + tracing_mock.side_effect = lambda *args, **kwargs: call_order.append("tracing") configure_azure_monitor() tracing_mock.assert_not_called() logging_mock.assert_called_once_with(configurations) metrics_mock.assert_called_once_with(configurations) live_metrics_mock.assert_not_called() instrumentation_mock.assert_called_once_with(configurations) + # Assert setup_metrics is called before setup_logging + self.assertLess(call_order.index("metrics"), call_order.index("logging")) @patch( "azure.monitor.opentelemetry._configure._setup_instrumentations", @@ -158,12 +165,19 @@ def test_configure_azure_monitor_disable_logging( "resource": TEST_RESOURCE, } config_mock.return_value = configurations + # Track call order using side_effect + call_order = [] + metrics_mock.side_effect = lambda *args, **kwargs: call_order.append("metrics") + logging_mock.side_effect = lambda *args, **kwargs: call_order.append("logging") + tracing_mock.side_effect = lambda *args, **kwargs: call_order.append("tracing") configure_azure_monitor() tracing_mock.assert_called_once_with(configurations) logging_mock.assert_not_called() metrics_mock.assert_called_once_with(configurations) live_metrics_mock.assert_not_called() instrumentation_mock.assert_called_once_with(configurations) + # Assert setup_metrics is called before setup_tracing + self.assertLess(call_order.index("metrics"), call_order.index("tracing")) @patch( "azure.monitor.opentelemetry._configure._setup_instrumentations", @@ -246,12 +260,20 @@ def test_configure_azure_monitor_enable_live_metrics( "resource": TEST_RESOURCE, } config_mock.return_value = configurations + # Track call order using side_effect + call_order = [] + metrics_mock.side_effect = lambda *args, **kwargs: call_order.append("metrics") + logging_mock.side_effect = lambda *args, **kwargs: call_order.append("logging") + tracing_mock.side_effect = lambda *args, **kwargs: call_order.append("tracing") configure_azure_monitor() tracing_mock.assert_called_once_with(configurations) logging_mock.assert_called_once_with(configurations) metrics_mock.assert_called_once_with(configurations) live_metrics_mock.assert_called_once_with(configurations) instrumentation_mock.assert_called_once_with(configurations) + # Assert setup_metrics is called before setup_logging and setup_tracing + self.assertLess(call_order.index("metrics"), call_order.index("logging")) + self.assertLess(call_order.index("metrics"), call_order.index("tracing")) @patch( "azure.monitor.opentelemetry._configure._setup_instrumentations",