#!/usr/bin/python
#
# ==-- process-stats-dir - summarize one or more Swift -stats-output-dirs --==#
#
# This source file is part of the Swift.org open source project
#
# Copyright (c) 2014-2017 Apple Inc. and the Swift project authors
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See https://swift.org/LICENSE.txt for license information
# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
#
# ==------------------------------------------------------------------------==#
#
# This file processes the contents of one or more directories generated by
# `swiftc -stats-output-dir` and emits summary data, traces etc. for analysis.

import argparse
import csv
import itertools
import json
import os
import platform
import re
import sys
import time
import urllib
import urllib2
from collections import namedtuple
from operator import attrgetter
from jobstats import load_stats_dir, merge_all_jobstats


MODULE_PAT = re.compile('^(\w+)\.')


def module_name_of_stat(name):
    return re.match(MODULE_PAT, name).groups()[0]


def stat_name_minus_module(name):
    return re.sub(MODULE_PAT, '', name)


# Perform any custom processing of args here, in particular the
# select_stats_from_csv_baseline step, which is a bit subtle.
def vars_of_args(args):
    vargs = vars(args)
    if args.select_stats_from_csv_baseline is not None:
        b = read_stats_dict_from_csv(args.select_stats_from_csv_baseline)
        # Sniff baseline stat-names to figure out if they're module-qualified
        # even when the user isn't asking us to _output_ module-grouped data.
        all_triples = all(len(k.split('.')) == 3 for k in b.keys())
        if args.group_by_module or all_triples:
            vargs['select_stat'] = set(stat_name_minus_module(k)
                                       for k in b.keys())
        else:
            vargs['select_stat'] = b.keys()
    return vargs


# Passed args with 2-element remainder ["old", "new"], return a list of tuples
# of the form [(name, (oldstats, newstats))] where each name is a common subdir
# of each of "old" and "new", and the stats are those found in the respective
# dirs.
def load_paired_stats_dirs(args):
    assert(len(args.remainder) == 2)
    paired_stats = []
    (old, new) = args.remainder
    vargs = vars_of_args(args)
    for p in sorted(os.listdir(old)):
        full_old = os.path.join(old, p)
        full_new = os.path.join(new, p)
        if not (os.path.exists(full_old) and os.path.isdir(full_old) and
                os.path.exists(full_new) and os.path.isdir(full_new)):
            continue
        old_stats = load_stats_dir(full_old, **vargs)
        new_stats = load_stats_dir(full_new, **vargs)
        if len(old_stats) == 0 or len(new_stats) == 0:
            continue
        paired_stats.append((p, (old_stats, new_stats)))
    return paired_stats


def write_catapult_trace(args):
    allstats = []
    vargs = vars_of_args(args)
    for path in args.remainder:
        allstats += load_stats_dir(path, **vargs)
    json.dump([s.to_catapult_trace_obj() for s in allstats], args.output)


def write_lnt_values(args):
    vargs = vars_of_args(args)
    for d in args.remainder:
        stats = load_stats_dir(d, **vargs)
        merged = merge_all_jobstats(stats, **vargs)
        j = merged.to_lnt_test_obj(args)
        if args.lnt_submit is None:
            json.dump(j, args.output, indent=4)
        else:
            url = args.lnt_submit
            print "\nsubmitting to LNT server: " + url
            json_report = {'input_data': json.dumps(j), 'commit': '1'}
            data = urllib.urlencode(json_report)
            response_str = urllib2.urlopen(urllib2.Request(url, data))
            response = json.loads(response_str.read())
            print "### response:"
            print response
            if 'success' in response:
                print "server response:\tSuccess"
            else:
                print "server response:\tError"
                print "error:\t", response['error']
                sys.exit(1)


def show_paired_incrementality(args):
    fieldnames = ["old_pct", "old_skip",
                  "new_pct", "new_skip",
                  "delta_pct", "delta_skip",
                  "name"]
    out = csv.DictWriter(args.output, fieldnames, dialect='excel-tab')
    out.writeheader()
    vargs = vars_of_args(args)

    for (name, (oldstats, newstats)) in load_paired_stats_dirs(args):
        olddriver = merge_all_jobstats((x for x in oldstats
                                        if x.is_driver_job()), **vargs)
        newdriver = merge_all_jobstats((x for x in newstats
                                        if x.is_driver_job()), **vargs)
        if olddriver is None or newdriver is None:
            continue
        oldpct = olddriver.incrementality_percentage()
        newpct = newdriver.incrementality_percentage()
        deltapct = newpct - oldpct
        oldskip = olddriver.driver_jobs_skipped()
        newskip = newdriver.driver_jobs_skipped()
        deltaskip = newskip - oldskip
        out.writerow(dict(name=name,
                          old_pct=oldpct, old_skip=oldskip,
                          new_pct=newpct, new_skip=newskip,
                          delta_pct=deltapct, delta_skip=deltaskip))


def show_incrementality(args):
    fieldnames = ["incrementality", "name"]
    out = csv.DictWriter(args.output, fieldnames, dialect='excel-tab')
    out.writeheader()

    vargs = vars_of_args(args)
    for path in args.remainder:
        stats = load_stats_dir(path, **vargs)
        for s in stats:
            if s.is_driver_job():
                pct = s.incrementality_percentage()
                out.writerow(dict(name=os.path.basename(path),
                                  incrementality=pct))


def diff_and_pct(old, new):
    if old == 0:
        if new == 0:
            return (0, 0.0)
        else:
            return (new, 100.0)
    delta = (new - old)
    delta_pct = round((float(delta) / float(old)) * 100.0, 2)
    return (delta, delta_pct)


def update_epoch_value(d, name, epoch, value):
    changed = 0
    if name in d:
        (existing_epoch, existing_value) = d[name]
        if existing_epoch > epoch:
            print("note: keeping newer value %d from epoch %d for %s"
                  % (existing_value, existing_epoch, name))
            epoch = existing_epoch
            value = existing_value
        elif existing_value == value:
            epoch = existing_epoch
        else:
            (_, delta_pct) = diff_and_pct(existing_value, value)
            print ("note: changing value %d -> %d (%.2f%%) for %s" %
                   (existing_value, value, delta_pct, name))
            changed = 1
    d[name] = (epoch, value)
    return (epoch, value, changed)


def read_stats_dict_from_csv(f, select_stat=''):
    infieldnames = ["epoch", "name", "value"]
    c = csv.DictReader(f, infieldnames,
                       dialect='excel-tab',
                       quoting=csv.QUOTE_NONNUMERIC)
    d = {}
    sre = re.compile('.*' if len(select_stat) == 0 else
                     '|'.join(select_stat))
    for row in c:
        epoch = int(row["epoch"])
        name = row["name"]
        if sre.search(name) is None:
            continue
        value = int(row["value"])
        update_epoch_value(d, name, epoch, value)
    return d


# The idea here is that a "baseline" is a (tab-separated) CSV file full of
# the counters you want to track, each prefixed by an epoch timestamp of
# the last time the value was reset.
#
# When you set a fresh baseline, all stats in the provided stats dir are
# written to the baseline. When you set against an _existing_ baseline,
# only the counters mentioned in the existing baseline are updated, and
# only if their values differ.
#
# Finally, since it's a line-oriented CSV file, you can put:
#
#    mybaseline.csv merge=union
#
# in your .gitattributes file, and forget about merge conflicts. The reader
# function above will take the later epoch anytime it detects duplicates,
# so union-merging is harmless. Duplicates will be eliminated whenever the
# next baseline-set is done.
def set_csv_baseline(args):
    existing = None
    vargs = vars_of_args(args)
    if os.path.exists(args.set_csv_baseline):
        with open(args.set_csv_baseline, "r") as f:
            ss = vargs['select_stat']
            existing = read_stats_dict_from_csv(f, select_stat=ss)
            print ("updating %d baseline entries in %s" %
                   (len(existing), args.set_csv_baseline))
    else:
        print "making new baseline " + args.set_csv_baseline
    fieldnames = ["epoch", "name", "value"]
    with open(args.set_csv_baseline, "wb") as f:
        out = csv.DictWriter(f, fieldnames, dialect='excel-tab',
                             quoting=csv.QUOTE_NONNUMERIC)
        m = merge_all_jobstats((s for d in args.remainder
                                for s in load_stats_dir(d, **vargs)),
                               **vargs)
        if m is None:
            print "no stats found"
            return 1
        changed = 0
        newepoch = int(time.time())
        for name in sorted(m.stats.keys()):
            epoch = newepoch
            value = m.stats[name]
            if existing is not None:
                if name not in existing:
                    continue
                (epoch, value, chg) = update_epoch_value(existing, name,
                                                         epoch, value)
                changed += chg
            out.writerow(dict(epoch=int(epoch),
                              name=name,
                              value=int(value)))
        if existing is not None:
            print "changed %d entries in baseline" % changed
    return 0


OutputRow = namedtuple("OutputRow",
                       ["name", "old", "new",
                        "delta", "delta_pct"])


def compare_stats(args, old_stats, new_stats):
    for name in sorted(old_stats.keys()):
        old = old_stats[name]
        new = new_stats.get(name, 0)
        (delta, delta_pct) = diff_and_pct(old, new)
        yield OutputRow(name=name,
                        old=int(old), new=int(new),
                        delta=int(delta),
                        delta_pct=delta_pct)


IMPROVED = -1
UNCHANGED = 0
REGRESSED = 1


def row_state(row, args):
    delta_pct_over_thresh = abs(row.delta_pct) > args.delta_pct_thresh
    if (row.name.startswith("time.") or '.time.' in row.name):
        # Timers are judged as changing if they exceed
        # the percentage _and_ absolute-time thresholds
        delta_usec_over_thresh = abs(row.delta) > args.delta_usec_thresh
        if delta_pct_over_thresh and delta_usec_over_thresh:
            return (REGRESSED if row.delta > 0 else IMPROVED)
    elif delta_pct_over_thresh:
        return (REGRESSED if row.delta > 0 else IMPROVED)
    return UNCHANGED


def write_comparison(args, old_stats, new_stats):
    rows = list(compare_stats(args, old_stats, new_stats))
    sort_key = (attrgetter('delta_pct')
                if args.sort_by_delta_pct
                else attrgetter('name'))

    regressed = [r for r in rows if row_state(r, args) == REGRESSED]
    unchanged = [r for r in rows if row_state(r, args) == UNCHANGED]
    improved = [r for r in rows if row_state(r, args) == IMPROVED]
    regressions = len(regressed)

    if args.markdown:

        def format_time(v):
            if abs(v) > 1000000:
                return "{:.1f}s".format(v / 1000000.0)
            elif abs(v) > 1000:
                return "{:.1f}ms".format(v / 1000.0)
            else:
                return "{:.1f}us".format(v)

        def format_field(field, row):
            if field == 'name':
                if args.group_by_module:
                    return stat_name_minus_module(row.name)
                else:
                    return row.name
            elif field == 'delta_pct':
                s = str(row.delta_pct) + "%"
                if args.github_emoji:
                    if row_state(row, args) == REGRESSED:
                        s += " :no_entry:"
                    elif row_state(row, args) == IMPROVED:
                        s += " :white_check_mark:"
                return s
            else:
                v = int(vars(row)[field])
                if row.name.startswith('time.'):
                    return format_time(v)
                else:
                    return "{:,d}".format(v)

        def format_table(elts):
            out = args.output
            out.write('\n')
            out.write(' | '.join(OutputRow._fields))
            out.write('\n')
            out.write(' | '.join('---:' for _ in OutputRow._fields))
            out.write('\n')
            for e in elts:
                out.write(' | '.join(format_field(f, e)
                                     for f in OutputRow._fields))
                out.write('\n')

        def format_details(name, elts, is_closed):
            out = args.output
            details = '<details>\n' if is_closed else '<details open>\n'
            out.write(details)
            out.write('<summary>%s (%d)</summary>\n'
                      % (name, len(elts)))
            if args.group_by_module:
                def keyfunc(e):
                    return module_name_of_stat(e.name)
                elts.sort(key=attrgetter('name'))
                for mod, group in itertools.groupby(elts, keyfunc):
                    groupelts = list(group)
                    groupelts.sort(key=sort_key, reverse=args.sort_descending)
                    out.write(details)
                    out.write('<summary>%s in %s (%d)</summary>\n'
                              % (name, mod, len(groupelts)))
                    format_table(groupelts)
                    out.write('</details>\n')
            else:
                elts.sort(key=sort_key, reverse=args.sort_descending)
                format_table(elts)
            out.write('</details>\n')

        closed_regressions = (args.close_regressions or len(regressed) == 0)
        format_details('Regressed', regressed, closed_regressions)
        format_details('Improved', improved, True)
        format_details('Unchanged (delta < %s%% or delta < %s)' %
                       (args.delta_pct_thresh,
                        format_time(args.delta_usec_thresh)),
                       unchanged, True)

    else:
        rows.sort(key=sort_key, reverse=args.sort_descending)
        out = csv.DictWriter(args.output, OutputRow._fields,
                             dialect='excel-tab')
        out.writeheader()
        for row in rows:
            if row_state(row, args) != UNCHANGED:
                out.writerow(row._asdict())

    return regressions


def compare_to_csv_baseline(args):
    vargs = vars_of_args(args)
    old_stats = read_stats_dict_from_csv(args.compare_to_csv_baseline,
                                         select_stat=vargs['select_stat'])
    m = merge_all_jobstats((s for d in args.remainder
                            for s in load_stats_dir(d, **vargs)),
                           **vargs)
    old_stats = dict((k, v) for (k, (_, v)) in old_stats.items())
    new_stats = m.stats

    return write_comparison(args, old_stats, new_stats)


# Summarize immediate difference between two stats-dirs, optionally
def compare_stats_dirs(args):
    if len(args.remainder) != 2:
        raise ValueError("Expected exactly 2 stats-dirs")

    vargs = vars_of_args(args)
    (old, new) = args.remainder
    old_stats = merge_all_jobstats(load_stats_dir(old, **vargs), **vargs)
    new_stats = merge_all_jobstats(load_stats_dir(new, **vargs), **vargs)

    return write_comparison(args, old_stats.stats, new_stats.stats)


# Evaluate a boolean expression in terms of the provided stats-dir; all stats
# are projected into python dicts (thus variables in the eval expr) named by
# the last identifier in the stat definition. This means you can evaluate
# things like 'NumIRInsts < 1000' or
# 'NumTypesValidated == NumTypesDeserialized'
def evaluate(args):
    if len(args.remainder) != 1:
        raise ValueError("Expected exactly 1 stats-dir to evaluate against")

    d = args.remainder[0]
    vargs = vars_of_args(args)
    merged = merge_all_jobstats(load_stats_dir(d, **vargs), **vargs)
    env = {}
    ident = re.compile('(\w+)$')
    for (k, v) in merged.stats.items():
        if k.startswith("time.") or '.time.' in k:
            continue
        m = re.search(ident, k)
        if m:
            i = m.groups()[0]
            if args.verbose:
                print("%s => %s" % (i, v))
            env[i] = v
    try:
        if eval(args.evaluate, env):
            return 0
        else:
            print("evaluate condition failed: '%s'" % args.evaluate)
            return 1
    except Exception as e:
        print(e)
        return 1


# Evaluate a boolean expression in terms of deltas between the provided two
# stats-dirs; works like evaluate() above but on absolute differences
def evaluate_delta(args):
    if len(args.remainder) != 2:
        raise ValueError("Expected exactly 2 stats-dirs to evaluate-delta")

    (old, new) = args.remainder
    vargs = vars_of_args(args)
    old_stats = merge_all_jobstats(load_stats_dir(old, **vargs), **vargs)
    new_stats = merge_all_jobstats(load_stats_dir(new, **vargs), **vargs)

    env = {}
    ident = re.compile('(\w+)$')
    for r in compare_stats(args, old_stats.stats, new_stats.stats):
        if r.name.startswith("time.") or '.time.' in r.name:
            continue
        m = re.search(ident, r.name)
        if m:
            i = m.groups()[0]
            if args.verbose:
                print("%s => %s" % (i, r.delta))
            env[i] = r.delta
    try:
        if eval(args.evaluate_delta, env):
            return 0
        else:
            print("evaluate-delta condition failed: '%s'" %
                  args.evaluate_delta)
            return 1
    except Exception as e:
        print(e)
        return 1


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--verbose", action="store_true",
                        help="Report activity verbosely")
    parser.add_argument("--output", default="-",
                        type=argparse.FileType('wb', 0),
                        help="Write output to file")
    parser.add_argument("--paired", action="store_true",
                        help="Process two dirs-of-stats-dirs, pairwise")
    parser.add_argument("--delta-pct-thresh", type=float, default=0.01,
                        help="Percentage change required to report")
    parser.add_argument("--delta-usec-thresh", type=int, default=100000,
                        help="Absolute delta on times required to report")
    parser.add_argument("--lnt-machine", type=str, default=platform.node(),
                        help="Machine name for LNT submission")
    parser.add_argument("--lnt-run-info", action='append', default=[],
                        type=lambda kv: kv.split("="),
                        help="Extra key=value pairs for LNT run-info")
    parser.add_argument("--lnt-machine-info", action='append', default=[],
                        type=lambda kv: kv.split("="),
                        help="Extra key=value pairs for LNT machine-info")
    parser.add_argument("--lnt-order", type=str,
                        default=str(int(time.time())),
                        help="Order for LNT submission")
    parser.add_argument("--lnt-tag", type=str, default="swift-compile",
                        help="Tag for LNT submission")
    parser.add_argument("--lnt-submit", type=str, default=None,
                        help="URL to submit LNT data to (rather than print)")
    parser.add_argument("--select-module",
                        default=[],
                        action="append",
                        help="Select specific modules")
    parser.add_argument("--group-by-module",
                        default=False,
                        action="store_true",
                        help="Group stats by module")
    parser.add_argument("--select-stat",
                        default=[],
                        action="append",
                        help="Select specific statistics")
    parser.add_argument("--select-stats-from-csv-baseline",
                        type=argparse.FileType('rb', 0), default=None,
                        help="Select statistics present in a CSV baseline")
    parser.add_argument("--exclude-timers",
                        default=False,
                        action="store_true",
                        help="only select counters, exclude timers")
    parser.add_argument("--sort-by-delta-pct",
                        default=False,
                        action="store_true",
                        help="Sort comparison results by delta-%%, not stat")
    parser.add_argument("--sort-descending",
                        default=False,
                        action="store_true",
                        help="Sort comparison results in descending order")
    parser.add_argument("--merge-by",
                        default="sum",
                        type=str,
                        help="Merge identical metrics by (sum|min|max)")
    parser.add_argument("--merge-timers",
                        default=False,
                        action="store_true",
                        help="Merge timers across modules/targets/etc.")
    parser.add_argument("--divide-by",
                        default=1,
                        metavar="D",
                        type=int,
                        help="Divide stats by D (to take an average)")
    parser.add_argument("--markdown",
                        default=False,
                        action="store_true",
                        help="Write output in markdown table format")
    parser.add_argument("--include-unchanged",
                        default=False,
                        action="store_true",
                        help="Include unchanged stats values in comparison")
    parser.add_argument("--close-regressions",
                        default=False,
                        action="store_true",
                        help="Close regression details in markdown")
    parser.add_argument("--github-emoji",
                        default=False,
                        action="store_true",
                        help="Add github-emoji indicators to markdown")
    modes = parser.add_mutually_exclusive_group(required=True)
    modes.add_argument("--catapult", action="store_true",
                       help="emit a 'catapult'-compatible trace of events")
    modes.add_argument("--incrementality", action="store_true",
                       help="summarize the 'incrementality' of a build")
    modes.add_argument("--set-csv-baseline", type=str, default=None,
                       help="Merge stats from a stats-dir into a CSV baseline")
    modes.add_argument("--compare-to-csv-baseline",
                       type=argparse.FileType('rb', 0), default=None,
                       metavar="BASELINE.csv",
                       help="Compare stats dir to named CSV baseline")
    modes.add_argument("--compare-stats-dirs",
                       action="store_true",
                       help="Compare two stats dirs directly")
    modes.add_argument("--lnt", action="store_true",
                       help="Emit an LNT-compatible test summary")
    modes.add_argument("--evaluate", type=str, default=None,
                       help="evaluate an expression of stat-names")
    modes.add_argument("--evaluate-delta", type=str, default=None,
                       help="evaluate an expression of stat-deltas")
    parser.add_argument('remainder', nargs=argparse.REMAINDER,
                        help="stats-dirs to process")

    args = parser.parse_args()
    if len(args.remainder) == 0:
        parser.print_help()
        return 1
    if args.catapult:
        write_catapult_trace(args)
    elif args.compare_stats_dirs:
        return compare_stats_dirs(args)
    elif args.set_csv_baseline is not None:
        return set_csv_baseline(args)
    elif args.compare_to_csv_baseline is not None:
        return compare_to_csv_baseline(args)
    elif args.incrementality:
        if args.paired:
            show_paired_incrementality(args)
        else:
            show_incrementality(args)
    elif args.lnt:
        write_lnt_values(args)
    elif args.evaluate:
        return evaluate(args)
    elif args.evaluate_delta:
        return evaluate_delta(args)
    return None


sys.exit(main())
