| Line 1... |
Line 1... |
| 1 |
mport json, urllib2, sys, datetime
|
1 |
import json, urllib2, sys, datetime
|
| 2 |
|
2 |
|
| 3 |
CRUCIBLE_URL_TEMPLATE = 'http://cds:8060/rest-service/reviews-v1'
|
3 |
CRUCIBLE_URL_TEMPLATE = 'http://cds:8060/rest-service/reviews-v1'
|
| 4 |
RESULTS_KEY = u'results'
|
4 |
RESULTS_KEY = 'results'
|
| 5 |
GEOMETRY_KEY = u'geometry'
|
5 |
GEOMETRY_KEY = 'geometry'
|
| 6 |
LOCATION_KEY = u'location'
|
6 |
LOCATION_KEY = 'location'
|
| 7 |
LAT_KEY = u'lat'
|
7 |
LAT_KEY = 'lat'
|
| 8 |
LNG_KEY = u'lng'
|
8 |
LNG_KEY = 'lng'
|
| 9 |
|
9 |
|
| 10 |
|
10 |
|
| 11 |
class CrucibleExtractor :
|
11 |
class CrucibleExtractor :
|
| 12 |
def __init__(self) :
|
12 |
def __init__(self) :
|
| 13 |
pass
|
13 |
pass
|
| Line 27... |
Line 27... |
| 27 |
if top :
|
27 |
if top :
|
| 28 |
retval = retval[top]
|
28 |
retval = retval[top]
|
| 29 |
return retval
|
29 |
return retval
|
| 30 |
def get_selected_review_ids(self,min_create_date, max_create_date) :
|
30 |
def get_selected_review_ids(self,min_create_date, max_create_date) :
|
| 31 |
url = CRUCIBLE_URL_TEMPLATE
|
31 |
url = CRUCIBLE_URL_TEMPLATE
|
| 32 |
reviewData = self.url_to_object(url, "reviewData")
|
32 |
reviewData = self.url_to_object(url,"reviewData")
|
| - |
|
33 |
print(len(str(reviewData)))
|
| 33 |
for r in reviewData :
|
34 |
for r in reviewData :
|
| 34 |
review_id = r["permaId"]["id"]
|
35 |
review_id = r["permaId"]["id"]
|
| 35 |
review_create_date = r["createDate"]
|
36 |
review_create_date = r["createDate"]
|
| 36 |
if review_create_date>=min_create_date and review_create_date<=max_create_date :
|
37 |
if review_create_date>=min_create_date and review_create_date<=max_create_date :
|
| 37 |
self.selected_reviews[review_id] = [ r[u'projectKey'], None, ]
|
38 |
self.selected_reviews[review_id] = [ r['projectKey'], None, ]
|
| 38 |
else :
|
39 |
else :
|
| 39 |
pass
|
40 |
pass
|
| 40 |
return self.selected_reviews.keys()
|
41 |
return self.selected_reviews.keys()
|
| 41 |
def get_review_summary(self,review_id) :
|
42 |
def get_review_summary(self,review_id) :
|
| 42 |
url = CRUCIBLE_URL_TEMPLATE + "/" + review_id + "/comments"
|
43 |
url = CRUCIBLE_URL_TEMPLATE + "/" + review_id + "/comments"
|
| 43 |
projectKey = str(self.selected_reviews[review_id][0])
|
44 |
projectKey = str(self.selected_reviews[review_id][0])
|
| 44 |
reviewDetails = self.url_to_object(url,u'comments')
|
45 |
reviewDetails = self.url_to_object(url,'comments')
|
| 45 |
retval = [
|
46 |
retval = [
|
| 46 |
projectKey,
|
47 |
projectKey,
|
| 47 |
0, # non-defect comments
|
48 |
0, # non-defect comments
|
| 48 |
0, # runtime defects
|
49 |
0, # runtime defects
|
| 49 |
0, # maintenance defects
|
50 |
0, # maintenance defects
|
| 50 |
0, # security defects
|
51 |
0, # security defects
|
| 51 |
0, # unclassified defects
|
52 |
0, # unclassified defects
|
| 52 |
]
|
53 |
]
|
| 53 |
for c in reviewDetails:
|
54 |
for c in reviewDetails:
|
| 54 |
if c[u'defectRaised'] is False :
|
55 |
if c['defectRaised'] is False :
|
| 55 |
retval[1] += 1
|
56 |
retval[1] += 1
|
| 56 |
elif len(c[u'metrics'].keys()) != 1 : # unclassified - either none of the drop downs or more than one selected
|
57 |
elif len(c['metrics'].keys()) != 1 : # unclassified - either none of the drop downs or more than one selected
|
| 57 |
retval[5] += 1
|
58 |
retval[5] += 1
|
| 58 |
self.unclassified_defect_reviews += [ review_id ]
|
59 |
self.unclassified_defect_reviews += [ review_id ]
|
| 59 |
self.total_defects += 1
|
60 |
self.total_defects += 1
|
| 60 |
else :
|
61 |
else :
|
| 61 |
defect_category_code = c[u'metrics'].keys()[0]
|
62 |
defect_category_code = c['metrics'].keys()[0]
|
| 62 |
defect_type = c[u'metrics'][defect_category_code][u'value']
|
63 |
defect_type = c['metrics'][defect_category_code]['value']
|
| 63 |
category_defect_map = None
|
64 |
category_defect_map = None
|
| 64 |
if defect_category_code == u'metric-57' : # maintenance
|
65 |
if defect_category_code == 'metric-57' : # maintenance
|
| 65 |
retval[3] += 1
|
66 |
retval[3] += 1
|
| 66 |
category_defect_map = self.maintenance_defects
|
67 |
category_defect_map = self.maintenance_defects
|
| 67 |
elif defect_category_code == u'metric-95' : # runtime
|
68 |
elif defect_category_code == 'metric-95' : # runtime
|
| 68 |
retval[2] += 1
|
69 |
retval[2] += 1
|
| 69 |
category_defect_map = self.runtime_defects
|
70 |
category_defect_map = self.runtime_defects
|
| 70 |
elif defect_category_code == u'metric-97' : # security
|
71 |
elif defect_category_code == 'metric-97' : # security
|
| 71 |
retval[4] += 1
|
72 |
retval[4] += 1
|
| 72 |
category_defect_map = self.security_defects
|
73 |
category_defect_map = self.security_defects
|
| 73 |
else :
|
74 |
else :
|
| 74 |
print u"Unexpected defect_category_code %s" % ( c[u'metrics'].keys()[0] )
|
75 |
print("Unexpected defect_category_code %s" % ( c['metrics'].keys()[0], ))
|
| 75 |
retval[5] += 1
|
76 |
retval[5] += 1
|
| 76 |
self.unclassified_defect_reviews += [ review_id ]
|
77 |
self.unclassified_defect_reviews += [ review_id ]
|
| 77 |
self.total_defects += 1
|
78 |
self.total_defects += 1
|
| 78 |
if category_defect_map is None :
|
79 |
if category_defect_map is None :
|
| 79 |
pass
|
80 |
pass
|
| Line 86... |
Line 87... |
| 86 |
return retval
|
87 |
return retval
|
| 87 |
def summarize_by_project(self, month_prefix) :
|
88 |
def summarize_by_project(self, month_prefix) :
|
| 88 |
start_date = month_prefix + "-00"
|
89 |
start_date = month_prefix + "-00"
|
| 89 |
end_date = month_prefix + "-99"
|
90 |
end_date = month_prefix + "-99"
|
| 90 |
if self.verbose :
|
91 |
if self.verbose :
|
| 91 |
print "Getting review ids"
|
92 |
print("Getting review ids")
|
| 92 |
review_ids = self.get_selected_review_ids(start_date, end_date)
|
93 |
review_ids = self.get_selected_review_ids(start_date, end_date)
|
| 93 |
project_summaries = {}
|
94 |
project_summaries = {}
|
| 94 |
overall_summary = [ 0, ] * 6
|
95 |
overall_summary = [ 0, ] * 6
|
| 95 |
for review_id in sorted(review_ids) :
|
96 |
for review_id in sorted(review_ids) :
|
| 96 |
if True :
|
97 |
if True :
|
| 97 |
review_summary = self.get_review_summary(review_id)
|
98 |
review_summary = self.get_review_summary(review_id)
|
| 98 |
if self.verbose :
|
99 |
if self.verbose :
|
| 99 |
print "%-12s: %s" % ( review_id, self.selected_reviews[review_id][1] )
|
100 |
print("%-12s: %s" % ( review_id, self.selected_reviews[review_id][1], ))
|
| 100 |
project_id = review_summary[0]
|
101 |
project_id = review_summary[0]
|
| 101 |
if project_id in project_summaries.keys() :
|
102 |
if project_id in project_summaries.keys() :
|
| 102 |
project_summary = project_summaries[project_id]
|
103 |
project_summary = project_summaries[project_id]
|
| 103 |
else :
|
104 |
else :
|
| 104 |
project_summary = [ 0,] * 6
|
105 |
project_summary = [ 0,] * 6
|
| Line 108... |
Line 109... |
| 108 |
project_summary[i] += review_summary[i]
|
109 |
project_summary[i] += review_summary[i]
|
| 109 |
overall_summary[i] += review_summary[i]
|
110 |
overall_summary[i] += review_summary[i]
|
| 110 |
project_summaries[project_id] = project_summary
|
111 |
project_summaries[project_id] = project_summary
|
| 111 |
REPORT_PRINTF_FORMAT = "%-12s %4s %4s %4s %4s %4s %4s"
|
112 |
REPORT_PRINTF_FORMAT = "%-12s %4s %4s %4s %4s %4s %4s"
|
| 112 |
REPORT_FORMAT_SEPARATOR = ( '-------','---','---','---','---','---','---')
|
113 |
REPORT_FORMAT_SEPARATOR = ( '-------','---','---','---','---','---','---')
|
| 113 |
print REPORT_PRINTF_FORMAT % REPORT_FORMAT_SEPARATOR
|
114 |
print ( REPORT_PRINTF_FORMAT % REPORT_FORMAT_SEPARATOR )
|
| 114 |
print REPORT_PRINTF_FORMAT % ( "Project", "rev", "com", "run", "mnt", "sec", "oth" )
|
115 |
print ( REPORT_PRINTF_FORMAT % ( "Project", "rev", "com", "run", "mnt", "sec", "oth" ) )
|
| 115 |
print REPORT_PRINTF_FORMAT % REPORT_FORMAT_SEPARATOR
|
116 |
print ( REPORT_PRINTF_FORMAT % REPORT_FORMAT_SEPARATOR )
|
| 116 |
for project_id in sorted(project_summaries.keys()) :
|
117 |
for project_id in sorted(project_summaries.keys()) :
|
| 117 |
ps = project_summaries[project_id]
|
118 |
ps = project_summaries[project_id]
|
| 118 |
print REPORT_PRINTF_FORMAT % ( project_id, ps[0], ps[1], ps[2], ps[3], ps[4], ps[5] )
|
119 |
print ( REPORT_PRINTF_FORMAT % ( project_id, ps[0], ps[1], ps[2], ps[3], ps[4], ps[5] ) )
|
| 119 |
print REPORT_PRINTF_FORMAT % REPORT_FORMAT_SEPARATOR
|
120 |
print ( REPORT_PRINTF_FORMAT % REPORT_FORMAT_SEPARATOR )
|
| 120 |
ps = overall_summary
|
121 |
ps = overall_summary
|
| 121 |
print REPORT_PRINTF_FORMAT % ( "TOTAL", ps[0], ps[1], ps[2], ps[3], ps[4], ps[5] )
|
122 |
print ( REPORT_PRINTF_FORMAT % ( "TOTAL", ps[0], ps[1], ps[2], ps[3], ps[4], ps[5] ) )
|
| 122 |
def summarize_for_category(self,category_name, category_types) :
|
123 |
def summarize_for_category(self,category_name, category_types) :
|
| 123 |
REPORT_PRINTF_FORMAT = "%-75s %6s %6s"
|
124 |
REPORT_PRINTF_FORMAT = "%-75s %6s %6s"
|
| 124 |
REPORT_FORMAT_SEPARATOR = ( '-----------------------','------','------')
|
125 |
REPORT_FORMAT_SEPARATOR = ( '-----------------------','------','------')
|
| 125 |
print REPORT_PRINTF_FORMAT % REPORT_FORMAT_SEPARATOR
|
126 |
print ( REPORT_PRINTF_FORMAT % REPORT_FORMAT_SEPARATOR )
|
| 126 |
print REPORT_PRINTF_FORMAT % ( "%s defects" % (category_name),"count","%")
|
127 |
print ( REPORT_PRINTF_FORMAT % ( "%s defects" % (category_name),"count","%") )
|
| 127 |
print REPORT_PRINTF_FORMAT % REPORT_FORMAT_SEPARATOR
|
128 |
print ( REPORT_PRINTF_FORMAT % REPORT_FORMAT_SEPARATOR )
|
| 128 |
count_for_category = 0
|
129 |
count_for_category = 0
|
| 129 |
percent_for_category = 0.0
|
130 |
percent_for_category = 0.0
|
| 130 |
for d in sorted(category_types.keys()) :
|
131 |
for d in sorted(category_types.keys()) :
|
| 131 |
count_for_type = category_types[d]
|
132 |
count_for_type = category_types[d]
|
| 132 |
percent_for_type = int( (1000.0 * count_for_type)/self.total_defects) * 0.1
|
133 |
percent_for_type = int( (1000.0 * count_for_type)/self.total_defects) * 0.1
|
| 133 |
count_for_category += count_for_type
|
134 |
count_for_category += count_for_type
|
| 134 |
percent_for_category += percent_for_type
|
135 |
percent_for_category += percent_for_type
|
| 135 |
d = d.replace(u"\u2013",u"-")
|
136 |
d = d.replace("\u2013","-")
|
| 136 |
print REPORT_PRINTF_FORMAT % ( d, count_for_type, percent_for_type )
|
137 |
print ( REPORT_PRINTF_FORMAT % ( d, count_for_type, percent_for_type ) )
|
| 137 |
print REPORT_PRINTF_FORMAT % REPORT_FORMAT_SEPARATOR
|
138 |
print ( REPORT_PRINTF_FORMAT % REPORT_FORMAT_SEPARATOR )
|
| 138 |
print REPORT_PRINTF_FORMAT % ( "Total %s" % (category_name,), count_for_category, percent_for_category )
|
139 |
print ( REPORT_PRINTF_FORMAT % ( "Total %s" % (category_name,), count_for_category, percent_for_category ) )
|
| 139 |
print REPORT_PRINTF_FORMAT % REPORT_FORMAT_SEPARATOR
|
140 |
print ( REPORT_PRINTF_FORMAT % REPORT_FORMAT_SEPARATOR )
|
| 140 |
def summarize_by_defect_type(self) :
|
141 |
def summarize_by_defect_type(self) :
|
| 141 |
self.summarize_for_category("maintenance",self.maintenance_defects)
|
142 |
self.summarize_for_category("maintenance",self.maintenance_defects)
|
| 142 |
self.summarize_for_category("runtime",self.runtime_defects)
|
143 |
self.summarize_for_category("runtime",self.runtime_defects)
|
| 143 |
self.summarize_for_category("security",self.security_defects)
|
144 |
self.summarize_for_category("security",self.security_defects)
|
| 144 |
def report_on_unclassified_defects(self) :
|
145 |
def report_on_unclassified_defects(self) :
|
| 145 |
print "Reviews with unclassified defects: %s" % (self.unclassified_defect_reviews,)
|
146 |
print ( "Reviews with unclassified defects: %s" % (self.unclassified_defect_reviews,) )
|
| 146 |
|
147 |
|
| 147 |
if __name__ == "__main__" :
|
148 |
if __name__ == "__main__" :
|
| 148 |
extractor = CrucibleExtractor()
|
149 |
extractor = CrucibleExtractor()
|
| 149 |
|
150 |
|
| 150 |
if sys.argv[1] == "--usage" :
|
151 |
if sys.argv[1] == "--usage" :
|
| 151 |
print "crucible_reporting.py YYYY-MM"
|
152 |
print ( "crucible_reporting.py YYYY-MM" )
|
| 152 |
print " report stats for specified month"
|
153 |
print ( " report stats for specified month" )
|
| 153 |
print "crucible_reporting.py"
|
154 |
print ( "crucible_reporting.py" )
|
| 154 |
print " report stats for previous month"
|
155 |
print ( " report stats for previous month" )
|
| 155 |
sys.exit(0)
|
156 |
sys.exit(0)
|
| 156 |
elif sys.argv[1] == "--verbose" :
|
157 |
elif sys.argv[1] == "--verbose" :
|
| 157 |
extractor.verbose = True
|
158 |
extractor.verbose = True
|
| 158 |
sys.argv = sys.argv[1:]
|
159 |
sys.argv = sys.argv[1:]
|
| 159 |
|
160 |
|
| Line 161... |
Line 162... |
| 161 |
today = datetime.date.today()
|
162 |
today = datetime.date.today()
|
| 162 |
if today.month!= 1 :
|
163 |
if today.month!= 1 :
|
| 163 |
month_prefix = "%04d-%02d" % (today.year, today.month-1)
|
164 |
month_prefix = "%04d-%02d" % (today.year, today.month-1)
|
| 164 |
else :
|
165 |
else :
|
| 165 |
month_prefix = "%04d-%02d" % (today.year-1, 12)
|
166 |
month_prefix = "%04d-%02d" % (today.year-1, 12)
|
| 166 |
print "Generating report for previous month (" + month_prefix + ")"
|
167 |
print ( "Generating report for previous month (" + month_prefix + ")" )
|
| 167 |
else :
|
168 |
else :
|
| 168 |
month_prefix = sys.argv[1]
|
169 |
month_prefix = sys.argv[1]
|
| 169 |
|
170 |
|
| 170 |
extractor.summarize_by_project(month_prefix)
|
171 |
extractor.summarize_by_project(month_prefix)
|
| 171 |
extractor.summarize_by_defect_type()
|
172 |
extractor.summarize_by_defect_type()
|