OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Script to parse perf data from Chrome Endure test executions, to be graphed. | 6 """Script to parse perf data from Chrome Endure test executions, to be graphed. |
7 | 7 |
8 This script connects via HTTP to a buildbot master in order to scrape and parse | 8 This script connects via HTTP to a buildbot master in order to scrape and parse |
9 perf data from Chrome Endure tests that have been run. The perf data is then | 9 perf data from Chrome Endure tests that have been run. The perf data is then |
10 stored in local text files to be graphed by the Chrome Endure graphing code. | 10 stored in local text files to be graphed by the Chrome Endure graphing code. |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 elif int(line_dict['rev']) < int(revision): | 105 elif int(line_dict['rev']) < int(revision): |
106 break | 106 break |
107 if not overwritten: | 107 if not overwritten: |
108 existing_lines.insert(0, simplejson.dumps(new_line)) | 108 existing_lines.insert(0, simplejson.dumps(new_line)) |
109 | 109 |
110 with open(data_file, 'w') as f: | 110 with open(data_file, 'w') as f: |
111 f.write('\n'.join(existing_lines)) | 111 f.write('\n'.join(existing_lines)) |
112 os.chmod(data_file, 0755) | 112 os.chmod(data_file, 0755) |
113 | 113 |
114 | 114 |
115 def OutputPerfData(revision, graph_name, description, value, units, units_x, | 115 def OutputPerfData(revision, graph_name, values, units, units_x, dest_dir): |
116 dest_dir): | |
117 """Outputs perf data to a local text file to be graphed. | 116 """Outputs perf data to a local text file to be graphed. |
118 | 117 |
119 Args: | 118 Args: |
120 revision: The string revision number associated with the perf data. | 119 revision: The string revision number associated with the perf data. |
121 graph_name: The string name of the graph on which to plot the data. | 120 graph_name: The string name of the graph on which to plot the data. |
122 description: A string description of the perf value to be graphed. | 121 values: A dict which maps a description to a value. A value is either a |
123 value: Either a single data value to be graphed, or a list of 2-tuples | 122 single data value to be graphed, or a list of 2-tuples |
124 representing (x, y) points to be graphed for long-running tests. | 123 representing (x, y) points to be graphed for long-running tests. |
125 units: The string description for the y-axis units on the graph. | 124 units: The string description for the y-axis units on the graph. |
126 units_x: The string description for the x-axis units on the graph. Should | 125 units_x: The string description for the x-axis units on the graph. Should |
127 be set to None if the results are not for long-running graphs. | 126 be set to None if the results are not for long-running graphs. |
128 dest_dir: The name of the destination directory to which to write. | 127 dest_dir: The name of the destination directory to which to write. |
129 """ | 128 """ |
130 # Update graphs.dat, which contains metadata associated with each graph. | 129 # Update graphs.dat, which contains metadata associated with each graph. |
131 existing_graphs = [] | 130 existing_graphs = [] |
132 graphs_file = os.path.join(dest_dir, 'graphs.dat') | 131 graphs_file = os.path.join(dest_dir, 'graphs.dat') |
133 if os.path.exists(graphs_file): | 132 if os.path.exists(graphs_file): |
(...skipping 19 matching lines...) Expand all Loading... |
153 os.chmod(graphs_file, 0755) | 152 os.chmod(graphs_file, 0755) |
154 | 153 |
155 # Update summary data file, containing the actual data to be graphed. | 154 # Update summary data file, containing the actual data to be graphed. |
156 data_file_name = graph_name + '-summary.dat' | 155 data_file_name = graph_name + '-summary.dat' |
157 existing_lines = [] | 156 existing_lines = [] |
158 data_file = os.path.join(dest_dir, data_file_name) | 157 data_file = os.path.join(dest_dir, data_file_name) |
159 if os.path.exists(data_file): | 158 if os.path.exists(data_file): |
160 with open(data_file, 'r') as f: | 159 with open(data_file, 'r') as f: |
161 existing_lines = f.readlines() | 160 existing_lines = f.readlines() |
162 existing_lines = map(lambda x: x.strip(), existing_lines) | 161 existing_lines = map(lambda x: x.strip(), existing_lines) |
163 if units_x: | 162 new_traces = {} |
164 points = [] | 163 for description in values: |
165 for point in value: | 164 value = values[description] |
166 points.append([str(point[0]), str(point[1])]) | 165 if units_x: |
167 new_traces = { | 166 points = [] |
168 description: points | 167 for point in value: |
169 } | 168 points.append([str(point[0]), str(point[1])]) |
170 else: | 169 new_traces[description] = points |
171 new_traces = { | 170 else: |
172 description: [str(value), str(0.0)] | 171 new_traces[description] = [str(value), str(0.0)] |
173 } | |
174 new_line = { | 172 new_line = { |
175 'traces': new_traces, | 173 'traces': new_traces, |
176 'rev': revision | 174 'rev': revision |
177 } | 175 } |
178 | 176 |
179 WriteToDataFile(new_line, existing_lines, revision, data_file) | 177 WriteToDataFile(new_line, existing_lines, revision, data_file) |
180 | 178 |
181 | 179 |
182 def OutputEventData(revision, description, event_list, dest_dir): | 180 def OutputEventData(revision, event_dict, dest_dir): |
183 """Outputs event data to a local text file to be graphed. | 181 """Outputs event data to a local text file to be graphed. |
184 | 182 |
185 Args: | 183 Args: |
186 revision: The string revision number associated with the event data. | 184 revision: The string revision number associated with the event data. |
187 description: A string description of the event values to be graphed. | 185 event_dict: A dict which maps a description to an array of tuples |
188 event_list: An array of tuples representing event data to be graphed. | 186 representing event data to be graphed. |
189 dest_dir: The name of the destination directory to which to write. | 187 dest_dir: The name of the destination directory to which to write. |
190 """ | 188 """ |
191 data_file_name = '_EVENT_-summary.dat' | 189 data_file_name = '_EVENT_-summary.dat' |
192 existing_lines = [] | 190 existing_lines = [] |
193 data_file = os.path.join(dest_dir, data_file_name) | 191 data_file = os.path.join(dest_dir, data_file_name) |
194 if os.path.exists(data_file): | 192 if os.path.exists(data_file): |
195 with open(data_file, 'r') as f: | 193 with open(data_file, 'r') as f: |
196 existing_lines = f.readlines() | 194 existing_lines = f.readlines() |
197 existing_lines = map(lambda x: x.strip(), existing_lines) | 195 existing_lines = map(lambda x: x.strip(), existing_lines) |
198 | 196 |
199 value_list = [] | 197 new_events = {} |
200 for event_time, event_data in event_list: | 198 for description in event_dict: |
201 value_list.append([str(event_time), event_data]) | 199 event_list = event_dict[description] |
202 new_events = { | 200 value_list = [] |
203 description: value_list | 201 for event_time, event_data in event_list: |
204 } | 202 value_list.append([str(event_time), event_data]) |
| 203 new_events[description] = value_list |
205 | 204 |
206 new_line = { | 205 new_line = { |
207 'rev': revision, | 206 'rev': revision, |
208 'events': new_events | 207 'events': new_events |
209 } | 208 } |
210 | 209 |
211 WriteToDataFile(new_line, existing_lines, revision, data_file) | 210 WriteToDataFile(new_line, existing_lines, revision, data_file) |
212 | 211 |
213 | 212 |
214 def UpdatePerfDataForSlaveAndBuild(slave_info, build_num): | 213 def UpdatePerfDataForSlaveAndBuild(slave_info, build_num): |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 AppendRawPerfData('_EVENT_', match[0], eval(match[1]), None, None, | 331 AppendRawPerfData('_EVENT_', match[0], eval(match[1]), None, None, |
333 stdio_url_data['webapp_name'], | 332 stdio_url_data['webapp_name'], |
334 stdio_url_data['test_name']) | 333 stdio_url_data['test_name']) |
335 | 334 |
336 # For each graph_name/description pair that refers to a long-running test | 335 # For each graph_name/description pair that refers to a long-running test |
337 # result or an event, concatenate all the results together (assume results | 336 # result or an event, concatenate all the results together (assume results |
338 # in the input file are in the correct order). For short-running test | 337 # in the input file are in the correct order). For short-running test |
339 # results, keep just one if more than one is specified. | 338 # results, keep just one if more than one is specified. |
340 perf_data = {} # Maps a graph-line key to a perf data dictionary. | 339 perf_data = {} # Maps a graph-line key to a perf data dictionary. |
341 for data in perf_data_raw: | 340 for data in perf_data_raw: |
342 key = data['graph_name'] + '|' + data['description'] | 341 key_graph = data['graph_name'] |
| 342 key_description = data['description'] |
| 343 if not key_graph in perf_data: |
| 344 perf_data[key_graph] = { |
| 345 'graph_name': data['graph_name'], |
| 346 'value': {}, |
| 347 'units': data['units'], |
| 348 'units_x': data['units_x'], |
| 349 'webapp_name': data['webapp_name'], |
| 350 'test_name': data['test_name'], |
| 351 } |
343 if data['graph_name'] != '_EVENT_' and not data['units_x']: | 352 if data['graph_name'] != '_EVENT_' and not data['units_x']: |
344 # Short-running test result. | 353 # Short-running test result. |
345 perf_data[key] = data | 354 perf_data[key_graph]['value'][key_description] = data['value'] |
346 else: | 355 else: |
347 # Long-running test result or event. | 356 # Long-running test result or event. |
348 if key in perf_data: | 357 if key_description in perf_data[key_graph]['value']: |
349 perf_data[key]['value'] += data['value'] | 358 perf_data[key_graph]['value'][key_description] += data['value'] |
350 else: | 359 else: |
351 perf_data[key] = data | 360 perf_data[key_graph]['value'][key_description] = data['value'] |
352 | 361 |
353 # Finally, for each graph-line in |perf_data|, update the associated local | 362 # Finally, for each graph-line in |perf_data|, update the associated local |
354 # graph data files if necessary. | 363 # graph data files if necessary. |
355 for perf_data_key in perf_data: | 364 for perf_data_key in perf_data: |
356 perf_data_dict = perf_data[perf_data_key] | 365 perf_data_dict = perf_data[perf_data_key] |
357 | 366 |
358 dest_dir = os.path.join(LOCAL_GRAPH_DIR, perf_data_dict['webapp_name']) | 367 dest_dir = os.path.join(LOCAL_GRAPH_DIR, perf_data_dict['webapp_name']) |
359 if not os.path.exists(dest_dir): | 368 if not os.path.exists(dest_dir): |
360 os.mkdir(dest_dir) # Webapp name directory. | 369 os.mkdir(dest_dir) # Webapp name directory. |
361 os.chmod(dest_dir, 0755) | 370 os.chmod(dest_dir, 0755) |
362 dest_dir = os.path.join(dest_dir, perf_data_dict['test_name']) | 371 dest_dir = os.path.join(dest_dir, perf_data_dict['test_name']) |
363 | 372 |
364 SetupBaseGraphDirIfNeeded(perf_data_dict['webapp_name'], | 373 SetupBaseGraphDirIfNeeded(perf_data_dict['webapp_name'], |
365 perf_data_dict['test_name'], dest_dir) | 374 perf_data_dict['test_name'], dest_dir) |
366 if perf_data_dict['graph_name'] == '_EVENT_': | 375 if perf_data_dict['graph_name'] == '_EVENT_': |
367 OutputEventData(revision, perf_data_dict['description'], | 376 OutputEventData(revision, perf_data_dict['value'], dest_dir) |
368 perf_data_dict['value'], dest_dir) | |
369 else: | 377 else: |
370 OutputPerfData(revision, perf_data_dict['graph_name'], | 378 OutputPerfData(revision, perf_data_dict['graph_name'], |
371 perf_data_dict['description'], perf_data_dict['value'], | 379 perf_data_dict['value'], |
372 perf_data_dict['units'], perf_data_dict['units_x'], | 380 perf_data_dict['units'], perf_data_dict['units_x'], |
373 dest_dir) | 381 dest_dir) |
374 | 382 |
375 return True | 383 return True |
376 | 384 |
377 | 385 |
378 def UpdatePerfDataFiles(): | 386 def UpdatePerfDataFiles(): |
379 """Updates the Chrome Endure graph data files with the latest test results. | 387 """Updates the Chrome Endure graph data files with the latest test results. |
380 | 388 |
381 For each known Chrome Endure slave, we scan its latest test results looking | 389 For each known Chrome Endure slave, we scan its latest test results looking |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 if not success: | 595 if not success: |
588 logging.error('Failed to update perf data files.') | 596 logging.error('Failed to update perf data files.') |
589 sys.exit(0) | 597 sys.exit(0) |
590 | 598 |
591 GenerateIndexPage() | 599 GenerateIndexPage() |
592 logging.debug('All done!') | 600 logging.debug('All done!') |
593 | 601 |
594 | 602 |
595 if __name__ == '__main__': | 603 if __name__ == '__main__': |
596 main() | 604 main() |
OLD | NEW |