blob: 9554b9a1a291ded53cf3ff941b8e488f08d5cd6c [file] [log] [blame]
#!/usr/bin/env python
import argparse
from time import gmtime
import numpy
import requests
from spark import spark
import sys
def seconds_to_human(secs):
raw_minutes = secs / 60
raw_hours, minutes = divmod(raw_minutes, 60)
result_str = '%dm' % minutes
raw_days, hours = divmod(raw_hours, 24)
if hours or raw_days:
result_str = '%dh' % hours + result_str
weeks, days = divmod(raw_days, 7)
if days or weeks:
result_str = '%dd' % days + result_str
if weeks:
result_str = '%dw' % weeks + result_str
return result_str
def get_times(user, interval, server):
return requests.get(
'%s/user/%s/stats_json/%s' % (server, user, interval)).json()['latencies']
def get_args():
parser = argparse.ArgumentParser(
description='Obtain weekly/monthly review stats from Rietveld.')
parser.add_argument('user',
help='Email of the user to generate a report for. Ex: stip@chromium.org.')
parser.add_argument('interval',
type=int,
choices=[7, 30],
help='Time interval to generate a report for.')
parser.add_argument('--server',
default='https://codereview.chromium.org',
help='Rietveld instance to connect to. (default %(default)s).')
parser.add_argument('--bins',
default=20,
type=int,
help='Number of bins for the histogram. (default %(default)s).')
parser.add_argument('--annotate', action='store_true',
help='Annotate the histograms with median and 90th percentile.')
args = parser.parse_args()
return args
def find_bin(edges, n):
return numpy.searchsorted(edges, n) - 1
def print_hist(bins, edges, p50, p90, label='', annotate=False):
p50bin = find_bin(edges, p50)
p90bin = find_bin(edges, p90)
if annotate:
if p50bin == p90bin:
print '`' + ' ' * (p50bin - 1) + '*' + '`'
else:
print '`' + ' ' * (p50bin) + '5' + ' ' * (p90bin - p50bin - 1) + '9' + '`'
print '- `' + spark.spark_string(bins) + '`' + label
def gen_hist(times, numbins, pmin, pmax, logarithmic=False):
if logarithmic:
bins = 10 ** numpy.linspace(numpy.log10(pmin), numpy.log10(pmax), numbins)
else:
bins = numpy.linspace(0, pmax, numbins)
return numpy.histogram(times, bins=bins)
def main():
args = get_args()
times = get_times(args.user, args.interval, args.server)
reviewed_times = filter(lambda x: x > 0, times)
print ('%s day [review statistics](%s/user/%s/stats/%s) generated by '
'[go/stippets](https://goto.google.com/stippets):') % (
args.interval, args.server, args.user, args.interval)
print
received = len(times) / float(args.interval)
print '- Received: %.2f r/day' % received
reviewed = len(reviewed_times) / float(args.interval)
print '- Reviewed: %.2f r/day' % reviewed
if reviewed_times:
p50 = numpy.percentile(reviewed_times, 50)
p75 = numpy.percentile(reviewed_times, 75)
p90 = numpy.percentile(reviewed_times, 90)
pmin = min(reviewed_times)
pmax = max(reviewed_times)
print '- Median review latency: %s' % seconds_to_human(p50)
print '- 75th: %s 90th: %s Max: %s' % (
seconds_to_human(p75),
seconds_to_human(p90),
seconds_to_human(pmax))
bins, edges = gen_hist(
reviewed_times, args.bins, pmin, pmax)
print_hist(bins, edges, p50, p90, label=' (latency distribution, linear x)',
annotate=args.annotate)
log_bins, log_edges = gen_hist(
reviewed_times, args.bins, pmin, pmax, logarithmic=True)
print_hist(log_bins, log_edges, p50, p90,
label=' (latency distribution, log10 x)',
annotate=args.annotate)
if __name__ == '__main__':
sys.exit(main())