Skip to content

Commit 0ba4f2e

Browse files
jeremydvossCopilot
andauthored
Fix circular dependency in Performance Counters on Mac (#44661)
* Initialize performance counters before adding processors * changelog * rm warning log for OSs that don't support process I/O * Add tests for execution order * pr number * Update sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_configure.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * lint * Remove unnecessary test * lint --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent daf8953 commit 0ba4f2e

File tree

4 files changed

+37
-11
lines changed

4 files changed

+37
-11
lines changed

sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_performance_counters/_manager.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,6 @@ def __init__(self, meter_provider=None):
597597
try:
598598
# Note: ProcessIORate may not be available on all platforms
599599
if metric_class == ProcessIORate and not _IO_AVAILABLE:
600-
_logger.warning("Process I/O Rate performance counter is not available on this platform.")
601600
continue
602601
performance_counter = metric_class(self._meter)
603602
self._performance_counters.append(performance_counter)

sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
### Bugs Fixed
1010
- Fix the format of the fixed percentage sampler constant and ensure backward compatability
1111
([#44656](https://github.com/Azure/azure-sdk-for-python/pull/44656))
12+
- Only add PerformanceCounter Processors after PerformanceCounter setup to avoid circular dependency.
13+
([#44661](https://github.com/Azure/azure-sdk-for-python/pull/44661))
1214

1315
### Other Changes
1416

sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_configure.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -133,25 +133,28 @@ def configure_azure_monitor(**kwargs) -> None: # pylint: disable=C4758
133133
disable_metrics = configurations[DISABLE_METRICS_ARG]
134134
enable_live_metrics_config = configurations[ENABLE_LIVE_METRICS_ARG]
135135

136-
# Setup live metrics
136+
# Set up metrics pipeline
137+
# Set up metrics with Performance Counters before _PerformanceCountersSpanProcessor and
138+
# _PerformanceCountersLogRecordProcessor. This avoids a circular dependency in the case that Performance Counter
139+
# setup produces a log.
140+
if not disable_metrics:
141+
_setup_metrics(configurations)
142+
143+
# Set up live metrics
137144
if enable_live_metrics_config:
138145
_setup_live_metrics(configurations)
139146

140-
# Setup tracing pipeline
147+
# Set up tracing pipeline
141148
if not disable_tracing:
142149
_setup_tracing(configurations)
143150

144-
# Setup logging pipeline
151+
# Set up logging pipeline
145152
if not disable_logging:
146153
_setup_logging(configurations)
147154

148-
# Setup metrics pipeline
149-
if not disable_metrics:
150-
_setup_metrics(configurations)
151-
152-
# Setup instrumentations
153-
# Instrumentations need to be setup last so to use the global providers
154-
# instanstiated in the other setup steps
155+
# Set up instrumentations
156+
# Instrumentations need to be set up last so to use the global providers
157+
# instantiated in the other setup steps
155158
_setup_instrumentations(configurations)
156159

157160

sdk/monitor/azure-monitor-opentelemetry/tests/test_configure.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,19 @@ def test_configure_azure_monitor_disable_tracing(
114114
"resource": TEST_RESOURCE,
115115
}
116116
config_mock.return_value = configurations
117+
# Track call order using side_effect
118+
call_order = []
119+
metrics_mock.side_effect = lambda *args, **kwargs: call_order.append("metrics")
120+
logging_mock.side_effect = lambda *args, **kwargs: call_order.append("logging")
121+
tracing_mock.side_effect = lambda *args, **kwargs: call_order.append("tracing")
117122
configure_azure_monitor()
118123
tracing_mock.assert_not_called()
119124
logging_mock.assert_called_once_with(configurations)
120125
metrics_mock.assert_called_once_with(configurations)
121126
live_metrics_mock.assert_not_called()
122127
instrumentation_mock.assert_called_once_with(configurations)
128+
# Assert setup_metrics is called before setup_logging
129+
self.assertLess(call_order.index("metrics"), call_order.index("logging"))
123130

124131
@patch(
125132
"azure.monitor.opentelemetry._configure._setup_instrumentations",
@@ -158,12 +165,19 @@ def test_configure_azure_monitor_disable_logging(
158165
"resource": TEST_RESOURCE,
159166
}
160167
config_mock.return_value = configurations
168+
# Track call order using side_effect
169+
call_order = []
170+
metrics_mock.side_effect = lambda *args, **kwargs: call_order.append("metrics")
171+
logging_mock.side_effect = lambda *args, **kwargs: call_order.append("logging")
172+
tracing_mock.side_effect = lambda *args, **kwargs: call_order.append("tracing")
161173
configure_azure_monitor()
162174
tracing_mock.assert_called_once_with(configurations)
163175
logging_mock.assert_not_called()
164176
metrics_mock.assert_called_once_with(configurations)
165177
live_metrics_mock.assert_not_called()
166178
instrumentation_mock.assert_called_once_with(configurations)
179+
# Assert setup_metrics is called before setup_tracing
180+
self.assertLess(call_order.index("metrics"), call_order.index("tracing"))
167181

168182
@patch(
169183
"azure.monitor.opentelemetry._configure._setup_instrumentations",
@@ -246,12 +260,20 @@ def test_configure_azure_monitor_enable_live_metrics(
246260
"resource": TEST_RESOURCE,
247261
}
248262
config_mock.return_value = configurations
263+
# Track call order using side_effect
264+
call_order = []
265+
metrics_mock.side_effect = lambda *args, **kwargs: call_order.append("metrics")
266+
logging_mock.side_effect = lambda *args, **kwargs: call_order.append("logging")
267+
tracing_mock.side_effect = lambda *args, **kwargs: call_order.append("tracing")
249268
configure_azure_monitor()
250269
tracing_mock.assert_called_once_with(configurations)
251270
logging_mock.assert_called_once_with(configurations)
252271
metrics_mock.assert_called_once_with(configurations)
253272
live_metrics_mock.assert_called_once_with(configurations)
254273
instrumentation_mock.assert_called_once_with(configurations)
274+
# Assert setup_metrics is called before setup_logging and setup_tracing
275+
self.assertLess(call_order.index("metrics"), call_order.index("logging"))
276+
self.assertLess(call_order.index("metrics"), call_order.index("tracing"))
255277

256278
@patch(
257279
"azure.monitor.opentelemetry._configure._setup_instrumentations",

0 commit comments

Comments
 (0)