Skip to content

Commit e913742

Browse files
authored
Update live metrics feature bit in statsbeat during runtime (Azure#38556)
1 parent 117ba56 commit e913742

File tree

7 files changed

+74
-9
lines changed

7 files changed

+74
-9
lines changed

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

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

99
### Bugs Fixed
1010

11+
- Detect live metrics usage during runtime in addition to on startup
12+
([#37694](https://github.com/Azure/azure-sdk-for-python/pull/37694))
13+
1114
### Other Changes
1215

1316
## 1.0.0b32 (2024-11-04)

sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_quickpulse/_live_metrics.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ def enable_live_metrics(**kwargs: Any) -> None: # pylint: disable=C4758
8282
:rtype: None
8383
"""
8484
_QuickpulseManager(**kwargs)
85+
# We can detect feature usage for statsbeat since we are in an opt-in model currently
86+
# Once we move to live metrics on-by-default, we will have to check for both explicit usage
87+
# and whether or not user is actually using live metrics (being on live metrics blade in UX)
8588
set_statsbeat_live_metrics_feature_set()
8689

8790

sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/statsbeat/_statsbeat_metrics.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,9 @@ def _get_feature_metric(self, options: CallbackOptions) -> Iterable[Observation]
241241
if get_statsbeat_custom_events_feature_set():
242242
self._feature |= _StatsbeatFeature.CUSTOM_EVENTS_EXTENSION
243243
_StatsbeatMetrics._FEATURE_ATTRIBUTES["feature"] = self._feature
244+
if get_statsbeat_live_metrics_feature_set():
245+
self._feature |= _StatsbeatFeature.LIVE_METRICS
246+
_StatsbeatMetrics._FEATURE_ATTRIBUTES["feature"] = self._feature
244247

245248
# Don't send observation if no features enabled
246249
if self._feature is not _StatsbeatFeature.NONE:

sdk/monitor/azure-monitor-opentelemetry-exporter/tests/statsbeat/test_statsbeat.py

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,34 @@ def test_get_feature_metric_custom_events(self, feature_mock):
733733
self.assertEqual(obs.value, 1)
734734
self.assertEqual(obs.attributes, attributes)
735735

736+
# pylint: disable=protected-access
737+
def test_get_feature_metric_custom_events_runtime(self):
738+
mp = MeterProvider()
739+
ikey = "1aa11111-bbbb-1ccc-8ddd-eeeeffff3334"
740+
endpoint = "https://westus-1.in.applicationinsights.azure.com/"
741+
_STATSBEAT_STATE["CUSTOM_EVENTS_FEATURE_SET"] = False
742+
metric = _StatsbeatMetrics(
743+
mp,
744+
ikey,
745+
endpoint,
746+
True,
747+
0,
748+
False,
749+
)
750+
self.assertTrue((metric._feature >> 2) & 1 == 0)
751+
attributes = dict(_StatsbeatMetrics._COMMON_ATTRIBUTES)
752+
attributes.update(_StatsbeatMetrics._FEATURE_ATTRIBUTES)
753+
self.assertEqual(attributes["feature"], 0)
754+
self.assertEqual(attributes["type"], _FEATURE_TYPES.FEATURE)
755+
_STATSBEAT_STATE["CUSTOM_EVENTS_FEATURE_SET"] = True
756+
observations = metric._get_feature_metric(options=None)
757+
attributes["feature"] = _StatsbeatMetrics._FEATURE_ATTRIBUTES["feature"]
758+
for obs in observations:
759+
self.assertEqual(obs.value, 1)
760+
self.assertEqual(obs.attributes, attributes)
761+
self.assertTrue((_StatsbeatMetrics._FEATURE_ATTRIBUTES["feature"] >> 2) & 1 == 1)
762+
_STATSBEAT_STATE["CUSTOM_EVENTS_FEATURE_SET"] = False
763+
736764
# pylint: disable=protected-access
737765
@mock.patch(
738766
"azure.monitor.opentelemetry.exporter.statsbeat._statsbeat_metrics.get_statsbeat_live_metrics_feature_set"
@@ -742,7 +770,6 @@ def test_get_feature_metric_live_metrics(self, feature_mock):
742770
mp = MeterProvider()
743771
ikey = "1aa11111-bbbb-1ccc-8ddd-eeeeffff3334"
744772
endpoint = "https://westus-1.in.applicationinsights.azure.com/"
745-
_STATSBEAT_STATE["LIVE_METRICS_FEATURE_SET"] = True
746773
metric = _StatsbeatMetrics(
747774
mp,
748775
ikey,
@@ -759,6 +786,33 @@ def test_get_feature_metric_live_metrics(self, feature_mock):
759786
for obs in observations:
760787
self.assertEqual(obs.value, 1)
761788
self.assertEqual(obs.attributes, attributes)
789+
790+
# pylint: disable=protected-access
791+
def test_get_feature_metric_live_metrics_runtime(self):
792+
mp = MeterProvider()
793+
ikey = "1aa11111-bbbb-1ccc-8ddd-eeeeffff3334"
794+
endpoint = "https://westus-1.in.applicationinsights.azure.com/"
795+
_STATSBEAT_STATE["LIVE_METRICS_FEATURE_SET"] = False
796+
metric = _StatsbeatMetrics(
797+
mp,
798+
ikey,
799+
endpoint,
800+
True,
801+
0,
802+
False,
803+
)
804+
self.assertTrue((metric._feature >> 4) & 1 == 0)
805+
attributes = dict(_StatsbeatMetrics._COMMON_ATTRIBUTES)
806+
attributes.update(_StatsbeatMetrics._FEATURE_ATTRIBUTES)
807+
self.assertEqual(attributes["feature"], 0)
808+
self.assertEqual(attributes["type"], _FEATURE_TYPES.FEATURE)
809+
_STATSBEAT_STATE["LIVE_METRICS_FEATURE_SET"] = True
810+
observations = metric._get_feature_metric(options=None)
811+
attributes["feature"] = _StatsbeatMetrics._FEATURE_ATTRIBUTES["feature"]
812+
for obs in observations:
813+
self.assertEqual(obs.value, 1)
814+
self.assertEqual(obs.attributes, attributes)
815+
self.assertTrue((_StatsbeatMetrics._FEATURE_ATTRIBUTES["feature"] >> 4) & 1 == 1)
762816
_STATSBEAT_STATE["LIVE_METRICS_FEATURE_SET"] = False
763817

764818
# pylint: disable=protected-access

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
([#38549](https://github.com/Azure/azure-sdk-for-python/pull/38549))
99
- Distro to automatically configure event logger provider
1010
([#38543](https://github.com/Azure/azure-sdk-for-python/pull/38543))
11+
- Configure live metrics first in pipeline to detect statsbeat usage
12+
([#37694](https://github.com/Azure/azure-sdk-for-python/pull/37694))
1113

1214
### Breaking Changes
1315

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from logging import getLogger
88
from typing import Dict, List, cast
99

10-
from opentelemetry._events import set_event_logger_provider
10+
from opentelemetry._events import _set_event_logger_provider
1111
from opentelemetry._logs import set_logger_provider
1212
from opentelemetry.instrumentation.dependencies import (
1313
get_dist_dependency_conflicts,
@@ -115,6 +115,10 @@ def configure_azure_monitor(**kwargs) -> None: # pylint: disable=C4758
115115
disable_metrics = configurations[DISABLE_METRICS_ARG]
116116
enable_live_metrics_config = configurations[ENABLE_LIVE_METRICS_ARG]
117117

118+
# Setup live metrics
119+
if enable_live_metrics_config:
120+
_setup_live_metrics(configurations)
121+
118122
# Setup tracing pipeline
119123
if not disable_tracing:
120124
_setup_tracing(configurations)
@@ -127,10 +131,6 @@ def configure_azure_monitor(**kwargs) -> None: # pylint: disable=C4758
127131
if not disable_metrics:
128132
_setup_metrics(configurations)
129133

130-
# Setup live metrics
131-
if enable_live_metrics_config:
132-
_setup_live_metrics(configurations)
133-
134134
# Setup instrumentations
135135
# Instrumentations need to be setup last so to use the global providers
136136
# instanstiated in the other setup steps
@@ -180,7 +180,7 @@ def _setup_logging(configurations: Dict[str, ConfigurationValue]):
180180

181181
# Setup EventLoggerProvider
182182
event_provider = EventLoggerProvider(logger_provider)
183-
set_event_logger_provider(event_provider)
183+
_set_event_logger_provider(event_provider, False)
184184

185185

186186
def _setup_metrics(configurations: Dict[str, ConfigurationValue]):

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ def test_setup_tracing(
305305
self.assertEqual(azure_core_mock.tracing_implementation, OpenTelemetrySpan)
306306

307307
@patch(
308-
"azure.monitor.opentelemetry._configure.set_event_logger_provider",
308+
"azure.monitor.opentelemetry._configure._set_event_logger_provider",
309309
)
310310
@patch(
311311
"azure.monitor.opentelemetry._configure.EventLoggerProvider",
@@ -373,7 +373,7 @@ def test_setup_logging(
373373
get_logger_mock.assert_called_once_with("test")
374374
logger_mock.addHandler.assert_called_once_with(logging_handler_init_mock)
375375
elp_mock.assert_called_once_with(lp_init_mock)
376-
set_elp_mock.assert_called_once_with(elp_init_mock)
376+
set_elp_mock.assert_called_once_with(elp_init_mock, False)
377377

378378
@patch(
379379
"azure.monitor.opentelemetry._configure.getLogger",

0 commit comments

Comments
 (0)