summary refs log tree commit diff
path: root/src/ci/scripts/upload-build-metrics.py
blob: a95e0949d700aaee8c31c6033c6999dbc57eb738 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
"""
This script postprocesses data gathered during a CI run, computes certain metrics
from them, and uploads these metrics to DataDog.

This script is expected to be executed from within a GitHub Actions job.

It expects the following environment variables:
- DATADOG_SITE: path to the DataDog API endpoint
- DATADOG_API_KEY: DataDog API token
- DD_GITHUB_JOB_NAME: Name of the current GitHub Actions job

And it also expects the presence of a binary called `datadog-ci` to be in PATH.
It can be installed with `npm install -g @datadog/datadog-ci`.

Usage:
```bash
$ python3 upload-build-metrics.py <path-to-CPU-usage-CSV>
```

`path-to-CPU-usage-CSV` is a path to a CSV generated by the `src/ci/cpu-usage-over-time.py` script.
"""
import argparse
import csv
import os
import subprocess
import sys
from pathlib import Path
from typing import List


def load_cpu_usage(path: Path) -> List[float]:
    usage = []
    with open(path) as f:
        reader = csv.reader(f, delimiter=',')
        for row in reader:
            # The log might contain incomplete rows or some Python exception
            if len(row) == 2:
                try:
                    idle = float(row[1])
                    usage.append(100.0 - idle)
                except ValueError:
                    pass
    return usage


def upload_datadog_measure(name: str, value: float):
    """
    Uploads a single numeric metric for the current GitHub Actions job to DataDog.
    """
    print(f"Metric {name}: {value:.4f}")

    datadog_cmd = "datadog-ci"
    if os.getenv("GITHUB_ACTIONS") is not None and sys.platform.lower().startswith("win"):
        # Due to weird interaction of MSYS2 and Python, we need to use an absolute path,
        # and also specify the ".cmd" at the end. See https://github.com/rust-lang/rust/pull/125771.
        datadog_cmd = "C:\\npm\\prefix\\datadog-ci.cmd"

    subprocess.run([
        datadog_cmd,
        "measure",
        "--level", "job",
        "--measures", f"{name}:{value}"
    ],
        check=False
    )


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        prog="DataDog metric uploader"
    )
    parser.add_argument("cpu-usage-history-csv")
    args = parser.parse_args()

    build_usage_csv = vars(args)["cpu-usage-history-csv"]
    usage_timeseries = load_cpu_usage(Path(build_usage_csv))
    if len(usage_timeseries) > 0:
        avg_cpu_usage = sum(usage_timeseries) / len(usage_timeseries)
    else:
        avg_cpu_usage = 0
    upload_datadog_measure("avg-cpu-usage", avg_cpu_usage)