diff --git a/server/djrandom/frontend/latency.py b/server/djrandom/frontend/latency.py index 851ca2780f27844b3548acc3bd358b48d1447535..3ae9f4b596327374c05b4c5cae7034ee250892a2 100644 --- a/server/djrandom/frontend/latency.py +++ b/server/djrandom/frontend/latency.py @@ -3,8 +3,8 @@ import time import pygooglechart -LATENCY_BUCKETS = [ - 1, 2, 5, +DEFAULT_BUCKETS = [ + 2, 5, 10, 20, 50, 100, 200, 500, ] @@ -12,9 +12,6 @@ LATENCY_BUCKETS = [ N_BUCKETS = len(LATENCY_BUCKETS) + 1 -def _build_buckets(): - return [0] * N_BUCKETS - def _percent(counts): tot = float(sum(counts)) return [(x, 100 * x / tot) for x in counts] @@ -22,10 +19,15 @@ def _percent(counts): class LatencyProfilerMiddleware(object): - def __init__(self, app, urls=[]): + def __init__(self, app, urls=None, buckets=None): self._app = app - self._urls = sorted(urls, key=lambda x: len(x), reverse=True) - self._buckets = collections.defaultdict(_build_buckets) + self._buckets = buckets or DEFAULT_BUCKETS + self._n_buckets = len(self._buckets) + 1 + self._urls = sorted(urls or [], + key=lambda x: len(x), reverse=True) + def _build_buckets(): + return [0] * self._n_buckets + self._data = collections.defaultdict(_build_buckets) def __call__(self, environ, start_response): start = time.time() @@ -41,12 +43,12 @@ class LatencyProfilerMiddleware(object): if url.startswith(url_prefix): url = url_prefix break - for bkt, threshold in enumerate(LATENCY_BUCKETS): + for bkt, threshold in enumerate(self._buckets): if elapsed_ms < threshold: break else: - bkt = len(LATENCY_BUCKETS) - self._buckets[url][bkt] += 1 + bkt = self._n_buckets - 1 + self._data[url][bkt] += 1 def handler(self, environ, start_response): headers = [('Content-type', 'text/html')] @@ -57,23 +59,36 @@ class LatencyProfilerMiddleware(object): '<html><head><title>Latency Breakdown</title>\n' '<style type="text/css">\n' 'body { background: white; font-family: sans-serif; }\n' + 'tbody td { text-align: left; padding-right: 10px; }\n' + 'thead th { font-weight: bold; text-align: left; color: white; ' + 'background-color: #666; }\n' + 'td.url { font-weight: bold; border-right: 1px solid #666; }\n' + 'tbody tr { border-bottom: 1px solid #ccc; }\n' '</style></head><body>\n' '<h3>Latency report by URL</h3>\n' - '<table><thead><tr>' + '<table cellspacing="0" cellpadding="0" border="0"><thead><tr>' '<th rowspan="2">URL</th>', - '<th colspan="%d">Latencies (ms)</th>' % N_BUCKETS, + '<th rowspan="2">Total</th>', + '<th colspan="%d">Latencies (ms)</th>' % self._n_buckets, + '<th rowspan="2"></th>', '</tr><tr>' ] - for ms in LATENCY_BUCKETS: + for ms in self._buckets: result.append('<th><%d</th>' % ms) result.append('<th>>%d</th>' % ms) result.append('</tr></thead><tbody>') - for url in sorted(self._buckets.keys()): - result.append('<tr><td class="url">%s</td>' % url) - for count, pct in _percent(self._buckets[url]): - result.append('<td>%d (%.3g%%)</td>' % (count, pct)) + for url in sorted(self._data.keys()): + values = self._data[url] + result.append('<tr><td class="url">%s</td><td>%d</td>' % ( + url, sum(values))) + chart = pygooglechart.SparkLineChart(80, 25) + chart.set_data(values) + for count, pct in _percent(values): + result.append('<td>%d (%.2g%%)</td>' % (count, pct)) + result.append('<td><img src="%s" width="80" height="25"></td>' % + chart.get_url()) result.append('</tr>') result.append('</tbody></table>')