#!/usr/bin/env vpython3
#
# Copyright 2021 The ANGLE Project Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# process_angle_perf_results.py:
#   Perf result merging and upload. Adapted from the Chromium script:
#   https://chromium.googlesource.com/chromium/src/+/main/tools/perf/process_perf_results.py

from __future__ import print_function

import argparse
import collections
import datetime
import json
import logging
import multiprocessing
import os
import pathlib
import shutil
import subprocess
import sys
import tempfile
import time
import uuid

logging.basicConfig(
    level=logging.INFO,
    format='(%(levelname)s) %(asctime)s pid=%(process)d'
    '  %(module)s.%(funcName)s:%(lineno)d  %(message)s')

ANGLE_ROOT = pathlib.Path(__file__).resolve().parents[1]
if str(ANGLE_ROOT) not in sys.path:
    sys.path.insert(0, str(ANGLE_ROOT))
from src import commit_id

PY_UTILS = str(ANGLE_ROOT / 'src' / 'tests' / 'py_utils')
if PY_UTILS not in sys.path:
    os.stat(PY_UTILS) and sys.path.insert(0, PY_UTILS)
import angle_metrics
import angle_path_util

angle_path_util.AddDepsDirToPath('tools/perf')
from core import path_util

path_util.AddTelemetryToPath()
from core import upload_results_to_perf_dashboard
from core import results_merger

path_util.AddAndroidPylibToPath()
try:
    from pylib.utils import logdog_helper
except ImportError:
    pass

path_util.AddTracingToPath()
from tracing.value import histogram
from tracing.value import histogram_set
from tracing.value.diagnostics import generic_set
from tracing.value.diagnostics import reserved_infos

RESULTS_URL = 'https://chromeperf.appspot.com'
JSON_CONTENT_TYPE = 'application/json'
MACHINE_GROUP = 'ANGLE'
BUILD_URL = 'https://ci.chromium.org/ui/p/angle/builders/ci/%s/%d'

GSUTIL_PY_PATH = str(
    pathlib.Path(__file__).resolve().parents[1] / 'third_party' / 'depot_tools' / 'gsutil.py')


def _upload_perf_results(json_to_upload, name, configuration_name, build_properties,
                         output_json_file):
    """Upload the contents of result JSON(s) to the perf dashboard."""
    args = [
        '--buildername',
        build_properties['buildername'],
        '--buildnumber',
        str(build_properties['buildnumber']),
        '--name',
        name,
        '--configuration-name',
        configuration_name,
        '--results-file',
        json_to_upload,
        '--results-url',
        RESULTS_URL,
        '--output-json-file',
        output_json_file,
        '--perf-dashboard-machine-group',
        MACHINE_GROUP,
        '--got-angle-revision',
        build_properties['got_angle_revision'],
        '--send-as-histograms',
        '--project',
        'angle',
    ]

    if build_properties.get('git_revision'):
        args.append('--git-revision')
        args.append(build_properties['git_revision'])

    #TODO(crbug.com/1072729): log this in top level
    logging.info('upload_results_to_perf_dashboard: %s.' % args)

    return upload_results_to_perf_dashboard.main(args)


def _merge_json_output(output_json, jsons_to_merge, extra_links, test_cross_device=False):
    """Merges the contents of one or more results JSONs.

  Args:
    output_json: A path to a JSON file to which the merged results should be
      written.
    jsons_to_merge: A list of JSON files that should be merged.
    extra_links: a (key, value) map in which keys are the human-readable strings
      which describe the data, and value is logdog url that contain the data.
  """
    begin_time = time.time()
    merged_results = results_merger.merge_test_results(jsons_to_merge, test_cross_device)

    # Only append the perf results links if present
    if extra_links:
        merged_results['links'] = extra_links

    with open(output_json, 'w') as f:
        json.dump(merged_results, f)

    end_time = time.time()
    print_duration('Merging json test results', begin_time, end_time)
    return 0


def _handle_perf_json_test_results(benchmark_directory_map, test_results_list):
    """Checks the test_results.json under each folder:

  1. mark the benchmark 'enabled' if tests results are found
  2. add the json content to a list for non-ref.
  """
    begin_time = time.time()
    benchmark_enabled_map = {}
    for benchmark_name, directories in benchmark_directory_map.items():
        for directory in directories:
            # Obtain the test name we are running
            is_ref = '.reference' in benchmark_name
            enabled = True
            try:
                with open(os.path.join(directory, 'test_results.json')) as json_data:
                    json_results = json.load(json_data)
                    if not json_results:
                        # Output is null meaning the test didn't produce any results.
                        # Want to output an error and continue loading the rest of the
                        # test results.
                        logging.warning('No results produced for %s, skipping upload' % directory)
                        continue
                    if json_results.get('version') == 3:
                        # Non-telemetry tests don't have written json results but
                        # if they are executing then they are enabled and will generate
                        # chartjson results.
                        if not bool(json_results.get('tests')):
                            enabled = False
                    if not is_ref:
                        # We don't need to upload reference build data to the
                        # flakiness dashboard since we don't monitor the ref build
                        test_results_list.append(json_results)
            except IOError as e:
                # TODO(crbug.com/936602): Figure out how to surface these errors. Should
                # we have a non-zero exit code if we error out?
                logging.error('Failed to obtain test results for %s: %s', benchmark_name, e)
                continue
            if not enabled:
                # We don't upload disabled benchmarks or tests that are run
                # as a smoke test
                logging.info('Benchmark %s ran no tests on at least one shard' % benchmark_name)
                continue
            benchmark_enabled_map[benchmark_name] = True

    end_time = time.time()
    print_duration('Analyzing perf json test results', begin_time, end_time)
    return benchmark_enabled_map


def _generate_unique_logdog_filename(name_prefix):
    return name_prefix + '_' + str(uuid.uuid4())


def _handle_perf_logs(benchmark_directory_map, extra_links):
    """ Upload benchmark logs to logdog and add a page entry for them. """
    begin_time = time.time()
    benchmark_logs_links = collections.defaultdict(list)

    for benchmark_name, directories in benchmark_directory_map.items():
        for directory in directories:
            benchmark_log_file = os.path.join(directory, 'benchmark_log.txt')
            if os.path.exists(benchmark_log_file):
                with open(benchmark_log_file) as f:
                    uploaded_link = logdog_helper.text(
                        name=_generate_unique_logdog_filename(benchmark_name), data=f.read())
                    benchmark_logs_links[benchmark_name].append(uploaded_link)

    logdog_file_name = _generate_unique_logdog_filename('Benchmarks_Logs')
    logdog_stream = logdog_helper.text(
        logdog_file_name,
        json.dumps(benchmark_logs_links, sort_keys=True, indent=4, separators=(',', ': ')),
        content_type=JSON_CONTENT_TYPE)
    extra_links['Benchmarks logs'] = logdog_stream
    end_time = time.time()
    print_duration('Generating perf log streams', begin_time, end_time)


def _handle_benchmarks_shard_map(benchmarks_shard_map_file, extra_links):
    begin_time = time.time()
    with open(benchmarks_shard_map_file) as f:
        benchmarks_shard_data = f.read()
        logdog_file_name = _generate_unique_logdog_filename('Benchmarks_Shard_Map')
        logdog_stream = logdog_helper.text(
            logdog_file_name, benchmarks_shard_data, content_type=JSON_CONTENT_TYPE)
        extra_links['Benchmarks shard map'] = logdog_stream
    end_time = time.time()
    print_duration('Generating benchmark shard map stream', begin_time, end_time)


def _get_benchmark_name(directory):
    return os.path.basename(directory).replace(" benchmark", "")


def _scan_output_dir(task_output_dir):
    benchmark_directory_map = {}
    benchmarks_shard_map_file = None

    directory_list = [
        f for f in os.listdir(task_output_dir)
        if not os.path.isfile(os.path.join(task_output_dir, f))
    ]
    benchmark_directory_list = []
    for directory in directory_list:
        for f in os.listdir(os.path.join(task_output_dir, directory)):
            path = os.path.join(task_output_dir, directory, f)
            if os.path.isdir(path):
                benchmark_directory_list.append(path)
            elif path.endswith('benchmarks_shard_map.json'):
                benchmarks_shard_map_file = path
    # Now create a map of benchmark name to the list of directories
    # the lists were written to.
    for directory in benchmark_directory_list:
        benchmark_name = _get_benchmark_name(directory)
        logging.debug('Found benchmark %s directory %s' % (benchmark_name, directory))
        if benchmark_name in benchmark_directory_map.keys():
            benchmark_directory_map[benchmark_name].append(directory)
        else:
            benchmark_directory_map[benchmark_name] = [directory]

    return benchmark_directory_map, benchmarks_shard_map_file


def _upload_to_skia_perf(benchmark_directory_map, benchmark_enabled_map, build_properties_map):
    metric_filenames = []

    for benchmark_name, directories in benchmark_directory_map.items():
        if not benchmark_enabled_map.get(benchmark_name, False):
            continue

        for directory in directories:
            metric_filenames.append(os.path.join(directory, 'angle_metrics.json'))

    assert metric_filenames

    buildername = build_properties_map['buildername']  # e.g. win10-nvidia-gtx1660-perf
    skia_data = {
        'version': 1,
        'git_hash': build_properties_map['got_angle_revision'],
        'key': {
            'buildername': buildername,
        },
        'results': angle_metrics.ConvertToSkiaPerf(metric_filenames),
    }

    skia_perf_dir = tempfile.mkdtemp('skia_perf')
    try:
        local_file = os.path.join(skia_perf_dir, '%s.%s.json' % (buildername, time.time()))
        with open(local_file, 'w') as f:
            json.dump(skia_data, f, indent=2)
        gs_dir = 'gs://angle-perf-skia/angle_perftests/%s/' % (
            datetime.datetime.now().strftime('%Y/%m/%d/%H'))
        upload_cmd = ['vpython3', GSUTIL_PY_PATH, 'cp', local_file, gs_dir]
        logging.info('Skia upload: %s', ' '.join(upload_cmd))
        subprocess.check_call(upload_cmd)
    finally:
        shutil.rmtree(skia_perf_dir)


def process_perf_results(output_json,
                         configuration_name,
                         build_properties,
                         task_output_dir,
                         smoke_test_mode,
                         output_results_dir,
                         lightweight=False,
                         skip_perf=False):
    """Process perf results.

  Consists of merging the json-test-format output, uploading the perf test
  output (histogram), and store the benchmark logs in logdog.

  Each directory in the task_output_dir represents one benchmark
  that was run. Within this directory, there is a subdirectory with the name
  of the benchmark that was run. In that subdirectory, there is a
  perftest-output.json file containing the performance results in histogram
  format and an output.json file containing the json test results for the
  benchmark.

  Returns:
    (return_code, upload_results_map):
      return_code is 0 if the whole operation is successful, non zero otherwise.
      benchmark_upload_result_map: the dictionary that describe which benchmarks
        were successfully uploaded.
  """
    handle_perf = not lightweight or not skip_perf
    handle_non_perf = not lightweight or skip_perf
    logging.info('lightweight mode: %r; handle_perf: %r; handle_non_perf: %r' %
                 (lightweight, handle_perf, handle_non_perf))

    begin_time = time.time()
    return_code = 0
    benchmark_upload_result_map = {}

    benchmark_directory_map, benchmarks_shard_map_file = _scan_output_dir(task_output_dir)

    test_results_list = []
    extra_links = {}

    if handle_non_perf:
        # First, upload benchmarks shard map to logdog and add a page
        # entry for it in extra_links.
        if benchmarks_shard_map_file:
            _handle_benchmarks_shard_map(benchmarks_shard_map_file, extra_links)

        # Second, upload all the benchmark logs to logdog and add a page entry for
        # those links in extra_links.
        _handle_perf_logs(benchmark_directory_map, extra_links)

    # Then try to obtain the list of json test results to merge
    # and determine the status of each benchmark.
    benchmark_enabled_map = _handle_perf_json_test_results(benchmark_directory_map,
                                                           test_results_list)

    if not smoke_test_mode and handle_perf:
        build_properties_map = json.loads(build_properties)
        if not configuration_name:
            # we are deprecating perf-id crbug.com/817823
            configuration_name = build_properties_map['buildername']

        try:
            return_code, benchmark_upload_result_map = _handle_perf_results(
                benchmark_enabled_map, benchmark_directory_map, configuration_name,
                build_properties_map, extra_links, output_results_dir)
        except Exception:
            logging.exception('Error handling perf results jsons')
            return_code = 1

        try:
            _upload_to_skia_perf(benchmark_directory_map, benchmark_enabled_map,
                                 build_properties_map)
        except Exception:
            logging.exception('Error uploading to skia perf')
            return_code = 1

    if handle_non_perf:
        # Finally, merge all test results json, add the extra links and write out to
        # output location
        try:
            _merge_json_output(output_json, test_results_list, extra_links)
        except Exception:
            logging.exception('Error handling test results jsons.')

    end_time = time.time()
    print_duration('Total process_perf_results', begin_time, end_time)
    return return_code, benchmark_upload_result_map


def _merge_histogram_results(histogram_lists):
    merged_results = []
    for histogram_list in histogram_lists:
        merged_results += histogram_list

    return merged_results


def _load_histogram_set_from_dict(data):
    histograms = histogram_set.HistogramSet()
    histograms.ImportDicts(data)
    return histograms


def _add_build_info(results, benchmark_name, build_properties):
    histograms = _load_histogram_set_from_dict(results)

    common_diagnostics = {
        reserved_infos.MASTERS:
            build_properties['builder_group'],
        reserved_infos.BOTS:
            build_properties['buildername'],
        reserved_infos.POINT_ID:
            build_properties.get('angle_commit_pos',
                                 commit_id.get_commit_position(str(ANGLE_ROOT))),
        reserved_infos.BENCHMARKS:
            benchmark_name,
        reserved_infos.ANGLE_REVISIONS:
            build_properties['got_angle_revision'],
        reserved_infos.BUILD_URLS:
            BUILD_URL % (build_properties['buildername'], build_properties['buildnumber']),
    }

    for k, v in common_diagnostics.items():
        histograms.AddSharedDiagnosticToAllHistograms(k.name, generic_set.GenericSet([v]))

    return histograms.AsDicts()


def _merge_perf_results(benchmark_name, results_filename, directories, build_properties):
    begin_time = time.time()
    collected_results = []
    for directory in directories:
        filename = os.path.join(directory, 'perf_results.json')
        try:
            with open(filename) as pf:
                collected_results.append(json.load(pf))
        except IOError as e:
            # TODO(crbug.com/936602): Figure out how to surface these errors. Should
            # we have a non-zero exit code if we error out?
            logging.error('Failed to obtain perf results from %s: %s', directory, e)
    if not collected_results:
        logging.error('Failed to obtain any perf results from %s.', benchmark_name)
        return

    # Assuming that multiple shards will be histogram set
    # Non-telemetry benchmarks only ever run on one shard
    merged_results = []
    assert (isinstance(collected_results[0], list))
    merged_results = _merge_histogram_results(collected_results)

    # Write additional histogram build info.
    merged_results = _add_build_info(merged_results, benchmark_name, build_properties)

    with open(results_filename, 'w') as rf:
        json.dump(merged_results, rf)

    end_time = time.time()
    print_duration(('%s results merging' % (benchmark_name)), begin_time, end_time)


def _upload_individual(benchmark_name, directories, configuration_name, build_properties,
                       output_json_file):
    tmpfile_dir = tempfile.mkdtemp()
    try:
        upload_begin_time = time.time()
        # There are potentially multiple directores with results, re-write and
        # merge them if necessary
        results_filename = None
        if len(directories) > 1:
            merge_perf_dir = os.path.join(os.path.abspath(tmpfile_dir), benchmark_name)
            if not os.path.exists(merge_perf_dir):
                os.makedirs(merge_perf_dir)
            results_filename = os.path.join(merge_perf_dir, 'merged_perf_results.json')
            _merge_perf_results(benchmark_name, results_filename, directories, build_properties)
        else:
            # It was only written to one shard, use that shards data
            results_filename = os.path.join(directories[0], 'perf_results.json')

        results_size_in_mib = os.path.getsize(results_filename) / (2**20)
        logging.info('Uploading perf results from %s benchmark (size %s Mib)' %
                     (benchmark_name, results_size_in_mib))
        upload_return_code = _upload_perf_results(results_filename, benchmark_name,
                                                  configuration_name, build_properties,
                                                  output_json_file)
        upload_end_time = time.time()
        print_duration(('%s upload time' % (benchmark_name)), upload_begin_time, upload_end_time)
        return (benchmark_name, upload_return_code == 0)
    finally:
        shutil.rmtree(tmpfile_dir)


def _upload_individual_benchmark(params):
    try:
        return _upload_individual(*params)
    except Exception:
        benchmark_name = params[0]
        upload_succeed = False
        logging.exception('Error uploading perf result of %s' % benchmark_name)
        return benchmark_name, upload_succeed


def _GetCpuCount(log=True):
    try:
        cpu_count = multiprocessing.cpu_count()
        if sys.platform == 'win32':
            # TODO(crbug.com/1190269) - we can't use more than 56
            # cores on Windows or Python3 may hang.
            cpu_count = min(cpu_count, 56)
        return cpu_count
    except NotImplementedError:
        if log:
            logging.warn('Failed to get a CPU count for this bot. See crbug.com/947035.')
        # TODO(crbug.com/948281): This is currently set to 4 since the mac masters
        # only have 4 cores. Once we move to all-linux, this can be increased or
        # we can even delete this whole function and use multiprocessing.cpu_count()
        # directly.
        return 4


def _load_shard_id_from_test_results(directory):
    shard_id = None
    test_json_path = os.path.join(directory, 'test_results.json')
    try:
        with open(test_json_path) as f:
            test_json = json.load(f)
            all_results = test_json['tests']
            for _, benchmark_results in all_results.items():
                for _, measurement_result in benchmark_results.items():
                    shard_id = measurement_result['shard']
                    break
    except IOError as e:
        logging.error('Failed to open test_results.json from %s: %s', test_json_path, e)
    except KeyError as e:
        logging.error('Failed to locate results in test_results.json: %s', e)
    return shard_id


def _find_device_id_by_shard_id(benchmarks_shard_map_file, shard_id):
    try:
        with open(benchmarks_shard_map_file) as f:
            shard_map_json = json.load(f)
            device_id = shard_map_json['extra_infos']['bot #%s' % shard_id]
    except KeyError as e:
        logging.error('Failed to locate device name in shard map: %s', e)
    return device_id


def _update_perf_json_with_summary_on_device_id(directory, device_id):
    perf_json_path = os.path.join(directory, 'perf_results.json')
    try:
        with open(perf_json_path, 'r') as f:
            perf_json = json.load(f)
    except IOError as e:
        logging.error('Failed to open perf_results.json from %s: %s', perf_json_path, e)
    summary_key_guid = str(uuid.uuid4())
    summary_key_generic_set = {
        'values': ['device_id'],
        'guid': summary_key_guid,
        'type': 'GenericSet'
    }
    perf_json.insert(0, summary_key_generic_set)
    logging.info('Inserted summary key generic set for perf result in %s: %s', directory,
                 summary_key_generic_set)
    stories_guids = set()
    for entry in perf_json:
        if 'diagnostics' in entry:
            entry['diagnostics']['summaryKeys'] = summary_key_guid
            stories_guids.add(entry['diagnostics']['stories'])
    for entry in perf_json:
        if 'guid' in entry and entry['guid'] in stories_guids:
            entry['values'].append(device_id)
    try:
        with open(perf_json_path, 'w') as f:
            json.dump(perf_json, f)
    except IOError as e:
        logging.error('Failed to writing perf_results.json to %s: %s', perf_json_path, e)
    logging.info('Finished adding device id %s in perf result.', device_id)


def _handle_perf_results(benchmark_enabled_map, benchmark_directory_map, configuration_name,
                         build_properties, extra_links, output_results_dir):
    """
    Upload perf results to the perf dashboard.

    This method also upload the perf results to logdog and augment it to
    |extra_links|.

    Returns:
      (return_code, benchmark_upload_result_map)
      return_code is 0 if this upload to perf dashboard successfully, 1
        otherwise.
       benchmark_upload_result_map is a dictionary describes which benchmark
        was successfully uploaded.
  """
    begin_time = time.time()
    # Upload all eligible benchmarks to the perf dashboard
    results_dict = {}

    invocations = []
    for benchmark_name, directories in benchmark_directory_map.items():
        if not benchmark_enabled_map.get(benchmark_name, False):
            continue
        # Create a place to write the perf results that you will write out to
        # logdog.
        output_json_file = os.path.join(output_results_dir, (str(uuid.uuid4()) + benchmark_name))
        results_dict[benchmark_name] = output_json_file
        #TODO(crbug.com/1072729): pass final arguments instead of build properties
        # and configuration_name
        invocations.append(
            (benchmark_name, directories, configuration_name, build_properties, output_json_file))

    # Kick off the uploads in multiple processes
    # crbug.com/1035930: We are hitting HTTP Response 429. Limit ourselves
    # to 2 processes to avoid this error. Uncomment the following code once
    # the problem is fixed on the dashboard side.
    # pool = multiprocessing.Pool(_GetCpuCount())
    pool = multiprocessing.Pool(2)
    upload_result_timeout = False
    try:
        async_result = pool.map_async(_upload_individual_benchmark, invocations)
        # TODO(crbug.com/947035): What timeout is reasonable?
        results = async_result.get(timeout=4000)
    except multiprocessing.TimeoutError:
        upload_result_timeout = True
        logging.error('Timeout uploading benchmarks to perf dashboard in parallel')
        results = []
        for benchmark_name in benchmark_directory_map:
            results.append((benchmark_name, False))
    finally:
        pool.terminate()

    # Keep a mapping of benchmarks to their upload results
    benchmark_upload_result_map = {}
    for r in results:
        benchmark_upload_result_map[r[0]] = r[1]

    logdog_dict = {}
    upload_failures_counter = 0
    logdog_stream = None
    logdog_label = 'Results Dashboard'
    for benchmark_name, output_file in results_dict.items():
        upload_succeed = benchmark_upload_result_map[benchmark_name]
        if not upload_succeed:
            upload_failures_counter += 1
        is_reference = '.reference' in benchmark_name
        _write_perf_data_to_logfile(
            benchmark_name,
            output_file,
            configuration_name,
            build_properties,
            logdog_dict,
            is_reference,
            upload_failure=not upload_succeed)

    logdog_file_name = _generate_unique_logdog_filename('Results_Dashboard_')
    logdog_stream = logdog_helper.text(
        logdog_file_name,
        json.dumps(dict(logdog_dict), sort_keys=True, indent=4, separators=(',', ': ')),
        content_type=JSON_CONTENT_TYPE)
    if upload_failures_counter > 0:
        logdog_label += (' %s merge script perf data upload failures' % upload_failures_counter)
    extra_links[logdog_label] = logdog_stream
    end_time = time.time()
    print_duration('Uploading results to perf dashboard', begin_time, end_time)
    if upload_result_timeout or upload_failures_counter > 0:
        return 1, benchmark_upload_result_map
    return 0, benchmark_upload_result_map


def _write_perf_data_to_logfile(benchmark_name, output_file, configuration_name, build_properties,
                                logdog_dict, is_ref, upload_failure):
    viewer_url = None
    # logdog file to write perf results to
    if os.path.exists(output_file):
        results = None
        with open(output_file) as f:
            try:
                results = json.load(f)
            except ValueError:
                logging.error('Error parsing perf results JSON for benchmark  %s' % benchmark_name)
        if results:
            try:
                json_fname = _generate_unique_logdog_filename(benchmark_name)
                output_json_file = logdog_helper.open_text(json_fname)
                json.dump(results, output_json_file, indent=4, separators=(',', ': '))
            except ValueError as e:
                logging.error('ValueError: "%s" while dumping output to logdog' % e)
            finally:
                output_json_file.close()
            viewer_url = output_json_file.get_viewer_url()
    else:
        logging.warning("Perf results JSON file doesn't exist for benchmark %s" % benchmark_name)

    base_benchmark_name = benchmark_name.replace('.reference', '')

    if base_benchmark_name not in logdog_dict:
        logdog_dict[base_benchmark_name] = {}

    # add links for the perf results and the dashboard url to
    # the logs section of buildbot
    if is_ref:
        if viewer_url:
            logdog_dict[base_benchmark_name]['perf_results_ref'] = viewer_url
        if upload_failure:
            logdog_dict[base_benchmark_name]['ref_upload_failed'] = 'True'
    else:
        # TODO(jmadill): Figure out if we can get a dashboard URL here. http://anglebug.com/40096778
        # logdog_dict[base_benchmark_name]['dashboard_url'] = (
        #     upload_results_to_perf_dashboard.GetDashboardUrl(benchmark_name, configuration_name,
        #                                                      RESULTS_URL,
        #                                                      build_properties['got_revision_cp'],
        #                                                      _GetMachineGroup(build_properties)))
        if viewer_url:
            logdog_dict[base_benchmark_name]['perf_results'] = viewer_url
        if upload_failure:
            logdog_dict[base_benchmark_name]['upload_failed'] = 'True'


def print_duration(step, start, end):
    logging.info('Duration of %s: %d seconds' % (step, end - start))


def main():
    """ See collect_task.collect_task for more on the merge script API. """
    logging.info(sys.argv)
    parser = argparse.ArgumentParser()
    # configuration-name (previously perf-id) is the name of bot the tests run on
    # For example, buildbot-test is the name of the android-go-perf bot
    # configuration-name and results-url are set in the json file which is going
    # away tools/perf/core/chromium.perf.fyi.extras.json
    parser.add_argument('--configuration-name', help=argparse.SUPPRESS)
    parser.add_argument('--build-properties', help=argparse.SUPPRESS)
    parser.add_argument('--summary-json', required=True, help=argparse.SUPPRESS)
    parser.add_argument('--task-output-dir', required=True, help=argparse.SUPPRESS)
    parser.add_argument('-o', '--output-json', required=True, help=argparse.SUPPRESS)
    parser.add_argument(
        '--skip-perf',
        action='store_true',
        help='In lightweight mode, using --skip-perf will skip the performance'
        ' data handling.')
    parser.add_argument(
        '--lightweight',
        action='store_true',
        help='Choose the lightweight mode in which the perf result handling'
        ' is performed on a separate VM.')
    parser.add_argument('json_files', nargs='*', help=argparse.SUPPRESS)
    parser.add_argument(
        '--smoke-test-mode',
        action='store_true',
        help='This test should be run in smoke test mode'
        ' meaning it does not upload to the perf dashboard')

    args = parser.parse_args()

    with open(args.summary_json) as f:
        shard_summary = json.load(f)
    shard_failed = any(int(shard.get('exit_code', 1)) != 0 for shard in shard_summary['shards'])

    output_results_dir = tempfile.mkdtemp('outputresults')
    try:
        return_code, _ = process_perf_results(args.output_json, args.configuration_name,
                                              args.build_properties, args.task_output_dir,
                                              args.smoke_test_mode, output_results_dir,
                                              args.lightweight, args.skip_perf)
    except Exception:
        logging.exception('process_perf_results raised an exception')
        return_code = 1
    finally:
        shutil.rmtree(output_results_dir)

    if return_code != 0 and shard_failed:
        logging.warning('Perf processing failed but one or more shards failed earlier')
        return_code = 0  # Enables the failed build info to be rendered normally

    return return_code


if __name__ == '__main__':
    sys.exit(main())
