# Copyright 2015 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.

"""Developer tool for exploring perf website interaction.

The performance dashboards can be found here (login w/your @google.com):
  https://chromeperf.appspot.com/  (production)
  https://chrome-perf.googleplex.com/  (staging)

By default though, this tool will post data to a local instance running on your
system.  See this page for details on running that:
  https://sites.google.com/a/google.com/chromeperf/

This guide should help familiarize yourself with the perf data format:
  http://dev.chromium.org/developers/testing/sending-data-to-the-performance-dashboard
This tool currently uses the version 0 data format.

Some notes:
 - --revision or --cros-version/--chrome-version should be independent
 - do not mix rev/cros-ver/chrome-ver in the same data series/graph

Examples:
  # Create a data point at (20110701024650,361077106).  The test name is
  # "sdk.size" and is in the "base" series in the "combined" graph.
  $ ./perf_dashboard_tool -u bytes -t sdk.size -g combined -d base \\
      --revision 20110701024650 361077106

  # Create a data point at (6689.0.0,2000400100).  The test name is
  # "disk.size" and is in the "data" series.
  $ ./perf_dashboard_tool -u bytes -t disk.size --cros-version 6689.0.0 \\
      --chrome-version 41.6689.0.0 2000400100
"""

from __future__ import print_function

import getpass
import logging
import os
import tempfile
import urllib

from chromite.lib import commandline
from chromite.lib import cros_build_lib
from chromite.lib import perf_uploader


MASTER_NAME = 'ChromeOSPerfTest'
TEST_NAME = 'perf_uploader_tool.%s' % getpass.getuser()


def GetParser():
  """Return a command line parser"""
  parser = commandline.ArgumentParser(description=__doc__)
  parser.add_argument('-n', '--dry-run', default=False, action='store_true',
                      help='Show what would be uploaded')
  parser.add_argument('--url', default=perf_uploader.LOCAL_DASHBOARD_URL,
                      help='Dashboard to send results to')

  group = parser.add_argument_group('Bot Details')
  group.add_argument('-m', '--master', default=MASTER_NAME,
                     help='The buildbot master field')
  group.add_argument('-b', '--bot',
                     default=cros_build_lib.GetHostName(fully_qualified=True),
                     help='The bot name (e.g. buildbot config)')

  group = parser.add_argument_group('Version Options (X-axis)')
  group.add_argument('--revision', default=None,
                     help='Revision number')
  group.add_argument('--cros-version', default=None,
                     help='Chrome OS version (X.Y.Z)')
  group.add_argument('--chrome-version', default=None,
                     help='Chrome version (M.X.Y.Z)')

  group = parser.add_argument_group('Data Options')
  group.add_argument('-t', '--test', default=TEST_NAME,
                     help='The test name field')
  group.add_argument('--higher-is-better', default=False, action='store_true',
                     help='Whether higher values are better than lower')
  group.add_argument('-u', '--units', default='',
                     help='Units for the perf data (e.g. percent, bytes)')
  group.add_argument('-g', '--graph',
                     help='Graph name (to group multiple tests)')
  group.add_argument('-d', '--description', default='data',
                     help='Name for this data series')
  group.add_argument('--stdio-uri',
                     help='Custom log page to link data point to')
  group.add_argument('data',
                     help='Data point (int or float)')

  return parser


def main(argv):
  parser = GetParser()
  opts = parser.parse_args(argv)
  opts.Freeze()

  logging.info('Uploading results to %s', opts.url)
  logging.info('Master name: %s', opts.master)
  logging.info('Test name: %s', opts.test)

  with tempfile.NamedTemporaryFile() as output:
    perf_uploader.OutputPerfValue(
        output.name,
        opts.description,
        float(opts.data),
        opts.units,
        graph=opts.graph,
        stdio_uri=opts.stdio_uri)
    perf_values = perf_uploader.LoadPerfValues(output.name)

  logging.debug('Uploading:')
  for value in perf_values:
    logging.debug('  %s', value)

  perf_uploader.UploadPerfValues(
      perf_values,
      opts.bot,
      opts.test,
      revision=opts.revision,
      cros_version=opts.cros_version,
      chrome_version=opts.chrome_version,
      dashboard=opts.url,
      master_name=opts.master,
      test_prefix='',
      platform_prefix='',
      dry_run=opts.dry_run)

  data_name = opts.graph if opts.graph else opts.description
  args = {
      'masters': opts.master,
      'tests': '%s/%s' % (opts.test, data_name),
      'bots': opts.bot,
  }
  view_url = os.path.join(opts.url, 'report?%s' % urllib.urlencode(args))
  logging.info('View results at %s', view_url)
  logging.info('Note: To make tests public, visit %s',
               os.path.join(opts.url, 'change_internal_only'))
  logging.info('Note: To update the test list, visit %s',
               os.path.join(opts.url, 'update_test_suites'))
