Updated clients to have a more robust error handling

- fire text and omg much more similar. Ready to be combined.
- Error handling now for JSON valid responses
This commit is contained in:
Martyn Inglis
2016-09-22 17:18:05 +01:00
parent 37a2dc7925
commit 376f8355cb
7 changed files with 146 additions and 80 deletions

View File

@@ -1,8 +1,9 @@
import json
from monotonic import monotonic
from requests import (request, RequestException, HTTPError)
from requests import (request, RequestException)
from app.clients import (STATISTICS_DELIVERED, STATISTICS_FAILURE)
from app.clients.sms import (SmsClient, SmsClientException)
from app.clients.sms import (SmsClient, SmsClientResponseException)
mmg_response_map = {
'2': {
@@ -42,13 +43,14 @@ def get_mmg_responses(status):
return mmg_response_map.get(status, mmg_response_map.get('default'))
class MMGClientException(SmsClientException):
def __init__(self, error_response):
self.code = error_response['Error']
self.description = error_response['Description']
class MMGClientResponseException(SmsClientResponseException):
def __init__(self, response, exception):
self.status_code = response.status_code
self.text = response.text
self.exception = exception
def __str__(self):
return "Code {} description {}".format(self.code, self.description)
return "Code {} text {} exception {}".format(self.status_code, self.text, str(self.exception))
class MMGClient(SmsClient):
@@ -65,6 +67,22 @@ class MMGClient(SmsClient):
self.statsd_client = statsd_client
self.mmg_url = current_app.config.get('MMG_URL')
def record_outcome(self, success, response):
log_message = "API {} request {} on {} response status_code {} response text'{}'".format(
"POST",
"succeeded" if success else "failed",
self.mmg_url,
response.status_code,
response.text
)
if not success:
self.statsd_client.incr("clients.mmg.error")
self.current_app.logger.error(log_message)
else:
self.current_app.logger.info(log_message)
self.statsd_client.incr("clients.mmg.success")
def get_name(self):
return self.name
@@ -79,38 +97,30 @@ class MMGClient(SmsClient):
}
start_time = monotonic()
try:
response = request("POST", self.mmg_url,
data=json.dumps(data),
headers={'Content-Type': 'application/json',
'Authorization': 'Basic {}'.format(self.api_key)})
if response.status_code != 200:
raise MMGClientException(response.json())
response = request(
"POST",
self.mmg_url,
data=json.dumps(data),
headers={
'Content-Type': 'application/json',
'Authorization': 'Basic {}'.format(self.api_key)
}
)
response.raise_for_status()
self.current_app.logger.info(
"API {} request on {} succeeded with {} '{}'".format(
"POST",
self.mmg_url,
response.status_code,
response.json().items()
)
)
try:
json.loads(response.text)
except (ValueError, AttributeError) as e:
self.record_outcome(False, response)
raise MMGClientResponseException(response=response, exception=e)
self.record_outcome(True, response)
except RequestException as e:
api_error = HTTPError.create(e)
self.current_app.logger.error(
"API {} request on {} failed with {} '{}'".format(
"POST",
self.mmg_url,
api_error.status_code,
api_error.message
)
)
self.statsd_client.incr("clients.mmg.error")
raise api_error
self.record_outcome(False, e.response)
raise MMGClientResponseException(response=e.response, exception=e)
finally:
elapsed_time = monotonic() - start_time
self.statsd_client.timing("clients.mmg.request-time", elapsed_time)
self.statsd_client.incr("clients.mmg.success")
self.current_app.logger.info("MMG request finished in {}".format(elapsed_time))
return response