<!--
Copyright 2022 The Go Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
-->

<!DOCTYPE html>
<html lang="en">
<head>
	<title>Go Performance Dashboard</title>
	<link rel="icon" href="https://go.dev/favicon.ico"/>
	<link rel="stylesheet" href="./static/style.css"/>
	<script src="https://ajax.googleapis.com/ajax/libs/d3js/7.4.2/d3.min.js"></script>
	<script src="./third_party/bandchart/bandchart.js"></script>
</head>

<body class="Dashboard">
<header class="Dashboard-topbar">
	<h1>
		<a href="https://farmer.golang.org/">Go Build Coordinator</a>
	</h1>
	<nav>
		<ul>
			<li><a href="https://build.golang.org/">Build Dashboard</a></li>
			<li><a href="/dashboard">Performance Dashboard</a></li>
			<li><a href="https://farmer.golang.org/builders">Builders</a></li>
		</ul>
	</nav>
</header>

<nav class="Dashboard-controls">
	<form autocomplete="off" action="./">
		<ul>
			<li>
				<div class="Dashboard-search">
					<input id="benchmark-input" type="text" name="benchmark" placeholder="Type benchmark name..." />
				</div>
				<input type="submit" />
			</li>
			<li><a href="?benchmark=all">All benchmarks</a></li>
			<li><a href="?benchmark=regressions">Regressions first</a></li>
			<span class="left-separator"></span>
			<li>
				Repository:
				<select id="repository-select" name="repository">
					<option>go</option>
					<option>tools</option>
				</select>
				Duration (days):
				<div class="Dashboard-duration">
					<input id="days-input" type="number" name="days" value="30" />
				</div>
				End (UTC): <input id="end-input" type="datetime-local" name="end" />
				<input type="submit">
			</li>
		</ul>
	</form>
</nav>

<div class="Dashboard-documentation">
	<p>
		Each graph displays benchmark results relative to its baseline
		commit, which is the latest stable release (e.g., 1.18.3) at
		the time of testing. The 95% confidence interval is displayed
		in light gray. On hover, the graph displays the benchmarked
		commit at that point (click to view full commit).
	</p>
	<p>
		Note that some commits are not tested, so there could be
		multiple commits (not shown) between two points on the graph.
		See the <code>linux-amd64-perf</code> column on the
		<a href="https://build.golang.org/?repo=golang.org%2fx%2fbenchmarks">x/benchmarks build dashboard</a>
		for tested ("ok") / untested (empty) commits.
	</p>
</div>

<div id="dashboard">
	<h2 class="Dashboard-title" id="loading">Loading...</h2>
</div>

<script>
function removeLoadingMessage() {
	let loading = document.getElementById("loading");
	loading.parentNode.removeChild(loading);
}

function addContent(benchmarks) {
	let dashboard = document.getElementById("dashboard");

	removeLoadingMessage();

	let prevName = "";
	let grid = null;
	for (const b in benchmarks) {
		const bench = benchmarks[b];

		if (bench.Name != prevName) {
			prevName = bench.Name;

			let link = document.createElement("a");
			link.href = "?benchmark=" + bench.Name;
			link.textContent = bench.Name;

			let title = document.createElement("h2");
			title.classList.add("Dashboard-title");
			title.appendChild(link);
			dashboard.appendChild(title);

			grid = document.createElement("grid");
			grid.classList.add("Dashboard-grid");
			dashboard.appendChild(grid);
		}

		let item = document.createElement("div");
		item.classList.add("Dashboard-grid-item");
		item.appendChild(BandChart(bench.Values, {
			unit: bench.Unit,
		}));
		grid.appendChild(item);
	}
}

function failure(name, response) {
	let dashboard = document.getElementById("dashboard");

	removeLoadingMessage();

	let title = document.createElement("h2");
	title.classList.add("Dashboard-title");
	title.textContent = "Benchmark \"" + name + "\" not found.";
	dashboard.appendChild(title);

	let message = document.createElement("p");
	message.classList.add("Dashboard-documentation");
	response.text().then(function(error) {
		message.textContent = error;
	});
	dashboard.appendChild(message);
}

// Fill search boxes from query params.
function prefillSearch() {
	let params = new URLSearchParams(window.location.search);

	let benchmark = params.get('benchmark');
	if (benchmark) {
		let input = document.getElementById('benchmark-input');
		input.value = benchmark;
	}

	let repository = params.get('repository');
	if (repository) {
		let select = document.getElementById('repository-select');
		select.value = repository;
	}

	let days = params.get('days');
	if (days) {
		let input = document.getElementById('days-input');
		input.value = days;
	}

	let end = params.get('end');
	let input = document.getElementById('end-input');
	if (end) {
		input.value = end;
	} else {
		// Default to now.
		let now = new Date();

		// toISOString always uses UTC, then we just chop off the end
		// of string to get the datetime-local format of
		// 2000-12-31T15:00.
		//
		// Yes, this is really the suggested approach...
		input.value = now.toISOString().slice(0, 16);
	}
}
prefillSearch()

// Fetch content.
let benchmark = (new URLSearchParams(window.location.search)).get('benchmark');
let dataURL = './data.json' + window.location.search;  // Pass through all URL params.
fetch(dataURL)
	.then(response => {
		if (!response.ok) {
			failure(benchmark, response);
			throw new Error("Data fetch failed");
		}
		return response.json();
	})
	.then(function(benchmarks) {
		// Convert CommitDate to a proper date.
		benchmarks.forEach(function(b) {
			b.Values.forEach(function(v) {
				v.CommitDate = new Date(v.CommitDate);
			});
		});

		addContent(benchmarks);
	});
</script>

</body>
</html>
