Chromium Code Reviews| Index: frontend/croschart/models.py |
| diff --git a/frontend/croschart/models.py b/frontend/croschart/models.py |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..a02412013b3885ade4613d5cd84bf1b1643f56d0 |
| --- /dev/null |
| +++ b/frontend/croschart/models.py |
| @@ -0,0 +1,95 @@ |
| +# Copyright (c) 2011 The Chromium OS Authors. All rights reserved. |
| +# Use of this source code is governed by a BSD-style license that can be |
| +# found in the LICENSE file. |
| + |
| + |
| +import logging |
| +import os |
| +import re |
| + |
| +from autotest_lib.frontend.afe import readonly_connection |
| + |
| + |
| +def AbbreviateBuild(build_pattern, build): |
| + m = re.match(build_pattern, build) |
| + if not m: |
| + logging.warning('Skipping poorly formatted build: %s.', build) |
| + return build |
| + new_build = '%s...%s' % (m.group(1), m.group(3)) |
|
ericli
2011/04/13 22:07:47
I think we agreed to s/.../- ?
truty
2011/04/14 19:01:51
Done.
|
| + return new_build |
| + |
| + |
| +def AggregateBuilds(test_key, data_list): |
| + build_dict = {} |
| + build_order = [] |
| + job_tags = [] |
| + build_pattern = re.compile( |
|
ericli
2011/04/13 22:07:47
promote this to a CONST str, and you can save one
truty
2011/04/14 19:01:51
Done.
|
| + '[\w]*\-[\w]*\-r[\w]*\-' |
| + '([\d]*\.[\d]*\.[\d]*\.[\d]*)-(r[\w]{8})-(b[\d]*)') |
| + for build, tag, value in data_list: |
| + build = AbbreviateBuild(build_pattern, build) |
| + if not build in build_dict: |
| + build_order.append(build) |
| + job_tags.append(tag) |
| + build_dict.setdefault(build, []).append(value) |
| + gviz_build_data = [] |
| + for build in build_order: |
| + value_list = build_dict[build] |
| + gviz_build_data.append({ |
| + 'build': build, |
| + test_key: round(sum(value_list, 0.0) / len(value_list), 2)}) |
| + return gviz_build_data, job_tags |
| + |
| + |
| +def GetChartData(boards, netbook, from_build, to_build, test_name, test_key): |
| + cursor = readonly_connection.connection().cursor() |
| + |
| + # Common query template that gets re-used. |
| + platform = 'netbook_%s' % netbook |
| + common_query = [ |
| + "SELECT %s", |
| + "FROM tko_perf_view_2", |
| + "WHERE job_name REGEXP %s", |
| + " AND platform = '%s'" % platform, |
| + " AND test_name = '%s'" % test_name, |
| + " AND iteration_key = '%s'" % test_key, |
| + " AND job_owner = 'chromeos-test'", |
| + " AND NOT ISNULL(iteration_value)", |
| + " AND iteration_value >= 0.0", |
| + " AND NOT ISNULL(test_started_time)", |
| + " AND NOT ISNULL(test_finished_time)", |
| + " AND NOT ISNULL(job_finished_time)"] |
| + common_job_name = "'(%s).*'" |
| + |
| + # Query notes: |
| + # 1. Getting the job_name to be able to aggregate different jobs that run |
| + # the same test on the same build. |
| + # 2. Getting every data point to be able to discard outliers. |
| + # 3. Default order of date. |
| + # 4. Uses subqueries to find bracketing dates mapping version to job_names. |
| + if from_build: |
| + job_name = common_job_name % '|'.join( |
| + '%s-%s' % (b, from_build.replace('.', '\.')) for b in boards.split('&')) |
| + min_query = ' '.join(common_query) % ( |
| + 'IFNULL(MIN(test_started_time), DATE_SUB(NOW(), INTERVAL 1 DAY))', |
| + job_name) |
| + else: |
| + min_query = 'SELECT DATE_SUB(NOW(), INTERVAL 2 WEEK)' |
| + |
| + if to_build: |
| + job_name = common_job_name % '|'.join( |
| + '%s-%s' % (b, to_build.replace('.', '\.')) for b in boards.split('&')) |
| + max_query = ' '.join(common_query) % ( |
| + 'IFNULL(MAX(test_started_time), NOW())', job_name) |
| + else: |
| + max_query = 'SELECT NOW()' |
| + |
| + iteration_values = 'job_name, job_tag, iteration_value' |
| + job_name = common_job_name % '|'.join(boards.split('&')) |
| + query = [ |
| + ' '.join(common_query) % (iteration_values, job_name), |
| + ' AND test_started_time > (%s)' % min_query, |
| + ' AND test_finished_time < (%s)' % max_query, |
| + 'ORDER BY test_started_time'] |
| + cursor.execute(' '.join(query)) |
| + return AggregateBuilds(test_key, cursor.fetchall()) |