Subversion Repositories DevTools

Rev

Rev 4766 | Rev 4954 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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