Files
edx-platform/lms/lib/comment_client/utils.py
Greg Price bd477581b6 Log all comments service requests
Logging the duration of each request will allow us to determine
whether there is a significant difference in the latency reported by
the comments service and that observed by the LMS. Each request will
be assigned a unique identifier to allow correlation of the reported
latency on each end.
2013-10-16 16:31:59 -04:00

108 lines
2.9 KiB
Python

from contextlib import contextmanager
from dogapi import dog_stats_api
import json
import logging
import requests
import settings
from time import time
from uuid import uuid4
log = logging.getLogger(__name__)
def strip_none(dic):
return dict([(k, v) for k, v in dic.iteritems() if v is not None])
def strip_blank(dic):
def _is_blank(v):
return isinstance(v, str) and len(v.strip()) == 0
return dict([(k, v) for k, v in dic.iteritems() if not _is_blank(v)])
def extract(dic, keys):
if isinstance(keys, str):
return strip_none({keys: dic.get(keys)})
else:
return strip_none({k: dic.get(k) for k in keys})
def merge_dict(dic1, dic2):
return dict(dic1.items() + dic2.items())
@contextmanager
def request_timer(request_id, method, url):
start = time()
yield
end = time()
duration = end - start
dog_stats_api.histogram('comment_client.request.time', duration, end)
log.info(
"comment_client_request_log: request_id={request_id}, method={method}, "
"url={url}, duration={duration}".format(
request_id=request_id,
method=method,
url=url,
duration=duration
)
)
def perform_request(method, url, data_or_params=None, *args, **kwargs):
if data_or_params is None:
data_or_params = {}
headers = {'X-Edx-Api-Key': settings.API_KEY}
request_id = uuid4()
request_id_dict = {'request_id': request_id}
try:
if method in ['post', 'put', 'patch']:
data = data_or_params
params = request_id_dict
else:
data = None
params = merge_dict(data_or_params, request_id_dict)
with request_timer(request_id, method, url):
response = requests.request(
method,
url,
data=data,
params=params,
headers=headers,
timeout=5
)
except Exception as err:
log.exception("Trying to call {method} on {url} with params {params}".format(
method=method, url=url, params=data_or_params))
# Reraise with a single exception type
raise CommentClientError(str(err))
if 200 < response.status_code < 500:
raise CommentClientError(response.text)
# Heroku returns a 503 when an application is in maintenance mode
elif response.status_code == 503:
raise CommentClientMaintenanceError(response.text)
elif response.status_code == 500:
raise CommentClientUnknownError(response.text)
else:
if kwargs.get("raw", False):
return response.text
else:
return json.loads(response.text)
class CommentClientError(Exception):
def __init__(self, msg):
self.message = msg
def __str__(self):
return repr(self.message)
class CommentClientMaintenanceError(CommentClientError):
pass
class CommentClientUnknownError(CommentClientError):
pass