137 lines
3.9 KiB
Python
Executable File
137 lines
3.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# Copyright (C) 2019 The Android Open Source Project
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import argparse
|
|
import json
|
|
import hashlib
|
|
import sys
|
|
|
|
from config import DB, PROJECT
|
|
from common_utils import req, SCOPES
|
|
'''
|
|
Uploads the performance metrics of the Perfetto tests to StackDriver and
|
|
Firebase.
|
|
|
|
The expected format of the JSON is as follows:
|
|
{
|
|
metrics: [
|
|
{
|
|
'metric': *metric name*,
|
|
'value': *metric value*,
|
|
'unit': *either s (seconds) or b (bytes)*,
|
|
'tags': {
|
|
*tag name*: *tag value*,
|
|
...
|
|
},
|
|
'labels': {
|
|
*label name*: *label value*,
|
|
...
|
|
}
|
|
},
|
|
...
|
|
]
|
|
}
|
|
'''
|
|
|
|
STACKDRIVER_API = 'https://monitoring.googleapis.com/v3/projects/%s' % PROJECT
|
|
SCOPES.append('https://www.googleapis.com/auth/firebase.database')
|
|
SCOPES.append('https://www.googleapis.com/auth/userinfo.email')
|
|
SCOPES.append('https://www.googleapis.com/auth/monitoring.write')
|
|
|
|
|
|
def sha1(obj):
|
|
hasher = hashlib.sha1()
|
|
hasher.update(
|
|
json.dumps(obj, sort_keys=True, separators=(',', ':')).encode('utf-8'))
|
|
return hasher.hexdigest()
|
|
|
|
|
|
def metric_list_to_hash_dict(raw_metrics):
|
|
metrics = {}
|
|
for metric in raw_metrics:
|
|
key = '%s-%s' % (metric['metric'], sha1(metric['tags']))
|
|
metrics[key] = metric
|
|
return metrics
|
|
|
|
|
|
def create_stackdriver_metrics(ts, metrics):
|
|
# Chunk up metrics into 100 element chunks to comply with Stackdriver's
|
|
# restrictions on the number of metrics in a request.
|
|
metrics_list = list(metrics.values())
|
|
metric_chunks = [metrics_list[x:x + 100] for x in range(0, len(metrics), 100)]
|
|
desc_chunks = []
|
|
|
|
for chunk in metric_chunks:
|
|
desc = {'timeSeries': []}
|
|
for metric in chunk:
|
|
metric_name = metric['metric']
|
|
desc['timeSeries'] += [{
|
|
'metric': {
|
|
'type':
|
|
'custom.googleapis.com/perfetto-ci/perf/%s' % metric_name,
|
|
'labels':
|
|
dict(
|
|
list(metric.get('tags', {}).items()) +
|
|
list(metric.get('labels', {}).items())),
|
|
},
|
|
'resource': {
|
|
'type': 'global'
|
|
},
|
|
'points': [{
|
|
'interval': {
|
|
'endTime': ts
|
|
},
|
|
'value': {
|
|
'doubleValue': str(metric['value'])
|
|
}
|
|
}]
|
|
}]
|
|
desc_chunks.append(desc)
|
|
return desc_chunks
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument(
|
|
'--job-id',
|
|
type=str,
|
|
required=True,
|
|
help='The Perfetto CI job ID to tie this upload to')
|
|
parser.add_argument(
|
|
'metrics_file', type=str, help='File containing the metrics to upload')
|
|
args = parser.parse_args()
|
|
|
|
with open(args.metrics_file, 'r') as metrics_file:
|
|
raw_metrics = json.loads(metrics_file.read())
|
|
|
|
job = req('GET', '%s/jobs/%s.json' % (DB, args.job_id))
|
|
ts = job['time_started']
|
|
|
|
metrics = metric_list_to_hash_dict(raw_metrics['metrics'])
|
|
req('PUT', '%s/perf/%s.json' % (DB, args.job_id), body=metrics)
|
|
|
|
# Only upload Stackdriver metrics for post-submit runs.
|
|
git_ref = job['env'].get('PERFETTO_TEST_GIT_REF')
|
|
if git_ref == 'refs/heads/master':
|
|
sd_metrics_chunks = create_stackdriver_metrics(ts, metrics)
|
|
for sd_metrics in sd_metrics_chunks:
|
|
req('POST', STACKDRIVER_API + '/timeSeries', body=sd_metrics)
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|