Skip to content
This repository was archived by the owner on Sep 17, 2025. It is now read-only.

Commit eaf9f2d

Browse files
authored
[Stats] Apply init + long logic to attach rate metrics (#1054)
1 parent 6e522f7 commit eaf9f2d

File tree

10 files changed

+111
-25
lines changed

10 files changed

+111
-25
lines changed

contrib/opencensus-ext-azure/opencensus/ext/azure/common/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ def __init__(self, *args, **kwargs):
111111
credential=None, # Credential class used by AAD auth
112112
enable_local_storage=True,
113113
enable_standard_metrics=True, # Used by metrics exporter, True to send standard metrics # noqa: E501
114+
enable_stats_metrics=True, # True to send stats metrics
114115
endpoint='https://dc.services.visualstudio.com/v2/track',
115116
export_interval=15.0,
116117
grace_period=5.0,

contrib/opencensus-ext-azure/opencensus/ext/azure/log_exporter/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,10 @@ def __init__(self, **options):
6363
self._worker = Worker(self._queue, self)
6464
self._worker.start()
6565
# start statsbeat on exporter instantiation
66-
statsbeat_metrics.collect_statsbeat_metrics(
67-
self.options.instrumentation_key
68-
)
66+
if self.options.enable_stats_metrics:
67+
statsbeat_metrics.collect_statsbeat_metrics(
68+
self.options.instrumentation_key
69+
)
6970

7071
def _export(self, batch, event=None): # pragma: NO COVER
7172
try:

contrib/opencensus-ext-azure/opencensus/ext/azure/metrics_exporter/__init__.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ def _create_envelope(self, data_point, timestamp, properties):
145145

146146
def shutdown(self):
147147
# Flush the exporter thread
148-
if self.exporter_thread:
148+
# Do not flush if metrics exporter for stats
149+
if self.exporter_thread and not self._is_stats:
149150
self.exporter_thread.close()
150151
# Shutsdown storage worker
151152
if self.storage:
@@ -161,9 +162,10 @@ def new_metrics_exporter(**options):
161162
producers,
162163
exporter,
163164
interval=exporter.options.export_interval)
164-
from opencensus.ext.azure.metrics_exporter import statsbeat_metrics
165-
# Stats will track the user's ikey
166-
statsbeat_metrics.collect_statsbeat_metrics(
167-
exporter.options.instrumentation_key
168-
)
165+
if exporter.options.enable_stats_metrics:
166+
from opencensus.ext.azure.metrics_exporter import statsbeat_metrics
167+
# Stats will track the user's ikey
168+
statsbeat_metrics.collect_statsbeat_metrics(
169+
exporter.options.instrumentation_key
170+
)
169171
return exporter

contrib/opencensus-ext-azure/opencensus/ext/azure/metrics_exporter/statsbeat_metrics/__init__.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from opencensus.ext.azure.metrics_exporter import MetricsExporter
1818
from opencensus.ext.azure.metrics_exporter.statsbeat_metrics.statsbeat import (
1919
_STATS_CONNECTION_STRING,
20-
_STATS_SHORT_EXPORT_INTERVAL,
20+
_STATS_LONG_EXPORT_INTERVAL,
2121
_StatsbeatMetrics,
2222
)
2323
from opencensus.metrics import transport
@@ -35,13 +35,16 @@ def collect_statsbeat_metrics(ikey):
3535
exporter = MetricsExporter(
3636
is_stats=True,
3737
connection_string=_STATS_CONNECTION_STRING,
38-
export_interval=_STATS_SHORT_EXPORT_INTERVAL, # 15 minutes by default # noqa: E501
38+
enable_standard_metrics=False,
39+
export_interval=_STATS_LONG_EXPORT_INTERVAL, # 24h by default
3940
)
4041
# The user's ikey is the one being tracked
4142
producer = _AzureStatsbeatMetricsProducer(
4243
instrumentation_key=ikey
4344
)
4445
_STATSBEAT_METRICS = producer
46+
# Export some initial stats on program start
47+
exporter.export_metrics(_STATSBEAT_METRICS.get_initial_metrics())
4548
exporter.exporter_thread = \
4649
transport.get_exporter_thread([_STATSBEAT_METRICS],
4750
exporter,
@@ -58,3 +61,6 @@ def __init__(self, instrumentation_key):
5861

5962
def get_metrics(self):
6063
return self._statsbeat.get_metrics()
64+
65+
def get_initial_metrics(self):
66+
return self._statsbeat.get_initial_metrics()

contrib/opencensus-ext-azure/opencensus/ext/azure/metrics_exporter/statsbeat_metrics/statsbeat.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
_AIMS_FORMAT = "format=json"
3030

3131
_DEFAULT_STATS_CONNECTION_STRING = "InstrumentationKey=c4a29126-a7cb-47e5-b348-11414998b11e;IngestionEndpoint=https://dc.services.visualstudio.com/" # noqa: E501
32-
_DEFAULT_STATS_SHORT_EXPORT_INTERVAL = 900
32+
_DEFAULT_STATS_SHORT_EXPORT_INTERVAL = 900 # 15 minutes
33+
_DEFAULT_STATS_LONG_EXPORT_INTERVAL = 86400 # 24 hours
3334

3435
_ATTACH_METRIC_NAME = "Attach"
3536

@@ -52,8 +53,17 @@ def _get_stats_short_export_interval():
5253
return _DEFAULT_STATS_SHORT_EXPORT_INTERVAL
5354

5455

56+
def _get_stats_long_export_interval():
57+
ei_env = os.environ.get("APPLICATION_INSIGHTS_STATS_LONG_EXPORT_INTERVAL")
58+
if ei_env:
59+
return ei_env
60+
else:
61+
return _DEFAULT_STATS_LONG_EXPORT_INTERVAL
62+
63+
5564
_STATS_CONNECTION_STRING = _get_stats_connection_string()
5665
_STATS_SHORT_EXPORT_INTERVAL = _get_stats_short_export_interval()
66+
_STATS_LONG_EXPORT_INTERVAL = _get_stats_long_export_interval()
5767

5868

5969
def _get_attach_properties():
@@ -84,12 +94,16 @@ def __init__(self, instrumentation_key):
8494
_get_attach_properties(),
8595
)
8696

87-
def get_metrics(self):
97+
def get_initial_metrics(self):
8898
stats_metrics = []
8999
if self._attach_metric:
90100
attach_metric = self._get_attach_metric(self._attach_metric)
91101
if attach_metric:
92102
stats_metrics.append(attach_metric)
103+
return stats_metrics
104+
105+
def get_metrics(self):
106+
stats_metrics = self.get_initial_metrics()
93107

94108
return stats_metrics
95109

@@ -125,7 +139,7 @@ def _get_attach_metric(self, metric):
125139
else:
126140
# Not in any rp or VM metadata failed
127141
properties.append(LabelValue(_RP_NAMES[3]))
128-
properties.append(LabelValue(""))
142+
properties.append(LabelValue(_RP_NAMES[3]))
129143

130144
properties.append(LabelValue("sdk")) # attach type
131145
properties.append(LabelValue(self._instrumentation_key)) # cikey

contrib/opencensus-ext-azure/opencensus/ext/azure/trace_exporter/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,10 @@ def __init__(self, **options):
7474
super(AzureExporter, self).__init__(**options)
7575
atexit.register(self._stop, self.options.grace_period)
7676
# start statsbeat on exporter instantiation
77-
statsbeat_metrics.collect_statsbeat_metrics(
78-
self.options.instrumentation_key
79-
)
77+
if self.options.enable_stats_metrics:
78+
statsbeat_metrics.collect_statsbeat_metrics(
79+
self.options.instrumentation_key
80+
)
8081

8182
def span_data_to_envelope(self, sd):
8283
envelope = Envelope(

contrib/opencensus-ext-azure/tests/test_azure_log_exporter.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ def __init__(self, max_batch_size, callback):
4545
self.callback = callback
4646
super(CustomLogHandler, self).__init__(
4747
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
48+
enable_stats_metrics=False,
4849
)
4950

5051
def export(self, batch):
@@ -77,12 +78,15 @@ def test_ctor(self):
7778
from opencensus.ext.azure.common import Options
7879
instrumentation_key = Options._default.instrumentation_key
7980
Options._default.instrumentation_key = None
80-
self.assertRaises(ValueError, lambda: log_exporter.AzureLogHandler())
81+
self.assertRaises(ValueError, lambda: log_exporter.AzureLogHandler(
82+
enable_stats_metrics=False,
83+
))
8184
Options._default.instrumentation_key = instrumentation_key
8285

8386
def test_invalid_sampling_rate(self):
8487
with self.assertRaises(ValueError):
8588
log_exporter.AzureLogHandler(
89+
enable_stats_metrics=False,
8690
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
8791
logging_sampling_rate=4.0,
8892
)
@@ -100,6 +104,7 @@ def test_init_handler_with_proxies(self):
100104

101105
def test_init_handler_with_queue_capacity(self):
102106
handler = log_exporter.AzureLogHandler(
107+
enable_stats_metrics=False,
103108
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
104109
queue_capacity=500,
105110
)
@@ -118,6 +123,7 @@ def test_init_handler_with_queue_capacity(self):
118123
def test_exception(self, requests_mock):
119124
logger = logging.getLogger(self.id())
120125
handler = log_exporter.AzureLogHandler(
126+
enable_stats_metrics=False,
121127
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
122128
storage_path=os.path.join(TEST_FOLDER, self.id()),
123129
)
@@ -135,6 +141,7 @@ def test_exception(self, requests_mock):
135141
def test_exception_with_custom_properties(self, requests_mock):
136142
logger = logging.getLogger(self.id())
137143
handler = log_exporter.AzureLogHandler(
144+
enable_stats_metrics=False,
138145
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
139146
storage_path=os.path.join(TEST_FOLDER, self.id()),
140147
)
@@ -160,6 +167,7 @@ def test_exception_with_custom_properties(self, requests_mock):
160167
@mock.patch('requests.post', return_value=mock.Mock())
161168
def test_export_empty(self, request_mock):
162169
handler = log_exporter.AzureLogHandler(
170+
enable_stats_metrics=False,
163171
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
164172
storage_path=os.path.join(TEST_FOLDER, self.id()),
165173
)
@@ -172,6 +180,7 @@ def test_export_empty(self, request_mock):
172180
def test_export_failure(self, log_record_to_envelope_mock):
173181
log_record_to_envelope_mock.return_value = ['bar']
174182
handler = log_exporter.AzureLogHandler(
183+
enable_stats_metrics=False,
175184
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
176185
storage_path=os.path.join(TEST_FOLDER, self.id()),
177186
)
@@ -185,6 +194,7 @@ def test_export_failure(self, log_record_to_envelope_mock):
185194

186195
def test_log_record_to_envelope(self):
187196
handler = log_exporter.AzureLogHandler(
197+
enable_stats_metrics=False,
188198
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
189199
storage_path=os.path.join(TEST_FOLDER, self.id()),
190200
)
@@ -201,6 +211,7 @@ def test_log_record_to_envelope(self):
201211
def test_log_record_with_custom_properties(self, requests_mock):
202212
logger = logging.getLogger(self.id())
203213
handler = log_exporter.AzureLogHandler(
214+
enable_stats_metrics=False,
204215
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
205216
storage_path=os.path.join(TEST_FOLDER, self.id()),
206217
)
@@ -222,6 +233,7 @@ def test_log_record_with_custom_properties(self, requests_mock):
222233
def test_log_with_invalid_custom_properties(self, requests_mock):
223234
logger = logging.getLogger(self.id())
224235
handler = log_exporter.AzureLogHandler(
236+
enable_stats_metrics=False,
225237
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
226238
storage_path=os.path.join(TEST_FOLDER, self.id()),
227239
)
@@ -248,6 +260,7 @@ def test_log_with_invalid_custom_properties(self, requests_mock):
248260
def test_log_record_sampled(self, requests_mock):
249261
logger = logging.getLogger(self.id())
250262
handler = log_exporter.AzureLogHandler(
263+
enable_stats_metrics=False,
251264
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
252265
logging_sampling_rate=1.0,
253266
)
@@ -267,6 +280,7 @@ def test_log_record_sampled(self, requests_mock):
267280
def test_log_record_not_sampled(self, requests_mock):
268281
logger = logging.getLogger(self.id())
269282
handler = log_exporter.AzureLogHandler(
283+
enable_stats_metrics=False,
270284
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
271285
logging_sampling_rate=0.0,
272286
)
@@ -284,18 +298,22 @@ def test_ctor(self):
284298
from opencensus.ext.azure.common import Options
285299
instrumentation_key = Options._default.instrumentation_key
286300
Options._default.instrumentation_key = None
287-
self.assertRaises(ValueError, lambda: log_exporter.AzureEventHandler())
301+
self.assertRaises(ValueError, lambda: log_exporter.AzureEventHandler(
302+
enable_stats_metrics=False,
303+
))
288304
Options._default.instrumentation_key = instrumentation_key
289305

290306
def test_invalid_sampling_rate(self):
291307
with self.assertRaises(ValueError):
292308
log_exporter.AzureEventHandler(
309+
enable_stats_metrics=False,
293310
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
294311
logging_sampling_rate=4.0,
295312
)
296313

297314
def test_init_handler_with_proxies(self):
298315
handler = log_exporter.AzureEventHandler(
316+
enable_stats_metrics=False,
299317
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
300318
proxies='{"https":"https://test-proxy.com"}',
301319
)
@@ -307,6 +325,7 @@ def test_init_handler_with_proxies(self):
307325

308326
def test_init_handler_with_queue_capacity(self):
309327
handler = log_exporter.AzureEventHandler(
328+
enable_stats_metrics=False,
310329
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
311330
queue_capacity=500,
312331
)
@@ -325,6 +344,7 @@ def test_init_handler_with_queue_capacity(self):
325344
def test_exception(self, requests_mock):
326345
logger = logging.getLogger(self.id())
327346
handler = log_exporter.AzureEventHandler(
347+
enable_stats_metrics=False,
328348
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
329349
storage_path=os.path.join(TEST_FOLDER, self.id()),
330350
)
@@ -342,6 +362,7 @@ def test_exception(self, requests_mock):
342362
def test_exception_with_custom_properties(self, requests_mock):
343363
logger = logging.getLogger(self.id())
344364
handler = log_exporter.AzureEventHandler(
365+
enable_stats_metrics=False,
345366
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
346367
storage_path=os.path.join(TEST_FOLDER, self.id()),
347368
)
@@ -367,6 +388,7 @@ def test_exception_with_custom_properties(self, requests_mock):
367388
@mock.patch('requests.post', return_value=mock.Mock())
368389
def test_export_empty(self, request_mock):
369390
handler = log_exporter.AzureEventHandler(
391+
enable_stats_metrics=False,
370392
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
371393
storage_path=os.path.join(TEST_FOLDER, self.id()),
372394
)
@@ -379,6 +401,7 @@ def test_export_empty(self, request_mock):
379401
def test_export_failure(self, log_record_to_envelope_mock):
380402
log_record_to_envelope_mock.return_value = ['bar']
381403
handler = log_exporter.AzureEventHandler(
404+
enable_stats_metrics=False,
382405
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
383406
storage_path=os.path.join(TEST_FOLDER, self.id()),
384407
)
@@ -392,6 +415,7 @@ def test_export_failure(self, log_record_to_envelope_mock):
392415

393416
def test_log_record_to_envelope(self):
394417
handler = log_exporter.AzureEventHandler(
418+
enable_stats_metrics=False,
395419
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
396420
storage_path=os.path.join(TEST_FOLDER, self.id()),
397421
)
@@ -408,6 +432,7 @@ def test_log_record_to_envelope(self):
408432
def test_log_record_with_custom_properties(self, requests_mock):
409433
logger = logging.getLogger(self.id())
410434
handler = log_exporter.AzureEventHandler(
435+
enable_stats_metrics=False,
411436
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
412437
storage_path=os.path.join(TEST_FOLDER, self.id()),
413438
)
@@ -429,6 +454,7 @@ def test_log_record_with_custom_properties(self, requests_mock):
429454
def test_log_with_invalid_custom_properties(self, requests_mock):
430455
logger = logging.getLogger(self.id())
431456
handler = log_exporter.AzureEventHandler(
457+
enable_stats_metrics=False,
432458
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
433459
storage_path=os.path.join(TEST_FOLDER, self.id()),
434460
)
@@ -455,6 +481,7 @@ def test_log_with_invalid_custom_properties(self, requests_mock):
455481
def test_log_record_sampled(self, requests_mock):
456482
logger = logging.getLogger(self.id())
457483
handler = log_exporter.AzureEventHandler(
484+
enable_stats_metrics=False,
458485
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
459486
logging_sampling_rate=1.0,
460487
)
@@ -474,6 +501,7 @@ def test_log_record_sampled(self, requests_mock):
474501
def test_log_record_not_sampled(self, requests_mock):
475502
logger = logging.getLogger(self.id())
476503
handler = log_exporter.AzureEventHandler(
504+
enable_stats_metrics=False,
477505
instrumentation_key='12345678-1234-5678-abcd-12345678abcd',
478506
logging_sampling_rate=0.0,
479507
)

0 commit comments

Comments
 (0)