changeset 2036:00afa5ec081a

restore more of the stats widget including the cpu/mem spinner
author drewp@bigasterisk.com
date Sat, 09 Apr 2022 11:44:57 -0700
parents f9faa2ec824f
children b731eaad3adf
files light9/web/homepage/StatsLine.ts light9/web/homepage/StatsProcess.ts light9/web/homepage/index.html makefile
diffstat 4 files changed, 94 insertions(+), 63 deletions(-) [+]
line wrap: on
line diff
--- a/light9/web/homepage/StatsLine.ts	Sat Apr 09 02:49:14 2022 -0700
+++ b/light9/web/homepage/StatsLine.ts	Sat Apr 09 11:44:57 2022 -0700
@@ -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 @@
   @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 @@
                 .text()
                 .then((msg) => {
                   this.stats = parsePrometheusTextFormat(msg) as Metrics;
+                  this.extractProcessStats(this.stats);
                   setTimeout(reload, 1000);
                 })
                 .catch((err) => {
@@ -49,6 +53,20 @@
       }
     });
   }
+  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 @@
       }
     };
 
-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`
-      <table>
-        ${this.stats.filter(nonBoring).map(
-          (row) => html`
-            <tr>
-              <th>${row.name}</th>
-              <td>
-                <table>
-                  ${row.metrics.map(
-                    (v) => html`
-                      <tr>
-                        <td>${JSON.stringify(v.labels)}</td>
-                        <td>${v.value}</td>
-                      </tr>
+      <div>
+        <table>
+          ${displayedStats.map(
+            (row, rowNum) => html`
+              <tr>
+                <th>${row.name}</th>
+                <td>
+                  <table>
+                    ${row.metrics.map(
+                      (v) => html`
+                        <tr>
+                          <td>${JSON.stringify(v.labels)}</td>
+                          <td>${v.value}</td>
+                        </tr>
+                      `
+                    )}
+                  </table>
+                </td>
+                ${rowNum == 0
+                  ? html`
+                      <td rowspan="${displayedStats.length}">
+                        <stats-process id="proc" cpu="${this.cpu}" mem="${this.mem}"></stats-process>
+                      </td>
                     `
-                  )}
-                </table>
-              </td>
-            </tr>
-          `
-        )}
-      </table>
-      <stats-process id="proc"></stats-process>
+                  : ""}
+              </tr>
+            `
+          )}
+        </table>
+      </div>
     `;
   }
 }
--- a/light9/web/homepage/StatsProcess.ts	Sat Apr 09 02:49:14 2022 -0700
+++ b/light9/web/homepage/StatsProcess.ts	Sat Apr 09 11:44:57 2022 -0700
@@ -10,18 +10,18 @@
 
 @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<string, any>) {
-    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 @@
     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 @@
     ctx.fill();
     ctx.restore();
   }
-  updated(changedProperties: Map<string, any>) {
-    if (changedProperties.has("dataTime")) {
-      this.shadowRoot!.firstElementChild!.setAttribute("title", `cpu ${this.cpu}% mem ${this.mem}MB`);
-    }
-  }
 
   static styles = [
     css`
--- a/light9/web/homepage/index.html	Sat Apr 09 02:49:14 2022 -0700
+++ b/light9/web/homepage/index.html	Sat Apr 09 11:44:57 2022 -0700
@@ -7,8 +7,6 @@
     <script type="module" src="./ServiceButtonRow.ts"></script>
   </head>
   <body>
-     
-    -->
     <h1>light9 home page</h1>
 
     <div style="display: grid">
@@ -25,7 +23,7 @@
       <service-button-row name="effects"></service-button-row>
       <service-button-row name="timeline"></service-button-row>
       <service-button-row name="paint"></service-button-row>
-      <service-button-row name="effectEval"></service-button-row>
+      <service-button-row name="effectEval"></service-button-row> 
 <!--       <hr>
       <service-button-row name="subServer"></service-button-row>
       <service-button-row name="subComposer"></service-button-row>
--- a/makefile	Sat Apr 09 02:49:14 2022 -0700
+++ b/makefile	Sat Apr 09 11:44:57 2022 -0700
@@ -21,13 +21,13 @@
 	pnpm install
 
 node_modules/n3/n3-browser.js:
-	(cd node_modules/n3; nodejs ../browserify/bin/cmd.js --standalone N3 --require n3 -o n3-browser.js)
+	(cd node_modules/n3; pnpx browserify --standalone N3 --require n3 -o n3-browser.js)
 
 light9/web/lib/debug/debug-build.js:
-	node_modules/browserify/bin/cmd.js light9/web/lib/debug/src/browser.js -o light9/web/lib/debug/debug-build.js --standalone debug
+	pnpx browserify light9/web/lib/debug/src/browser.js -o light9/web/lib/debug/debug-build.js --standalone debug
 
 light9/web/lib/debug/debug-build-es6.js:
-	node_modules/browserify/bin/cmd.js light9/web/lib/debug/src/browser.js -o light9/web/lib/debug/debug-build-es6.js --standalone debug
+	pnpx browserify light9/web/lib/debug/src/browser.js -o light9/web/lib/debug/debug-build-es6.js --standalone debug
 	echo "\nexport default window.debug;" >> light9/web/lib/debug/debug-build-es6.js
 
 lit_fix:
@@ -59,12 +59,6 @@
 coffee:
 	zsh -c 'cd light9/web; ../../node_modules/coffeescript/bin/coffee --map -cw {.,live,timeline,paint,effects}/*.coffee'
 
-mypy:
-	inv mypy
-
-reformat:
-	inv reformat
-
 ### show ###
 
 qlc_artnet_dmx_proxy:
@@ -102,25 +96,25 @@
 NOSEARGS="--no-path-adjustment light9.rdfdb.rdflibpatch light9.rdfdb.patch light9.effecteval.test_effect light9.collector light9.rdfdb.graphfile_test light9.paint light9.effect"
 
 tests:
-	eval env/bin/nosetests -x $(NOSEARGS)
+	eval pdm run nosetests -x $(NOSEARGS)
 
 tests_watch:
-	eval env/bin/nosetests --with-watcher $(NOSEARGS)
+	eval pdm run nosetests --with-watcher $(NOSEARGS)
 
 
 tests_coverage:
-	eval env/bin/nosetests --with-coverage --cover-erase --cover-html --cover-html-dir=/tmp/light9-cov/  --cover-package=light9 --cover-branches $(NOSEARGS)
+	eval pdm run nosetests --with-coverage --cover-erase --cover-html --cover-html-dir=/tmp/light9-cov/  --cover-package=light9 --cover-branches $(NOSEARGS)
 
 test_js_init:
 	npm install
 
 test_js:
-	node_modules/coffeescript/bin/coffee -c light9/web/*.coffee
-	node_modules/mocha/bin/mocha --compilers coffee:coffee-script/register --globals window,N3 light9/web/graph_test.coffee
+	pnpx coffee -c light9/web/*.coffee
+	pnpx mocha --compilers coffee:coffee-script/register --globals window,N3 light9/web/graph_test.coffee
 
 test_js_watch:
 	# have coffee continuously running
-	watch -c node_modules/mocha/bin/mocha --compilers coffee:coffee-script/register --globals window,N3 light9/web/graph_test.coffee --colors
+	watch -c pnpx mocha --compilers coffee:coffee-script/register --globals window,N3 light9/web/graph_test.coffee --colors
 
 profile_seq:
 	echo in lib, get https://github.com/uber/pyflame.git and https://github.com/brendangregg/FlameGraph.git