231 lines
7.4 KiB
Cheetah
231 lines
7.4 KiB
Cheetah
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/water.css">
|
|
<script src="https://code.highcharts.com/10/highcharts.js"></script>
|
|
<script type="module">
|
|
const allMessages = {{ json "Marshal" .messages }};
|
|
|
|
function fillForm() {
|
|
const filterableFields = [
|
|
"Asset",
|
|
"Channel",
|
|
"Event",
|
|
"EventName",
|
|
"Resolved",
|
|
"Thread",
|
|
];
|
|
const fieldsToOptions = {};
|
|
filterableFields.map((field) => {fieldsToOptions[field] = {}});
|
|
allMessages.map((message) => {
|
|
Object.keys(fieldsToOptions).map((field) => {fieldsToOptions[field][message[field]] = true});
|
|
});
|
|
Object.keys(fieldsToOptions).map((field) => {fieldsToOptions[field] = Object.keys(fieldsToOptions[field]); fieldsToOptions[field].sort();});
|
|
|
|
document.getElementById("form").innerHTML = Object.keys(fieldsToOptions).map((field) => {
|
|
return `
|
|
<label for="${field}">${field}</label>
|
|
<select name="${field}" multiple ${fieldsToOptions[field].length > 10 ? "size=10" : `size=${fieldsToOptions[field].length}`}>
|
|
${fieldsToOptions[field].map((option) => `
|
|
<option selected>${option}</option>
|
|
`)}
|
|
</select>
|
|
`
|
|
}).join("\n");
|
|
}
|
|
window.fillForm = fillForm;
|
|
|
|
function drawAll() {
|
|
const messages = filterMessages(allMessages)
|
|
|
|
dumpEvents(messages);
|
|
drawEventVolumeByName(messages)
|
|
drawEventVolumeByWeekday(messages)
|
|
drawEventVolumeByHour(messages)
|
|
drawEventVolumeByAsset(messages)
|
|
}
|
|
window.drawAll = drawAll;
|
|
|
|
function dumpEvents(messages) {
|
|
const eventToThreads = {};
|
|
for(var m of messages) {
|
|
if (!eventToThreads[m.Event])
|
|
eventToThreads[m.Event] = [];
|
|
eventToThreads[m.Event].push(m.Thread);
|
|
}
|
|
|
|
const threadToMessages = {};
|
|
for(var m of messages) {
|
|
if (!threadToMessages[m.Thread])
|
|
threadToMessages[m.Thread] = [];
|
|
threadToMessages[m.Thread].push(m);
|
|
}
|
|
|
|
const eventToMessages = {};
|
|
for(var e in eventToThreads) {
|
|
if (!eventToMessages[e])
|
|
eventToMessages[e] = [];
|
|
for (var thread of eventToThreads[e])
|
|
eventToMessages[e] = eventToMessages[e].concat(threadToMessages[thread]);
|
|
}
|
|
for(var e in eventToMessages)
|
|
eventToMessages[e].sort((a, b) => a.TS - b.TS);
|
|
var events = Object.keys(eventToMessages);
|
|
events.sort();
|
|
events.reverse();
|
|
|
|
var keys = ["TS", "Event", "EventName", "Latest"];
|
|
document.getElementById("events").innerHTML = `
|
|
<tr>
|
|
<th>TS</th>
|
|
<th>Event</th>
|
|
<th>EventName</th>
|
|
<th>Latest</th>
|
|
</tr>
|
|
${events.map((e) => `
|
|
<tr>
|
|
<td><a href="${eventToMessages[e][0].Source}">${new Date(eventToMessages[e][0].TS * 1000).toDateString()}</a></td>
|
|
<td><a href="${eventToMessages[e][0].Source}">${eventToMessages[e][0].Event}</a></td>
|
|
<td>${eventToMessages[e][0].EventName}</td>
|
|
<td><a href="${eventToMessages[e].at(-1).Source}">${eventToMessages[e].at(-1).Plaintext}</a></td>
|
|
</tr>
|
|
`).join("")}
|
|
`;
|
|
}
|
|
|
|
function filterMessages(messages) {
|
|
const selects = document.getElementById("form").getElementsByTagName("select");
|
|
const fieldsToOptions = {};
|
|
for(var select of selects) {
|
|
fieldsToOptions[select.name] = [];
|
|
for(var option of select.getElementsByTagName("option"))
|
|
if (option.selected)
|
|
fieldsToOptions[select.name].push(option.innerHTML);
|
|
}
|
|
return messages.map((m) => {
|
|
for(var k in fieldsToOptions) {
|
|
if (fieldsToOptions[k].filter((v) => `${v}` == `${m[k]}`).length == 0) {
|
|
return null;
|
|
}
|
|
}
|
|
return m;
|
|
}).filter((m) => { return m != null });
|
|
}
|
|
|
|
function drawEventVolumeByName(messages) {}
|
|
|
|
function drawEventVolumeByWeekday(messages) {
|
|
var prettyWeekday = (d) => {
|
|
switch (d%7) {
|
|
case 0: return "Sun";
|
|
case 1: return "Mon";
|
|
case 2: return "Tue";
|
|
case 3: return "Wed";
|
|
case 4: return "Thu";
|
|
case 5: return "Fri";
|
|
case 6: return "Sat";
|
|
}
|
|
};
|
|
var byWeekday = [];
|
|
for(var i = 0; i < 7; i++)
|
|
byWeekday.push(0);
|
|
for(var m of messages) {
|
|
var d = new Date(1000 * m.TS);
|
|
byWeekday[d.getDay()] += 1;
|
|
}
|
|
byWeekday = byWeekday.map((cnt, idx) => {
|
|
return {x: prettyWeekday(idx), y: cnt};
|
|
});
|
|
|
|
draw("eventVolumeByWeekday", byWeekday);
|
|
}
|
|
|
|
function drawEventVolumeByHour(messages) {
|
|
var byHour = [];
|
|
for(var i = 0; i < 24; i++)
|
|
byHour.push(0);
|
|
for(var m of messages) {
|
|
var d = new Date(1000 * m.TS);
|
|
byHour[d.getHours()] += 1;
|
|
}
|
|
byHour = byHour.map((cnt, idx) => {
|
|
return {x: idx, y: cnt};
|
|
});
|
|
|
|
draw("eventVolumeByHour", byHour);
|
|
}
|
|
|
|
function drawEventVolumeByAsset(messages) {}
|
|
|
|
function draw(id, points) {
|
|
document.getElementById(id).innerHTML = "";
|
|
Highcharts.chart(id, {
|
|
chart: { type: 'column' },
|
|
title: { text: '' },
|
|
xAxis: { categories: points.map((point) => `${point.x}`) },
|
|
yAxis: { allowDecimals: false, title: { text: '' } },
|
|
legend: { enabled: false },
|
|
series: [{data: points.map((point) => point.y) }],
|
|
plotOptions: { column: { stacking: 'normal' } },
|
|
});
|
|
}
|
|
</script>
|
|
<style>
|
|
rows {
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex-grow: 1;
|
|
}
|
|
columns {
|
|
display: flex;
|
|
flex-direction: row;
|
|
flex-grow: 1;
|
|
}
|
|
rows, columns { border: 1px solid red; }
|
|
</style>
|
|
</head>
|
|
<body onload="fillForm(); drawAll();" style="max-width: inherit;">
|
|
<h1>Report</h1>
|
|
<columns>
|
|
<form style="width: 16em; flex-shrink: 0;" onsubmit="drawAll(); return false;">
|
|
<columns>
|
|
<button type="submit">Apply</button>
|
|
</columns>
|
|
<rows id="form"></rows>
|
|
</form>
|
|
<rows>
|
|
<rows>
|
|
<rows>
|
|
<h2>Event Volume by Name</h2>
|
|
<div>DRAW ME</div>
|
|
</rows>
|
|
<columns>
|
|
<rows>
|
|
<h3>by Weekday</h3>
|
|
<div id="eventVolumeByWeekday"></div>
|
|
</rows>
|
|
<rows>
|
|
<h3>by Hour</h3>
|
|
<div id="eventVolumeByHour"></div>
|
|
</rows>
|
|
</columns>
|
|
<rows>
|
|
<h3>by Asset</h3>
|
|
<div>DRAW ME</div>
|
|
</rows>
|
|
</rows>
|
|
<rows>
|
|
<div>
|
|
<h2>Events</h2>
|
|
<table id="events">
|
|
</table>
|
|
</div>
|
|
</rows>
|
|
</rows>
|
|
</columns>
|
|
</body>
|
|
<footer>
|
|
</footer>
|
|
</html>
|