# HG changeset patch # User drewp@bigasterisk.com # Date 2022-04-09 18:44:57 # Node ID 00afa5ec081aee1e49b1b674780be85730079e08 # Parent f9faa2ec824fe967c35ea81d07177a04499f63fd restore more of the stats widget including the cpu/mem spinner diff --git a/light9/web/homepage/StatsLine.ts b/light9/web/homepage/StatsLine.ts --- a/light9/web/homepage/StatsLine.ts +++ b/light9/web/homepage/StatsLine.ts @@ -1,7 +1,5 @@ import { css, html, LitElement, TemplateResult } from "lit"; import { customElement, property } from "lit/decorators.js"; -import { rounding } from "significant-rounding"; -import { StatsProcess } from "./StatsProcess"; export { StatsProcess } from "./StatsProcess"; import parsePrometheusTextFormat from "parse-prometheus-text-format"; @@ -22,6 +20,11 @@ export class StatsLine extends LitElemen @property() name = "?"; @property() stats: Metrics = []; + prevCpuNow = 0; + prevCpuTotal = 0; + @property() cpu = 0; + @property() mem = 0; + updated(changedProperties: any) { changedProperties.forEach((oldValue: any, propName: string) => { if (propName == "name") { @@ -32,6 +35,7 @@ export class StatsLine extends LitElemen .text() .then((msg) => { this.stats = parsePrometheusTextFormat(msg) as Metrics; + this.extractProcessStats(this.stats); setTimeout(reload, 1000); }) .catch((err) => { @@ -49,6 +53,20 @@ export class StatsLine extends LitElemen } }); } + extractProcessStats(stats: Metrics) { + stats.forEach((row) => { + if (row.name == "process_resident_memory_bytes") { + this.mem = parseFloat(row.metrics[0].value) / 1024 / 1024; + } + if (row.name == "process_cpu_seconds_total") { + const now = Date.now() / 1000; + const cpuSecondsTotal = parseFloat(row.metrics[0].value); + this.cpu = (cpuSecondsTotal - this.prevCpuTotal) / (now - this.prevCpuNow); + this.prevCpuTotal = cpuSecondsTotal; + this.prevCpuNow = now; + } + }); + } static styles = [ css` @@ -195,34 +213,52 @@ export class StatsLine extends LitElemen } }; -const nonBoring = (m: Metric)=>{ - return !m.name.endsWith('_created') && m.name!= 'python_info' -} + const nonBoring = (m: Metric) => { + return ( + !m.name.endsWith("_created") && // + !m.name.startsWith("python_gc_") && + m.name != "python_info" && + m.name != "process_max_fds" && + m.name != "process_virtual_memory_bytes" && + m.name != "process_resident_memory_bytes" && + m.name != "process_start_time_seconds" && + m.name != "process_cpu_seconds_total" + ); + }; // return table(this.stats, []); + const displayedStats = this.stats.filter(nonBoring); return html` - - ${this.stats.filter(nonBoring).map( - (row) => html` - - - - - ` - )} -
${row.name} - - ${row.metrics.map( - (v) => html` - - - - +
+
${JSON.stringify(v.labels)}${v.value}
+ ${displayedStats.map( + (row, rowNum) => html` + + + + ${rowNum == 0 + ? html` + ` - )} -
${row.name} + + ${row.metrics.map( + (v) => html` + + + + + ` + )} +
${JSON.stringify(v.labels)}${v.value}
+
+ +
-
- + : ""} + + ` + )} + + `; } } diff --git a/light9/web/homepage/StatsProcess.ts b/light9/web/homepage/StatsProcess.ts --- a/light9/web/homepage/StatsProcess.ts +++ b/light9/web/homepage/StatsProcess.ts @@ -10,18 +10,18 @@ const remap = (x: number, lo: number, hi @customElement("stats-process") export class StatsProcess extends LitElement { - @property() dataTime: number = 0; // millis at last data change - @property() cpu: number = 12; // process_cpu_seconds_total - @property() mem: number = 50000000; // process_resident_memory_bytes + // inspired by https://codepen.io/qiruiyin/pen/qOopQx + @property() cpu = 0; // process_cpu_seconds_total + @property() mem = 0; // process_resident_memory_bytes w = 64; h = 64; revs = 0; prev = 0; + canvas?: HTMLCanvasElement; ctx?: CanvasRenderingContext2D; - firstUpdated(c: Map) { - super.firstUpdated(c); - // inspired by https://codepen.io/qiruiyin/pen/qOopQx + connectedCallback() { + super.connectedCallback(); this.initCanvas(this.shadowRoot!.firstElementChild as HTMLCanvasElement); this.prev = Date.now() / 1000; @@ -32,27 +32,35 @@ export class StatsProcess extends LitEle animate(); } initCanvas(canvas: HTMLCanvasElement) { - var ctx = canvas.getContext("2d")!; + if (!canvas) { + return; + } + this.canvas = canvas; + this.ctx = this.canvas.getContext("2d")!; - canvas.width = this.w; - canvas.height = this.h; + this.canvas.width = this.w; + this.canvas.height = this.h; } redraw() { + if (!this.ctx) { + this.initCanvas(this.shadowRoot!.firstElementChild as HTMLCanvasElement); + } if (!this.ctx) return; + + this.canvas!.setAttribute("title", + `cpu ${new Number(this.cpu).toPrecision(3)}% mem ${new Number(this.mem).toPrecision(3)}MB`); + const now = Date.now() / 1000; const ctx = this.ctx; ctx.beginPath(); // wrong type of fade- never goes to 0 ctx.fillStyle = "#00000003"; ctx.fillRect(0, 0, this.w, this.h); - // if (!this.data || this.data.time < now - 2) { - // return; - // } const dt = now - this.prev; this.prev = now; - const size = remap(this.mem / 1024 / 1024, /*in*/ 20, 600, /*out*/ 3, 30); - this.revs += dt * remap(this.cpu, /*in*/ 0, 100, /*out*/ 4, 120); + const size = remap(this.mem.valueOf() / 1024 / 1024, /*in*/ 20, 600, /*out*/ 3, 30); + this.revs += dt * remap(this.cpu.valueOf(), /*in*/ 0, 100, /*out*/ 4, 120); const rad = remap(size, /*in*/ 3, 30, /*out*/ 14, 5); var x = this.w / 2 + rad * Math.cos(this.revs / 6.28), @@ -65,11 +73,6 @@ export class StatsProcess extends LitEle ctx.fill(); ctx.restore(); } - updated(changedProperties: Map) { - if (changedProperties.has("dataTime")) { - this.shadowRoot!.firstElementChild!.setAttribute("title", `cpu ${this.cpu}% mem ${this.mem}MB`); - } - } static styles = [ css` diff --git a/light9/web/homepage/index.html b/light9/web/homepage/index.html --- a/light9/web/homepage/index.html +++ b/light9/web/homepage/index.html @@ -7,8 +7,6 @@ - - -->

light9 home page

@@ -25,7 +23,7 @@ - +