Skip to content

Instantly share code, notes, and snippets.

@smerritt
Created May 20, 2013 20:02
Show Gist options
  • Save smerritt/5615053 to your computer and use it in GitHub Desktop.
Save smerritt/5615053 to your computer and use it in GitHub Desktop.
OpenStack review stats. Started life as http://173.203.107.207/~soren/stats/stats.py.txt, then I went and hacked it up a bunch to do what I wanted.
#!/usr/bin/python
from collections import defaultdict
import calendar
import datetime
import json
import operator
import optparse
import paramiko
from pprint import pprint
from tabulate import tabulate
import sys
optparser = optparse.OptionParser()
optparser.add_option('-p', '--project', default='swift', help='Project to generate stats for')
optparser.add_option('-d', '--days', type='int', default=30, help='Number of days to consider')
optparser.add_option('-c', '--cutoff', type='int', default=1, metavar='N', help='Only show reviewers with at least N reviews')
options, args = optparser.parse_args()
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.load_system_host_keys()
client.connect('review.openstack.org', port=29418, key_filename='/Users/torgomatic/.ssh/id_rsa', username='torgomatic')
# allow for stackforge/X as well
if '/' not in options.project:
project = "openstack/" + options.project
else:
project = options.project
stdin, stdout, stderr = client.exec_command('gerrit query project:%s --all-approvals --patch-sets --format JSON' % project)
changes = []
for l in stdout:
changes += [json.loads(l)]
reviews = []
for change in changes:
#print json.dumps(change, sort_keys=True, indent=4)
for patchset in change.get('patchSets', []):
for review in patchset.get('approvals', []):
reviews += [review]
cut_off = datetime.datetime.now() - datetime.timedelta(days=options.days)
ts = calendar.timegm(cut_off.timetuple())
reviews = filter(lambda x:x['grantedOn'] > ts, reviews)
def round_to_day(ts):
SECONDS_PER_DAY = 60*60*24
return (ts / (SECONDS_PER_DAY)) * SECONDS_PER_DAY
scores_by_reviewer = defaultdict(lambda: defaultdict(int))
scores = defaultdict(int)
for review in reviews:
if review.get('type') != "CRVW":
continue
reviewer = review['by'].get('username', 'unknown')
score = int(review["value"])
scores_by_reviewer[reviewer][score] += 1
scores[score] += 1
table = []
total_reviews = 0
for reviewer, scores in scores_by_reviewer.iteritems():
total = sum(scores.values())
total_reviews += total
row = [reviewer,
total,
scores[-2],
scores[-1],
scores[1],
scores[2]]
grumpiness = float(sum((scores[-2], scores[-1]))) / total
row.append("%0.1f%%" % (grumpiness * 100))
table.append(row)
table.sort(key=operator.itemgetter(1), reverse=True)
print tabulate(table, ["Reviewer", "Total Reviews (%d)" % total_reviews, "-2", "-1", "1", "2", "Grumpiness"])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment