import { LitElement, html, css } from "lit"; import { customElement, property } from "lit/decorators.js"; import debug from "debug"; const log = debug("process"); const remap = (x: number, lo: number, hi: number, outLo: number, outHi: number) => { return outLo + (outHi - outLo) * Math.max(0, Math.min(1, (x - lo) / (hi - lo))); }; @customElement("stats-process") export class StatsProcess extends LitElement { // 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; connectedCallback() { super.connectedCallback(); this.initCanvas(this.shadowRoot!.firstElementChild as HTMLCanvasElement); this.prev = Date.now() / 1000; var animate = () => { requestAnimationFrame(animate); this.redraw(); }; animate(); } initCanvas(canvas: HTMLCanvasElement) { if (!canvas) { return; } this.canvas = canvas; this.ctx = this.canvas.getContext("2d")!; 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); const dt = now - this.prev; this.prev = now; const size = remap(this.mem.valueOf() / 1024 / 1024, /*in*/ 20, 80, /*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), y = this.h / 2 + rad * Math.sin(this.revs / 6.28); ctx.save(); ctx.beginPath(); ctx.fillStyle = "hsl(194, 100%, 42%)"; ctx.arc(x, y, size, 0, 2 * Math.PI); ctx.fill(); ctx.restore(); } static styles = [ css` :host { display: inline-block; width: 64px; height: 64px; } `, ]; render() { return html``; } }