<!--
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>
				Branch:
				<select id="branch-select" name="branch">
					<option>master</option>
					<option>release-branch.go1.17</option>
					<option>release-branch.go1.18</option>
					<option>release-branch.go1.19</option>
					<option>release-branch.go1.20</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>
	<p>
		Also note that the 'branch' selection above is the Go branch
		that benchmarking ran against on https://build.golang.org, not
		the subrepo branch.
	</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 branch = params.get('branch');
	if (branch) {
		let select = document.getElementById('branch-select');
		select.value = branch;
	}

	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>
