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

Commit c609ef0

Browse files
authored
Fix statsbeat bugs (#1113)
1 parent 56386a1 commit c609ef0

File tree

7 files changed

+388
-54
lines changed

7 files changed

+388
-54
lines changed

contrib/opencensus-ext-azure/CHANGELOG.md

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

33
## Unreleased
44

5+
- Statsbeat bug fixes
6+
([#1113](https://github.com/census-instrumentation/opencensus-python/pull/1113))
7+
58
## 1.1.3
69
Released 2022-03-03
710

contrib/opencensus-ext-azure/examples/logs/simple.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@
2121
# and place it in the APPLICATIONINSIGHTS_CONNECTION_STRING
2222
# environment variable.
2323
logger.addHandler(AzureLogHandler())
24+
25+
logger.warning("Hello World!")

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

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,6 @@ def _transmit(self, envelopes):
9494
except requests.RequestException as ex:
9595
logger.warning(
9696
'Retrying due to transient client side error %s.', ex)
97-
if self._check_stats_collection():
98-
with _requests_lock:
99-
_requests_map['retry'] = _requests_map.get('retry', 0) + 1 # noqa: E501
10097
# client side error (retryable)
10198
exception = self.options.minimum_retry_interval
10299
except CredentialUnavailableError as ex:
@@ -108,9 +105,6 @@ def _transmit(self, envelopes):
108105
except Exception as ex:
109106
logger.warning(
110107
'Error when sending request %s. Dropping telemetry.', ex)
111-
if self._check_stats_collection():
112-
with _requests_lock:
113-
_requests_map['exception'] = _requests_map.get('exception', 0) + 1 # noqa: E501
114108
# Extraneous error (non-retryable)
115109
exception = -1
116110
finally:
@@ -120,6 +114,13 @@ def _transmit(self, envelopes):
120114
duration = _requests_map.get('duration', 0)
121115
_requests_map['duration'] = duration + (end_time - start_time) # noqa: E501
122116
if exception is not None:
117+
if self._check_stats_collection():
118+
with _requests_lock:
119+
if exception >= 0:
120+
_requests_map['retry'] = _requests_map.get('retry', 0) + 1 # noqa: E501
121+
else:
122+
_requests_map['exception'] = _requests_map.get('exception', 0) + 1 # noqa: E501
123+
123124
return exception
124125

125126
text = 'N/A'
@@ -139,10 +140,11 @@ def _transmit(self, envelopes):
139140
with _requests_lock:
140141
_requests_map['success'] = _requests_map.get('success', 0) + 1 # noqa: E501
141142
return 0
142-
# Status code not 200 counts as failure
143+
# Status code not 200, 439 or 402 counts as failures
143144
if self._check_stats_collection():
144-
with _requests_lock:
145-
_requests_map['failure'] = _requests_map.get('failure', 0) + 1 # noqa: E501
145+
if response.status_code != 439 and response.status_code != 402:
146+
with _requests_lock:
147+
_requests_map['failure'] = _requests_map.get('failure', 0) + 1 # noqa: E501
146148
if response.status_code == 206: # Partial Content
147149
if data:
148150
try:
@@ -162,6 +164,9 @@ def _transmit(self, envelopes):
162164
envelopes[error['index']],
163165
)
164166
if resend_envelopes:
167+
if self._check_stats_collection():
168+
with _requests_lock:
169+
_requests_map['retry'] = _requests_map.get('retry', 0) + 1 # noqa: E501
165170
self.storage.put(resend_envelopes)
166171
except Exception as ex:
167172
logger.error(
@@ -170,9 +175,6 @@ def _transmit(self, envelopes):
170175
text,
171176
ex,
172177
)
173-
if self._check_stats_collection():
174-
with _requests_lock:
175-
_requests_map['retry'] = _requests_map.get('retry', 0) + 1 # noqa: E501
176178
return -response.status_code
177179
# cannot parse response body, fallback to retry
178180
if response.status_code in (
@@ -189,11 +191,7 @@ def _transmit(self, envelopes):
189191
# server side error (retryable)
190192
if self._check_stats_collection():
191193
with _requests_lock:
192-
# 429 counts as throttle instead of retry
193-
if response.status_code == 429:
194-
_requests_map['throttle'] = _requests_map.get('throttle', 0) + 1 # noqa: E501
195-
else:
196-
_requests_map['retry'] = _requests_map.get('retry', 0) + 1 # noqa: E501
194+
_requests_map['retry'] = _requests_map.get('retry', 0) + 1 # noqa: E501
197195
return self.options.minimum_retry_interval
198196
# Authentication error
199197
if response.status_code == 401:
@@ -235,14 +233,25 @@ def _transmit(self, envelopes):
235233
logger.error(
236234
"Error parsing redirect information."
237235
)
238-
logger.error(
239-
"Error sending telemetry because of circular redirects."
240-
" Please check the integrity of your connection string."
241-
)
236+
else:
237+
logger.error(
238+
"Error sending telemetry because of circular redirects."
239+
" Please check the integrity of your connection string."
240+
)
241+
# If redirect but did not return, exception occured
242+
if self._check_stats_collection():
243+
with _requests_lock:
244+
_requests_map['exception'] = _requests_map.get('exception', 0) + 1 # noqa: E501
245+
# Other, server side error (non-retryable)
242246
logger.error(
243247
'Non-retryable server side error %s: %s.',
244248
response.status_code,
245249
text,
246250
)
247-
# server side error (non-retryable)
251+
if self._check_stats_collection():
252+
if response.status_code == 402 or response.status_code == 439:
253+
# 402: Monthly Quota Exceeded (new SDK)
254+
# 439: Monthly Quota Exceeded (old SDK) <- Currently OC SDK
255+
with _requests_lock:
256+
_requests_map['throttle'] = _requests_map.get('throttle', 0) + 1 # noqa: E501
248257
return -response.status_code

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

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -150,27 +150,24 @@ def _get_feature_properties():
150150

151151
def _get_success_count_value():
152152
with _requests_lock:
153-
interval_count = _requests_map.get('success', 0) \
154-
- _requests_map.get('last_success', 0)
155-
_requests_map['last_success'] = _requests_map.get('success', 0)
153+
interval_count = _requests_map.get('success', 0)
154+
_requests_map['success'] = 0
156155
return interval_count
157156

158157

159158
def _get_failure_count_value():
160159
with _requests_lock:
161-
interval_count = _requests_map.get('failure', 0) \
162-
- _requests_map.get('last_failure', 0)
163-
_requests_map['last_failure'] = _requests_map.get('failure', 0)
160+
interval_count = _requests_map.get('failure', 0)
161+
_requests_map['failure'] = 0
164162
return interval_count
165163

166164

167165
def _get_average_duration_value():
168166
with _requests_lock:
169-
interval_duration = _requests_map.get('duration', 0) \
170-
- _requests_map.get('last_duration', 0)
171-
interval_count = _requests_map.get('count', 0) \
172-
- _requests_map.get('last_count', 0)
173-
_requests_map['last_duration'] = _requests_map.get('duration', 0)
167+
interval_duration = _requests_map.get('duration', 0)
168+
interval_count = _requests_map.get('count', 0)
169+
_requests_map['duration'] = 0
170+
_requests_map['count'] = 0
174171
if interval_duration > 0 and interval_count > 0:
175172
result = interval_duration / interval_count
176173
# Convert to milliseconds
@@ -180,25 +177,22 @@ def _get_average_duration_value():
180177

181178
def _get_retry_count_value():
182179
with _requests_lock:
183-
interval_count = _requests_map.get('retry', 0) \
184-
- _requests_map.get('last_retry', 0)
185-
_requests_map['last_retry'] = _requests_map.get('retry', 0)
180+
interval_count = _requests_map.get('retry', 0)
181+
_requests_map['retry'] = 0
186182
return interval_count
187183

188184

189185
def _get_throttle_count_value():
190186
with _requests_lock:
191-
interval_count = _requests_map.get('throttle', 0) \
192-
- _requests_map.get('last_throttle', 0)
193-
_requests_map['last_throttle'] = _requests_map.get('throttle', 0)
187+
interval_count = _requests_map.get('throttle', 0)
188+
_requests_map['throttle'] = 0
194189
return interval_count
195190

196191

197192
def _get_exception_count_value():
198193
with _requests_lock:
199-
interval_count = _requests_map.get('exception', 0) \
200-
- _requests_map.get('last_exception', 0)
201-
_requests_map['last_exception'] = _requests_map.get('exception', 0)
194+
interval_count = _requests_map.get('exception', 0)
195+
_requests_map['exception'] = 0
202196
return interval_count
203197

204198

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

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -337,10 +337,46 @@ def test_get_common_properties(self):
337337

338338
def test_get_success_count_value(self):
339339
_requests_map.clear()
340-
_requests_map['last_success'] = 5
341340
_requests_map['success'] = 10
342-
self.assertEqual(_get_success_count_value(), 5)
343-
self.assertEqual(_requests_map['last_success'], 10)
341+
self.assertEqual(_get_success_count_value(), 10)
342+
self.assertEqual(_requests_map['success'], 0)
343+
_requests_map.clear()
344+
345+
def test_get_failure_count_value(self):
346+
_requests_map.clear()
347+
_requests_map['failure'] = 10
348+
self.assertEqual(_get_failure_count_value(), 10)
349+
self.assertEqual(_requests_map['failure'], 0)
350+
_requests_map.clear()
351+
352+
def test_get_average_duration_value(self):
353+
_requests_map.clear()
354+
_requests_map['duration'] = 10
355+
_requests_map['count'] = 2
356+
self.assertEqual(_get_average_duration_value(), 5000.0)
357+
self.assertEqual(_requests_map['duration'], 0)
358+
self.assertEqual(_requests_map['count'], 0)
359+
_requests_map.clear()
360+
361+
def test_get_retry_count_value(self):
362+
_requests_map.clear()
363+
_requests_map['retry'] = 10
364+
self.assertEqual(_get_retry_count_value(), 10)
365+
self.assertEqual(_requests_map['retry'], 0)
366+
_requests_map.clear()
367+
368+
def test_get_throttle_count_value(self):
369+
_requests_map.clear()
370+
_requests_map['throttle'] = 10
371+
self.assertEqual(_get_throttle_count_value(), 10)
372+
self.assertEqual(_requests_map['throttle'], 0)
373+
_requests_map.clear()
374+
375+
def test_get_exception_count_value(self):
376+
_requests_map.clear()
377+
_requests_map['exception'] = 10
378+
self.assertEqual(_get_exception_count_value(), 10)
379+
self.assertEqual(_requests_map['exception'], 0)
344380
_requests_map.clear()
345381

346382
def test_statsbeat_metric_get_initial_metrics(self):

0 commit comments

Comments
 (0)