Skip to content

Commit

Permalink
Fix inifinite retry issue in telemetry upload
Browse files Browse the repository at this point in the history
  • Loading branch information
troydai committed Nov 30, 2017
1 parent 78f2c3f commit 6fea00b
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 9 deletions.
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
adal==0.4.7
applicationinsights==0.10.0
argcomplete==1.8.0
colorama==0.3.7
humanfriendly==2.4
Expand Down
1 change: 1 addition & 0 deletions src/azure-cli-core/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Release History
* Minor fixes
* Modified the AZURE_US_GOV_CLOUD's AAD authority endpoint from login.microsoftonline.com to login.microsoftonline.us.
* Introduce SDKProfile to support azure-mgmt-compute 3.1.0rc1 and integrated profile support.
* Improve telemetry: remove inifinity retry loop from SynchronousSender.

2.0.21
++++++
Expand Down
56 changes: 49 additions & 7 deletions src/azure-cli-core/azure/cli/core/telemetry_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,59 @@
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

try:
# Python 2.x
import urllib2 as HTTPClient
from urllib2 import HTTPError
except ImportError:
# Python 3.x
import urllib.request as HTTPClient
from urllib.error import HTTPError

import os
import sys
import json
import six
import azure.cli.core.decorators as decorators

from applicationinsights import TelemetryClient
from applicationinsights.exceptions import enable
from applicationinsights.channel import SynchronousSender, SynchronousQueue, TelemetryChannel

DIAGNOSTICS_TELEMETRY_ENV_NAME = 'AZURE_CLI_DIAGNOSTICS_TELEMETRY'
INSTRUMENTATION_KEY = 'c4395b75-49cc-422c-bc95-c7d51aef5d46'


class LimitedRetrySender(SynchronousSender):
def __init__(self):
super(LimitedRetrySender, self).__init__()
self.retry = 0

def send(self, data_to_send):
""" Override the default resend mechanism in SenderBase. Stop resend when it fails."""
request_payload = json.dumps([a.write() for a in data_to_send])

request = HTTPClient.Request(self._service_endpoint_uri, bytearray(request_payload, 'utf-8'),
{'Accept': 'application/json', 'Content-Type': 'application/json; charset=utf-8'})
try:
response = HTTPClient.urlopen(request)
status_code = response.getcode()
if 200 <= status_code < 300:
return
except HTTPError as e:
if e.getcode() == 400:
return
except Exception: # pylint: disable=broad-except
if self.retry < 3:
self.retry = self.retry + 1
else:
return

# Add our unsent data back on to the queue
for data in data_to_send:
self._queue.put(data)


def in_diagnostic_mode():
"""
When the telemetry runs in the diagnostic mode, exception are not suppressed and telemetry
Expand All @@ -23,10 +66,8 @@ def in_diagnostic_mode():

@decorators.suppress_all_exceptions(raise_in_diagnostics=True)
def upload(data_to_save):
from applicationinsights import TelemetryClient
from applicationinsights.exceptions import enable

client = TelemetryClient(INSTRUMENTATION_KEY)
client = TelemetryClient(instrumentation_key=INSTRUMENTATION_KEY,
telemetry_channel=TelemetryChannel(queue=SynchronousQueue(LimitedRetrySender())))
enable(INSTRUMENTATION_KEY)

if in_diagnostic_mode():
Expand All @@ -37,7 +78,7 @@ def upload(data_to_save):
data_to_save = json.loads(data_to_save.replace("'", '"'))
except Exception as err: # pylint: disable=broad-except
if in_diagnostic_mode():
sys.stdout.write('{}/n'.format(str(err)))
sys.stdout.write('ERROR: {}/n'.format(str(err)))
sys.stdout.write('Raw [{}]/n'.format(data_to_save))

for record in data_to_save:
Expand All @@ -54,8 +95,9 @@ def upload(data_to_save):
client.track_event(record['name'], properties, measurements)

if in_diagnostic_mode():
sys.stdout.write('\nTrack Event: {}\nProperties: {}\nMeasurements: {}'.format(
name, json.dumps(properties, indent=2), json.dumps(measurements, indent=2)))
sys.stdout.write(
'\nTrack Event: {}\nProperties: {}\nMeasurements: {}'.format(name, json.dumps(properties, indent=2),
json.dumps(measurements, indent=2)))

client.flush()

Expand Down
2 changes: 1 addition & 1 deletion src/azure-cli-core/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
# TODO These dependencies should be updated to reflect only what this package needs
DEPENDENCIES = [
'adal>=0.4.7',
'applicationinsights',
'applicationinsights>=0.11.1',
'argcomplete>=1.8.0',
'colorama',
'humanfriendly',
Expand Down

0 comments on commit 6fea00b

Please sign in to comment.