Skip to content

Instantly share code, notes, and snippets.

@russellb
Created March 4, 2013 14:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save russellb/5082605 to your computer and use it in GitHub Desktop.
Save russellb/5082605 to your computer and use it in GitHub Desktop.
nova reviews in the last 6 months
$ date
Mon Mar 4 09:33:37 EST 2013
$ python stats.py -d 182
Reviews for the last 182 days in nova
+------------------------+---------+
| Reviewer | Reviews |
+------------------------+---------+
| vishvananda | 1281 |
| mikalstill | 1258 |
| klmitch | 1163 |
| sdague-b | 1126 |
| russellb | 1073 |
| danms | 591 |
| markmc | 569 |
| jogo | 447 |
| cerberus | 436 |
| jk0 | 415 |
| cbehrens | 403 |
| p-draigbrady | 321 |
| johannes.erdfelt | 308 |
| maurosr | 306 |
| yunmao | 298 |
| zulcss | 212 |
| alaski | 208 |
| dan-prince | 194 |
| dims-v | 189 |
| devananda | 176 |
| lifeless | 164 |
| berrange | 152 |
| dripton | 146 |
| belliott | 119 |
| cyeoh-0 | 114 |
| rkhardalian | 86 |
| rconradharris | 72 |
| treinish | 70 |
| tr3buchet | 70 |
| lauria | 65 |
| boris-42 | 65 |
| krtaylor | 51 |
| john-griffith | 48 |
| heut2008 | 48 |
| ttx | 44 |
| arata776 | 40 |
| jason-koelker | 37 |
| ndipanov | 35 |
| eglynn | 35 |
| wenjianhn | 34 |
| tmello | 34 |
| johngarbutt | 34 |
| garyk | 31 |
| amotoki | 30 |
| ivan-zhu | 27 |
| danwent | 25 |
| mestery | 23 |
| hzwangpan | 23 |
| bcwaldon | 22 |
| ewindisch | 21 |
| malini-k-bhandaru | 20 |
| gongysh | 19 |
| davewalker | 19 |
| 0x44 | 19 |
| alexpilotti | 18 |
| cboylan | 17 |
| msherborne+openstack | 16 |
| mordred | 16 |
| fungi | 16 |
| smoser | 15 |
| arosen | 14 |
| apevec | 14 |
| sorrison | 13 |
| locke105 | 12 |
| stanislaw-pitucha | 11 |
| nikhil-komawar | 11 |
| mathrock | 11 |
| mate-lakat | 11 |
| motokentsai | 10 |
| ijw-ubuntu | 10 |
| ethuleau | 10 |
| ekirpichov | 10 |
| nicolas.simonds | 9 |
| geekinutah | 9 |
| adalbas | 9 |
| sandy-walsh | 8 |
| philip-day | 8 |
| mdrnstm | 8 |
| harlowja | 7 |
| blk-u | 7 |
| aloga | 7 |
| rkukura | 6 |
| n0ano | 6 |
| mapleoin | 6 |
| ldbragst | 6 |
| iccha-sethi | 6 |
| drdanhe | 6 |
| dperaza | 6 |
| bfilippov | 6 |
| yehia-beyh | 5 |
| nobodycam | 5 |
| kiall | 5 |
| fifieldt | 5 |
| clay-gerrard | 5 |
| cfb-n | 5 |
| armando-migliaccio | 5 |
| zhiteng-huang | 4 |
| markmcclain | 4 |
| gtt116 | 4 |
| flaper87 | 4 |
| doug-hellmann | 4 |
| avishay-il | 4 |
| alex-meade | 4 |
| yuxcer | 3 |
| xing-yang | 3 |
| unicell | 3 |
| salvatore-orlando | 3 |
| rainya-mosher-m | 3 |
| oliver-leahy-l | 3 |
| nati-ueno | 3 |
| lzy-dev | 3 |
| luis-fernandez-alvarez | 3 |
| li9zheng | 3 |
| kurt-f-martin | 3 |
| jsuh | 3 |
| jdurgin | 3 |
| jdanjou | 3 |
| jaypipes | 3 |
| heckj | 3 |
| hanlind | 3 |
| cthiel-suse | 3 |
| bswartz | 3 |
| zyluo | 2 |
| zrzhit | 2 |
| zaneb | 2 |
| walter-boring | 2 |
| unknown | 2 |
| sirisha-devineni | 2 |
| otherwiseguy | 2 |
| markwash | 2 |
| ljjjustin | 2 |
| kravchenko-pavel | 2 |
| john-herndon | 2 |
| jiangwt100 | 2 |
| hzguanqiang | 2 |
| glikson | 2 |
| ghe.rivero | 2 |
| genggjh | 2 |
| gabriel-hurley | 2 |
| emagana | 2 |
| dricco | 2 |
| corystone | 2 |
| chmouel | 2 |
| brazie | 2 |
| berendt | 2 |
| andreslc | 2 |
| afazekas | 2 |
| zxkuqyb | 1 |
| yugsuo | 1 |
| yufang521247 | 1 |
| xychu2008 | 1 |
| xuhj | 1 |
| wenhao-x | 1 |
| unmesh-gurjar | 1 |
| tpatil | 1 |
| tom-gall | 1 |
| thomas-goirand | 1 |
| the-william-kelly | 1 |
| soren | 1 |
| snaiksat | 1 |
| shengjie-min | 1 |
| shardy | 1 |
| rushiagr | 1 |
| roytman | 1 |
| rohitkarajgi | 1 |
| pednape | 1 |
| parthipan | 1 |
| opencompute | 1 |
| oldsharp | 1 |
| niuwl586-v | 1 |
| mjfork | 1 |
| meizu647 | 1 |
| mdragon | 1 |
| matt-nycresistor | 1 |
| lianhao-lu | 1 |
| kirkland | 1 |
| jshepher | 1 |
| jokcylou | 1 |
| jfehlig | 1 |
| james-page | 1 |
| gessau | 1 |
| freedomhui | 1 |
| emilienm | 1 |
| eharney | 1 |
| ed-bak2 | 1 |
| duncan-thomas | 1 |
| dtroyer | 1 |
| dscannell | 1 |
| david-kranz | 1 |
| dave-mcnally | 1 |
| corvus | 1 |
| cmsj | 1 |
| changbl | 1 |
| cgoncalves | 1 |
| boris-fiuczynski | 1 |
| blamar | 1 |
| ayoung | 1 |
| annegentle | 1 |
| andrew-melton | 1 |
| amir-sadoughi | 1 |
| alexyang | 1 |
+------------------------+---------+
Total reviews: 13395
$ cat stats.py
#!/usr/bin/python
'''
Originally by Soren Hansen
Later hacked on by Russell Bryant
- support larger values for --days
- sort output
'''
import calendar
import datetime
import json
import optparse
import paramiko
from pprint import pprint
import prettytable
import sys
optparser = optparse.OptionParser()
optparser.add_option('-p', '--project', default='nova', help='Project to generate stats for')
optparser.add_option('-d', '--days', type='int', default=14, help='Number of days to consider')
optparser.add_option('-r', '--raw', action='store_true', default=False, help='Um... Hard to explain. Try it and see')
optparser.add_option('-u', '--user', default='russellb', help='gerrit user')
optparser.add_option('-k', '--key', default=None, help='ssh key for gerrit')
options, args = optparser.parse_args()
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.load_system_host_keys()
changes = []
while True:
client.connect('review.openstack.org', port=29418,
key_filename=options.key, username=options.user)
cmd = ('gerrit query project:openstack/%s '
'--all-approvals --patch-sets --format JSON' % options.project)
if len(changes) > 0:
cmd += ' resume_sortkey:%s' % changes[-2]['sortKey']
stdin, stdout, stderr = client.exec_command(cmd)
for l in stdout:
changes += [json.loads(l)]
if changes[-1]['rowCount'] == 0:
break
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]
if not options.raw:
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
reviewers = {}
for review in reviews:
reviewer = review['by'].get('username', 'unknown')
if options.raw:
if reviewer not in reviewers:
reviewers[reviewer] = {}
day = round_to_day(review['grantedOn'])
reviewers[reviewer][day] = reviewers[reviewer].get(day, 0) + 1
else:
reviewers[reviewer] = reviewers.get(reviewer, 0) + 1
#print json.dumps(reviewers, sort_keys=True, indent=4)
reviewers = [(v, k) for k, v in reviewers.iteritems()
if k.lower() not in ('jenkins', 'smokestack')]
reviewers.sort(reverse=True)
print 'Reviews for the last %d days in %s' % (options.days, options.project)
table = prettytable.PrettyTable(('Reviewer', 'Reviews'))
total = 0
for k, v in reviewers:
table.add_row((v, k))
total += k
print table
print '\nTotal reviews: %d' % total
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment