Changeset - 00afa5ec081a
[Not reviewed]
default
0 4 0
drewp@bigasterisk.com - 3 years ago 2022-04-09 18:44:57
drewp@bigasterisk.com
restore more of the stats widget including the cpu/mem spinner
4 files changed with 94 insertions and 63 deletions:
0 comments (0 inline, 0 general)
light9/web/homepage/StatsLine.ts
Show inline comments
 
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`
 
      <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>
 
    `;
 
  }
 
}
light9/web/homepage/StatsProcess.ts
Show inline comments
 
@@ -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<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 @@ 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<string, any>) {
 
    if (changedProperties.has("dataTime")) {
 
      this.shadowRoot!.firstElementChild!.setAttribute("title", `cpu ${this.cpu}% mem ${this.mem}MB`);
 
    }
 
  }
 

	
 
  static styles = [
 
    css`
light9/web/homepage/index.html
Show inline comments
 
@@ -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>
makefile
Show inline comments
 
@@ -21,13 +21,13 @@ npm_install:
 
	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 @@ tkdnd_build:
 
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 @@ arduino_upload: /usr/share/arduino/Ardui
 
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
0 comments (0 inline, 0 general)