Mercurial > code > home > repos > racc
diff console/src/main.ts @ 6:b1043d39e493
start web console
author | drewp@bigasterisk.com |
---|---|
date | Mon, 13 Mar 2023 18:53:45 -0700 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/src/main.ts Mon Mar 13 18:53:45 2023 -0700 @@ -0,0 +1,143 @@ +import { startOfDay, subDays, differenceInMinutes, getUnixTime, addDays, format, min, formatISO } from "date-fns"; +import * as echarts from "echarts"; +import { TabulatorFull as Tabulator } from "tabulator-tables"; + +const QUERY_RANGE = "https://bigasterisk.com/m/prometheus/api/v1/query_range"; +const MAC = new Map([ +]); + +function progQueryUrl(prog: string, s: Date, e: Date): URL { + const rangeMins = differenceInMinutes(e, s); + const out = new URL(QUERY_RANGE); + + const host = "Kelsis-iMac"; + const isRunningQl = `racc_running{prog="${prog}",host="${host}"}`; + const isNonIdleQl = `max(racc_idle{host="${host}"}) < 100`; + const countedTimeQl = `(${isRunningQl}) if (${isNonIdleQl})`; + const integralQl = `integrate((${countedTimeQl})[${rangeMins}m])`; + const hoursQl = `${integralQl}/1h`; + + out.searchParams.append("query", hoursQl); + out.searchParams.append("start", "" + getUnixTime(s)); + out.searchParams.append("end", "" + getUnixTime(e)); + out.searchParams.append("step", "1m"); + return out; +} + +async function queryLastRow(queryUrl: URL): Promise<string> { + const response = await fetch(queryUrl); + const body = await response.json(); + if (!body?.data?.result) { + return "0"; + } + const m = body.data.result[0]; + if (m?.values?.length) { + const lastRow = m.values[m.values.length - 1]; + return parseFloat(lastRow[1]).toFixed(2); + } + return "0"; +} + +async function makeSeries(now: Date, meas: string, prog: string, numDays: number): Promise<echarts.BarSeriesOption> { + const rows = []; + const sod = startOfDay(now); + + for (let i = numDays-1 ; i >= 0; i--) { + const s = subDays(sod, i); + const e = min([now, addDays(s, 1)]); + console.log(i, formatISO(s), formatISO(e)); + rows.push(queryLastRow(progQueryUrl(prog, s, e))); + } + const mc = await Promise.all(rows); + + return { + name: meas, + type: "bar", + animation: false, + data: mc, + emphasis: { focus: "series" }, + label: { show: true }, + stack: "total", + + }; +} + +function dateRowLabels(now: Date, days: number) { + const rowNames = []; + for (let d = subDays(now, days - 1); d < now; d = addDays(d, 1)) { + rowNames.push(format(d, "MM/dd EEE")); + } + rowNames.push(format(now, "MM/dd EEE") + " (today)"); + return rowNames; +} + +function fillDebugTable(el: HTMLElement) { + var rows = []; + + const vmui = (expr: string, range: string): string => + "https://bigasterisk.com/m/vmui/?" + + "g0.expr=" + + encodeURIComponent(expr) + // + "&g0.range_input=" + + encodeURIComponent(range); + const view = (url: string): string => `<a href="${url}">view</a>`; + for (let host of ["Kelsis-iMac", "dash", "dot", "plus"]) { + rows.push({ + id: rows.length, + host: host, + metrics: view(`http://${host}:5150/metrics`), + uptime: view(vmui(`python_info{job="racc",instance="${host}:5150"}`, "14d")), + traffic: view(vmui(`rate(lan_bytes_sent_from_total{mac="${MAC.get(host)}"})`, "6h")), + }); + } + var table = new Tabulator(el, { + data: rows, + columns: [ + { title: "Host", field: "host" }, + { title: "current /metrics", field: "metrics", formatter: "html" }, + { title: "racc uptime history", field: "uptime", formatter: "html" }, + { title: "outgoing net traffic", field: "traffic", formatter: "html" }, + ], + }); +} + +async function main() { + fillDebugTable(document.getElementById("debug1")!); + + const now = new Date(); + + const chartDom = document.getElementById("chart1")!; + const chart = echarts.init(chartDom); + + const nDays = 8; + const rowNames = dateRowLabels(now, nDays); + + const option: echarts.EChartsOption = { + tooltip: { + trigger: "axis", + axisPointer: { + type: "shadow", + }, + }, + legend: {}, + grid: { + left: "0%", + containLabel: true, + }, + xAxis: { + type: "value", + max: 10, + }, + yAxis: { + type: "category", + data: rowNames, + }, + series: await Promise.all([ + makeSeries(now, "Minecraft hours", "minecraft", nDays), // + makeSeries(now, "Roblox hours", "roblox", nDays), + ]), + }; +console.log(option); + chart.setOption(option); +} +main();