Skip to content

Commit f2a9a34

Browse files
authored
Support Live metrics via OneSettings control plane (#43032)
1 parent e73aa3c commit f2a9a34

File tree

24 files changed

+2791
-1410
lines changed

24 files changed

+2791
-1410
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
### Features Added
66

7+
- OneSettings control plane: Add live metrics feature control
8+
([#43032](https://github.com/Azure/azure-sdk-for-python/pull/43032))
9+
710
### Breaking Changes
811

912
### Bugs Fixed

sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_configuration/__init__.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
_ONE_SETTINGS_CHANGE_URL,
1111
_ONE_SETTINGS_CONFIG_URL,
1212
)
13+
from azure.monitor.opentelemetry.exporter._configuration._utils import _ConfigurationProfile
1314
from azure.monitor.opentelemetry.exporter._configuration._utils import make_onesettings_request
1415
from azure.monitor.opentelemetry.exporter._utils import Singleton
1516

@@ -40,26 +41,34 @@ class _ConfigurationManager(metaclass=Singleton):
4041

4142
def __init__(self):
4243
"""Initialize the ConfigurationManager instance."""
43-
4444
self._configuration_worker = None
4545
self._state_lock = Lock() # Single lock for all state
4646
self._current_state = _ConfigurationState()
4747
self._callbacks = []
48-
self._initialize_worker()
48+
self._initialized = False
4949

50-
def _initialize_worker(self):
50+
def initialize(self, **kwargs):
5151
"""Initialize the ConfigurationManager and start the configuration worker."""
52-
# Lazy import to avoid circular import
53-
from azure.monitor.opentelemetry.exporter._configuration._worker import _ConfigurationWorker
54-
55-
# Get initial refresh interval from state
5652
with self._state_lock:
53+
if self._initialized:
54+
return
55+
56+
# Fill the configuration profile with the initializer's parameters
57+
_ConfigurationProfile.fill(**kwargs)
58+
59+
# Lazy import to avoid circular import
60+
from azure.monitor.opentelemetry.exporter._configuration._worker import _ConfigurationWorker
61+
62+
# Get initial refresh interval from current state
5763
initial_refresh_interval = self._current_state.refresh_interval
5864

59-
self._configuration_worker = _ConfigurationWorker(self, initial_refresh_interval)
65+
self._configuration_worker = _ConfigurationWorker(self, initial_refresh_interval)
66+
self._initialized = True
6067

6168
def register_callback(self, callback):
6269
# Register a callback to be invoked when configuration changes.
70+
if not self._initialized:
71+
return
6372
self._callbacks.append(callback)
6473

6574
def _notify_callbacks(self, settings: Dict[str, str]):
@@ -148,7 +157,7 @@ def get_configuration_and_refresh_interval(self, query_dict: Optional[Dict[str,
148157
new_state_updates['refresh_interval'] = response.refresh_interval # type: ignore
149158

150159
if response.status_code == 304:
151-
# Not modified: Only update etag and refresh interval below
160+
# Not modified: Settings unchanged, but update etag and refresh interval if provided
152161
pass
153162
# Handle version and settings updates
154163
elif response.settings and response.version is not None:
@@ -225,6 +234,8 @@ def shutdown(self) -> None:
225234
if self._configuration_worker:
226235
self._configuration_worker.shutdown()
227236
self._configuration_worker = None
237+
self._initialized = False
238+
self._callbacks.clear()
228239
# Clear the singleton instance from the metaclass
229-
if self.__class__ in Singleton._instances: # pylint: disable=protected-access
230-
del Singleton._instances[self.__class__] # pylint: disable=protected-access
240+
if self.__class__ in _ConfigurationManager._instances: # pylint: disable=protected-access
241+
del _ConfigurationManager._instances[self.__class__] # pylint: disable=protected-access
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
"""State management utilities for Configuration Manager.
4+
5+
This module provides global access functions for the Configuration Manager singleton.
6+
"""
7+
8+
from typing import TYPE_CHECKING
9+
10+
if TYPE_CHECKING:
11+
from azure.monitor.opentelemetry.exporter._configuration import _ConfigurationManager
12+
13+
# Global singleton instance for easy access throughout the codebase
14+
_configuration_manager = None
15+
16+
def get_configuration_manager() -> "_ConfigurationManager":
17+
"""Get the global Configuration Manager singleton instance.
18+
19+
This provides a single access point to the manager and handles lazy initialization.
20+
21+
:return: The singleton Configuration Manager instance
22+
:rtype: _ConfigurationManager
23+
"""
24+
global _configuration_manager # pylint: disable=global-statement
25+
if _configuration_manager is None:
26+
from azure.monitor.opentelemetry.exporter._configuration import _ConfigurationManager
27+
_configuration_manager = _ConfigurationManager()
28+
return _configuration_manager

0 commit comments

Comments
 (0)