ClickHouse/utils/tests-visualizer/index.html

201 lines
5.5 KiB
HTML
Raw Normal View History

2022-01-06 21:35:02 +00:00
<html id="html">
<head>
<meta charset="UTF-8">
2022-01-06 21:35:02 +00:00
<style>
body {
color: white;
background: black;
font-family: sans-serif;
}
#loading {
margin-top: 1em;
}
#loading img {
width: 130px;
display: block;
margin: 30px auto;
-webkit-animation: spin 2s ease-in-out infinite;
-moz-animation: spin 2s ease-in-out infinite;
animation: spin 2s ease-in-out infinite;
}
#loading h1 {
text-align: center;
}
#info {
position: sticky;
top: 1rem;
z-index: 1;
margin: 1rem;
float: right;
font-size: 16pt;
padding: 0.5rem;
border: 1px solid #111;
border-radius: 10px;
box-shadow: white 5px 5px 28px -10px;
display: none;
}
canvas {
position: absolute;
cursor: pointer;
}
@-moz-keyframes spin {
100% { -moz-transform: rotate(360deg); }
}
@-webkit-keyframes spin {
100% { -webkit-transform: rotate(360deg); }
}
@keyframes spin {
100% { transform:rotate(360deg); }
}
</style>
</head>
2022-01-06 21:35:02 +00:00
<body>
<div id="loading">
<img src="https://clickhouse.com/images/logo.svg">
<h1>Loading (~10 seconds, try load ~20 MB)</h1>
</div>
<pre id="info"></pre>
<canvas id="canvas"></canvas>
<script type="text/javascript">
2022-01-06 21:35:02 +00:00
///////////////////////
// GLOBAL VARIABLES
///////////////////////
let start_date = '2020-06-13';
2022-01-06 21:35:02 +00:00
const canvasNode = document.getElementById('canvas');
const infoNode = document.getElementById('info');
const loadingNode = document.getElementById('loading');
///////////////////////
// QUERIES
///////////////////////
let render_data_query = `
WITH '${start_date}'::Date AS start_date
SELECT groupArray([d, n, fail]) FROM
(
SELECT n, check_start_time::Date - start_date AS d, max(test_status LIKE 'F%' OR test_status LIKE 'E%') AS fail
FROM "gh-data".checks
INNER JOIN
(
SELECT test_name, toUInt16(rowNumberInAllBlocks()) AS n FROM
(
SELECT DISTINCT test_name
FROM "gh-data".checks
WHERE match(test_name, '^\\d+_') AND check_name ILIKE '%stateless%' AND check_start_time > now() - INTERVAL 1 DAY
ORDER BY test_name
)
) AS nums
USING (test_name)
WHERE
check_name ILIKE '%stateless%'
AND pull_request_number = 0
AND check_start_time >= start_date
GROUP BY d, n
ORDER BY d, n
)
FORMAT TSV`;
2022-01-06 21:35:02 +00:00
let test_names_query = `
SELECT test_name, toUInt16(rowNumberInAllBlocks()) AS n FROM
(
SELECT DISTINCT test_name
FROM "gh-data".checks
WHERE match(test_name, '^\\d+_') AND check_name ILIKE '%stateless%' AND check_start_time > now() - INTERVAL 1 DAY
ORDER BY test_name
) FORMAT JSONCompact`
///////////////////////
// MAIN
///////////////////////
Promise.all([
invokeCbWithDataByQuery(render_data_query, renderResponse),
invokeCbWithDataByQuery(test_names_query, saveTestNames),
])
.then(hideLoader)
.catch(alert);
///////////////////////
// SPECIAL FUNCTIONS
///////////////////////
async function invokeCbWithDataByQuery(query, callback) {
data = await loadDataByQuery(query);
callback(data);
}
async function loadDataByQuery(query) {
const response = await fetch(
"https://play-ci.clickhouse.com?user=play&add_http_cors_header=1",
{ method: "POST", body: query }
)
2022-01-06 21:35:02 +00:00
if (!response.ok) throw new Error(`Data download failed\nHTTP status ${response.status}`);
const json = await response.json();
return json;
}
2022-01-06 21:35:02 +00:00
function renderResponse(data) {
const last_pixel = data[data.length - 1];
2022-01-06 21:35:02 +00:00
canvasNode.width = last_pixel[0] + 1;
canvasNode.height = last_pixel[1] + 1;
2022-01-06 21:35:02 +00:00
document.getElementById('html').style.height = canvasNode.height + 10 + 'px';
document.body.style.height = canvasNode.height + 10 + 'px';
2022-01-06 21:35:02 +00:00
let ctx = canvasNode.getContext('2d');
let image = ctx.createImageData(canvasNode.width, canvasNode.height);
let {data: pixels} = image;
data.map(elem => {
let x = elem[0];
2022-01-06 21:35:02 +00:00
let y = canvasNode.height - elem[1];
2022-01-06 21:35:02 +00:00
pixels[(x + y * canvasNode.width) * 4 + 0] = elem[2] ? 255 : 0; // r
pixels[(x + y * canvasNode.width) * 4 + 1] = elem[2] ? 0 : 100; // g
pixels[(x + y * canvasNode.width) * 4 + 2] = 0; // b
pixels[(x + y * canvasNode.width) * 4 + 3] = 255; // a
});
ctx.putImageData(image, 0, 0);
}
2022-01-06 21:35:02 +00:00
function saveTestNames(data) {
let {data: test_names} = data;
infoNode.style.display = 'block';
2022-01-06 21:35:02 +00:00
canvasNode.addEventListener('mousemove', (event) => {
const x = event.layerX;
const y = event.layerY;
2022-01-06 21:35:02 +00:00
let date = new Date(start_date);
date.setDate(date.getDate() + x);
[date] = date.toISOString().split('T');
let [test] = test_names[canvasNode.height - y];
let {data: pixel} = canvasNode.getContext('2d').getImageData(x, y, 1, 1);
updateInfo(date, test, pixel);
})
}
2022-01-06 21:35:02 +00:00
function updateInfo(date, test, pixel) {
infoNode.innerText = `${date}, ${test}`;
infoNode.style.background = pixel[0] > 0 ? '#F00' : (pixel[3] > 0 ? '#006400' : '#000');
}
2022-01-06 21:35:02 +00:00
function hideLoader() {
loadingNode.style.display = 'none';
}
</script>
</body>
</html>