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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
111 elif int(line_dict['rev']) < int(revision): | 111 elif int(line_dict['rev']) < int(revision): |
112 break | 112 break |
113 if not overwritten: | 113 if not overwritten: |
114 existing_lines.insert(0, simplejson.dumps(new_line)) | 114 existing_lines.insert(0, simplejson.dumps(new_line)) |
115 | 115 |
116 with open(data_file, 'w') as f: | 116 with open(data_file, 'w') as f: |
117 f.write('\n'.join(existing_lines)) | 117 f.write('\n'.join(existing_lines)) |
118 os.chmod(data_file, 0755) | 118 os.chmod(data_file, 0755) |
119 | 119 |
120 | 120 |
121 def OutputPerfData(revision, graph_name, description, value, units, units_x, | 121 def OutputPerfData(revision, graph_name, values, units, units_x, dest_dir): |
122 dest_dir): | |
123 """Outputs perf data to a local text file to be graphed. | 122 """Outputs perf data to a local text file to be graphed. |
124 | 123 |
125 Args: | 124 Args: |
126 revision: The string revision number associated with the perf data. | 125 revision: The string revision number associated with the perf data. |
127 graph_name: The string name of the graph on which to plot the data. | 126 graph_name: The string name of the graph on which to plot the data. |
128 description: A string description of the perf value to be graphed. | 127 values: A dict which maps a description to a value. A value is either a |
129 value: Either a single data value to be graphed, or a list of 2-tuples | 128 single data value to be graphed, or a list of 2-tuples |
130 representing (x, y) points to be graphed for long-running tests. | 129 representing (x, y) points to be graphed for long-running tests. |
131 units: The string description for the y-axis units on the graph. | 130 units: The string description for the y-axis units on the graph. |
132 units_x: The string description for the x-axis units on the graph. Should | 131 units_x: The string description for the x-axis units on the graph. Should |
133 be set to None if the results are not for long-running graphs. | 132 be set to None if the results are not for long-running graphs. |
134 dest_dir: The name of the destination directory to which to write. | 133 dest_dir: The name of the destination directory to which to write. |
135 """ | 134 """ |
136 # Update graphs.dat, which contains metadata associated with each graph. | 135 # Update graphs.dat, which contains metadata associated with each graph. |
137 existing_graphs = [] | 136 existing_graphs = [] |
138 graphs_file = os.path.join(dest_dir, 'graphs.dat') | 137 graphs_file = os.path.join(dest_dir, 'graphs.dat') |
139 if os.path.exists(graphs_file): | 138 if os.path.exists(graphs_file): |
(...skipping 19 matching lines...) Expand all Loading... | |
159 os.chmod(graphs_file, 0755) | 158 os.chmod(graphs_file, 0755) |
160 | 159 |
161 # Update summary data file, containing the actual data to be graphed. | 160 # Update summary data file, containing the actual data to be graphed. |
162 data_file_name = graph_name + '-summary.dat' | 161 data_file_name = graph_name + '-summary.dat' |
163 existing_lines = [] | 162 existing_lines = [] |
164 data_file = os.path.join(dest_dir, data_file_name) | 163 data_file = os.path.join(dest_dir, data_file_name) |
165 if os.path.exists(data_file): | 164 if os.path.exists(data_file): |
166 with open(data_file, 'r') as f: | 165 with open(data_file, 'r') as f: |
167 existing_lines = f.readlines() | 166 existing_lines = f.readlines() |
168 existing_lines = map(lambda x: x.strip(), existing_lines) | 167 existing_lines = map(lambda x: x.strip(), existing_lines) |
169 if units_x: | 168 new_traces = {} |
170 points = [] | 169 for description in values: |
171 for point in value: | 170 value = values[description] |
172 points.append([str(point[0]), str(point[1])]) | 171 if units_x: |
173 new_traces = { | 172 points = [] |
174 description: points | 173 for point in value: |
175 } | 174 points.append([str(point[0]), str(point[1])]) |
176 else: | 175 new_traces[description] = points |
177 new_traces = { | 176 else: |
178 description: [str(value), str(0.0)] | 177 new_traces[description] = [str(value), str(0.0)] |
179 } | |
180 new_line = { | 178 new_line = { |
181 'traces': new_traces, | 179 'traces': new_traces, |
182 'rev': revision | 180 'rev': revision |
183 } | 181 } |
184 | 182 |
185 WriteToDataFile(new_line, existing_lines, revision, data_file) | 183 WriteToDataFile(new_line, existing_lines, revision, data_file) |
186 | 184 |
187 | 185 |
188 def OutputEventData(revision, description, event_list, dest_dir): | 186 def OutputEventData(revision, event_dict, dest_dir): |
189 """Outputs event data to a local text file to be graphed. | 187 """Outputs event data to a local text file to be graphed. |
190 | 188 |
191 Args: | 189 Args: |
192 revision: The string revision number associated with the event data. | 190 revision: The string revision number associated with the event data. |
193 description: A string description of the event values to be graphed. | 191 event_dict: A dict which maps a description to an array of tuples |
194 event_list: An array of tuples representing event data to be graphed. | 192 representing event data to be graphed. |
195 dest_dir: The name of the destination directory to which to write. | 193 dest_dir: The name of the destination directory to which to write. |
196 """ | 194 """ |
197 data_file_name = '_EVENT_-summary.dat' | 195 data_file_name = '_EVENT_-summary.dat' |
198 existing_lines = [] | 196 existing_lines = [] |
199 data_file = os.path.join(dest_dir, data_file_name) | 197 data_file = os.path.join(dest_dir, data_file_name) |
200 if os.path.exists(data_file): | 198 if os.path.exists(data_file): |
201 with open(data_file, 'r') as f: | 199 with open(data_file, 'r') as f: |
202 existing_lines = f.readlines() | 200 existing_lines = f.readlines() |
203 existing_lines = map(lambda x: x.strip(), existing_lines) | 201 existing_lines = map(lambda x: x.strip(), existing_lines) |
204 | 202 |
205 value_list = [] | 203 new_events = {} |
206 for event_time, event_data in event_list: | 204 for description in event_dict: |
207 value_list.append([str(event_time), event_data]) | 205 event_list = event_dict[description] |
208 new_events = { | 206 value_list = [] |
209 description: value_list | 207 for event_time, event_data in event_list: |
210 } | 208 value_list.append([str(event_time), event_data]) |
209 new_events[description] = value_list | |
211 | 210 |
212 new_line = { | 211 new_line = { |
213 'rev': revision, | 212 'rev': revision, |
214 'events': new_events | 213 'events': new_events |
215 } | 214 } |
216 | 215 |
217 WriteToDataFile(new_line, existing_lines, revision, data_file) | 216 WriteToDataFile(new_line, existing_lines, revision, data_file) |
218 | 217 |
219 | 218 |
220 def UpdatePerfDataForSlaveAndBuild(slave_info, build_num): | 219 def UpdatePerfDataForSlaveAndBuild(slave_info, build_num): |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
338 AppendRawPerfData('_EVENT_', match[0], eval(match[1]), None, None, | 337 AppendRawPerfData('_EVENT_', match[0], eval(match[1]), None, None, |
339 stdio_url_data['webapp_name'], | 338 stdio_url_data['webapp_name'], |
340 stdio_url_data['test_name']) | 339 stdio_url_data['test_name']) |
341 | 340 |
342 # For each graph_name/description pair that refers to a long-running test | 341 # For each graph_name/description pair that refers to a long-running test |
343 # result or an event, concatenate all the results together (assume results | 342 # result or an event, concatenate all the results together (assume results |
344 # in the input file are in the correct order). For short-running test | 343 # in the input file are in the correct order). For short-running test |
345 # results, keep just one if more than one is specified. | 344 # results, keep just one if more than one is specified. |
346 perf_data = {} # Maps a graph-line key to a perf data dictionary. | 345 perf_data = {} # Maps a graph-line key to a perf data dictionary. |
347 for data in perf_data_raw: | 346 for data in perf_data_raw: |
348 key = data['graph_name'] + '|' + data['description'] | 347 key1 = data['graph_name'] |
dennis_jeffrey
2012/09/26 00:34:29
use a more descriptive variable name, such as "key
Dai Mikurube (NOT FULLTIME)
2012/09/26 02:44:51
Done.
| |
348 key2 = data['description'] | |
dennis_jeffrey
2012/09/26 00:34:29
use a more descriptive variable name, such as "key
Dai Mikurube (NOT FULLTIME)
2012/09/26 02:44:51
Done.
| |
349 if not key1 in perf_data: | |
350 perf_data[key1] = { | |
351 'graph_name': data['graph_name'], | |
352 'value': {}, | |
353 'units': data['units'], | |
354 'units_x': data['units_x'], | |
355 'webapp_name': data['webapp_name'], | |
356 'test_name': data['test_name'], | |
357 } | |
349 if data['graph_name'] != '_EVENT_' and not data['units_x']: | 358 if data['graph_name'] != '_EVENT_' and not data['units_x']: |
350 # Short-running test result. | 359 # Short-running test result. |
351 perf_data[key] = data | 360 perf_data[key1]['value'][key2] = data['value'] |
352 else: | 361 else: |
353 # Long-running test result or event. | 362 # Long-running test result or event. |
354 if key in perf_data: | 363 if key2 in perf_data[key1]['value']: |
355 perf_data[key]['value'] += data['value'] | 364 perf_data[key1]['value'][key2] += data['value'] |
356 else: | 365 else: |
357 perf_data[key] = data | 366 perf_data[key1]['value'][key2] = data['value'] |
358 | 367 |
359 # Finally, for each graph-line in |perf_data|, update the associated local | 368 # Finally, for each graph-line in |perf_data|, update the associated local |
360 # graph data files if necessary. | 369 # graph data files if necessary. |
361 for perf_data_key in perf_data: | 370 for perf_data_key in perf_data: |
362 perf_data_dict = perf_data[perf_data_key] | 371 perf_data_dict = perf_data[perf_data_key] |
363 | 372 |
364 dest_dir = os.path.join(LOCAL_GRAPH_DIR, perf_data_dict['webapp_name']) | 373 dest_dir = os.path.join(LOCAL_GRAPH_DIR, perf_data_dict['webapp_name']) |
365 if not os.path.exists(dest_dir): | 374 if not os.path.exists(dest_dir): |
366 os.mkdir(dest_dir) # Webapp name directory. | 375 os.mkdir(dest_dir) # Webapp name directory. |
367 os.chmod(dest_dir, 0755) | 376 os.chmod(dest_dir, 0755) |
368 dest_dir = os.path.join(dest_dir, perf_data_dict['test_name']) | 377 dest_dir = os.path.join(dest_dir, perf_data_dict['test_name']) |
369 | 378 |
370 SetupBaseGraphDirIfNeeded(perf_data_dict['webapp_name'], | 379 SetupBaseGraphDirIfNeeded(perf_data_dict['webapp_name'], |
371 perf_data_dict['test_name'], dest_dir) | 380 perf_data_dict['test_name'], dest_dir) |
372 if perf_data_dict['graph_name'] == '_EVENT_': | 381 if perf_data_dict['graph_name'] == '_EVENT_': |
373 OutputEventData(revision, perf_data_dict['description'], | 382 OutputEventData(revision, perf_data_dict['value'], dest_dir) |
374 perf_data_dict['value'], dest_dir) | |
375 else: | 383 else: |
376 OutputPerfData(revision, perf_data_dict['graph_name'], | 384 OutputPerfData(revision, perf_data_dict['graph_name'], |
377 perf_data_dict['description'], perf_data_dict['value'], | 385 perf_data_dict['value'], |
378 perf_data_dict['units'], perf_data_dict['units_x'], | 386 perf_data_dict['units'], perf_data_dict['units_x'], |
379 dest_dir) | 387 dest_dir) |
380 | 388 |
381 return True | 389 return True |
382 | 390 |
383 | 391 |
384 def UpdatePerfDataFiles(): | 392 def UpdatePerfDataFiles(): |
385 """Updates the Chrome Endure graph data files with the latest test results. | 393 """Updates the Chrome Endure graph data files with the latest test results. |
386 | 394 |
387 For each known Chrome Endure slave, we scan its latest test results looking | 395 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... | |
593 if not success: | 601 if not success: |
594 logging.error('Failed to update perf data files.') | 602 logging.error('Failed to update perf data files.') |
595 sys.exit(0) | 603 sys.exit(0) |
596 | 604 |
597 GenerateIndexPage() | 605 GenerateIndexPage() |
598 logging.debug('All done!') | 606 logging.debug('All done!') |
599 | 607 |
600 | 608 |
601 if __name__ == '__main__': | 609 if __name__ == '__main__': |
602 main() | 610 main() |
OLD | NEW |