#!/usr/bin/env python3
# Copyright 2020 The Fuchsia 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 argparse
import concurrent.futures
import csv
import json
import logging
import os
import pathlib
import re
import shutil
import subprocess
import sys
from urllib import parse


class StepInfo:
    ABOUT_COLUMNS = (
        "step_name",
        "mem_bytes_inc",
        "mem_bytes_net",
        "top_mem_type",
        "bottom_mem_type",
        "num_objects_inc",
        "num_objects_net",
    )
    # 3 columns separated by " | ".
    _TABLE_ROW_PAT = re.compile(r"([^|]+) \| ([^|]+) \| ([^|]+)$")
    _UNIT_TO_MULTIPLE = {"B": 1, "KB": 1 << 10, "MB": 1 << 20, "GB": 1 << 30}

    def __init__(self, src_path: str):
        self.src_path = src_path.lstrip("/")
        self.step_name = os.path.dirname(src_path.split("/+/u/")[1])
        self.debug_log = None

    def download_log(self):
        self.debug_log = subprocess.check_output(
            ("logdog", "-host", "logs.chromium.org", "cat", self.src_path),
            encoding="utf-8",
        )

    def about(self):
        mem_inc, mem_net = float(0), float(0)
        top_mem_type, bottom_mem_type = ("", 0), ("", 0)
        obj_inc, obj_net = 0, 0
        for line in self.debug_log.split("\n"):
            # Optimization to exit early.
            # This is printed at the end of the memory snapshot.
            if line.endswith("Ends --------"):
                break

            match = self._TABLE_ROW_PAT.match(line)
            if not match:
                continue
            type_name, num_objs, mem = line.split(" | ")
            try:
                num_objs = int(num_objs)
            except ValueError:
                continue

            if num_objs > 0:
                obj_inc += num_objs
            obj_net += num_objs
            mem_magnitude, mem_unit = mem.split()
            num_bytes = float(mem_magnitude) * self._UNIT_TO_MULTIPLE[mem_unit]
            mem_net += num_bytes
            if num_bytes > 0:
                mem_inc += num_bytes

            type_name = type_name.strip()
            if num_bytes > top_mem_type[1]:
                top_mem_type = type_name, num_bytes
            if num_bytes < bottom_mem_type[1]:
                bottom_mem_type = type_name, num_bytes

        return (
            self.step_name,
            str(mem_inc),
            str(mem_net),
            top_mem_type[0],
            bottom_mem_type[0],
            str(obj_inc),
            str(obj_net),
        )


parser = argparse.ArgumentParser()
parser.add_argument("build_url", help="Milo URL for the build of interest")
parser.add_argument("-o", "--output", help="path to which the output will be written")


def main():
    logging.basicConfig(stream=sys.stderr, level=logging.INFO)

    args = parser.parse_args()

    build_url = args.build_url

    if not shutil.which("logdog"):
        sys.exit("logdog not found in $PATH")
    if not shutil.which("bb"):
        sys.exit("bb not found in $PATH")

    build_url_parsed = parse.urlparse(build_url)
    build_id = pathlib.PurePosixPath(build_url_parsed.path).name.lstrip("b")
    logging.info("Getting build %s", build_id)
    build_dict = json.loads(
        subprocess.check_output(
            ("bb", "get", "-json", "-steps", "-p", build_id), encoding="utf-8"
        )
    )
    if (
        not build_dict["input"]["properties"]
        .get("$recipe_engine", {})
        .get("memory_profiler", {})
        .get("enable_snapshot")
    ):
        sys.exit(
            "Build %s does not have memory profiling enabled. See "
            "https://chromium.googlesource.com/infra/luci/recipes-py/+/HEAD/doc/"
            "user_guide.md#memory-leak" % build_url
        )

    step_infos = []
    for step_d in build_dict["steps"]:
        for log_d in step_d.get("logs", ()):
            if log_d["name"] == "$debug":
                step_infos.append(StepInfo(parse.urlparse(log_d["url"]).path))
                break

    logging.info("Downloading debug logs")
    executor = concurrent.futures.ThreadPoolExecutor()
    completed_procs = []
    for step_info in step_infos:
        completed_procs.append(executor.submit(step_info.download_log))
    executor.shutdown(wait=True)
    for cp in completed_procs:
        cp.result()  # Raise any errors.

    logging.info("Writing summary to %s", args.output)
    with open(args.output, "w", encoding="utf-8") as summary_f:
        writer = csv.writer(summary_f)
        writer.writerow(StepInfo.ABOUT_COLUMNS)
        for step_info in step_infos:
            writer.writerow(step_info.about())


if __name__ == "__main__":
    main()
