changeset 5:9eaa993ed373

monitoring
author drewp@bigasterisk.com
date Sun, 15 Oct 2023 18:47:45 -0700
parents d0fa3638de2a
children f3786656cf4f
files front_door_lock.py src/MetricRow.ts src/main.ts
diffstat 3 files changed, 89 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/front_door_lock.py	Sun Aug 27 13:18:36 2023 -0700
+++ b/front_door_lock.py	Sun Oct 15 18:47:45 2023 -0700
@@ -31,7 +31,7 @@
 from starlette.responses import JSONResponse
 from starlette.routing import Route
 from starlette_exporter import PrometheusMiddleware, handle_metrics
-
+from prometheus_client import Gauge
 from get_agent import getFoafAgent
 
 logging.basicConfig(level=logging.INFO)
@@ -41,6 +41,8 @@
 ctx = ROOM['frontDoorLockGraph']
 lockUri = ROOM['frontDoorLock']
 
+MQTT_CONNECTED = Gauge('mqtt_connected', 'mqtt is connected')
+HW_CONNECTED = Gauge('hw_connected', 'esp is connected')
 
 def output(graph: PatchableGraph, request: Request) -> JSONResponse:
     return JSONResponse({"demo": "hello"})
@@ -120,10 +122,14 @@
         while True:
             try:
                 async with self.client:
+                    MQTT_CONNECTED.set(1)
                     await self._handleMessages()
             except aiomqtt.MqttError:
+                MQTT_CONNECTED.set(0)
                 log.error('mqtt reconnecting', exc_info=True)
                 await asyncio.sleep(5)
+            finally:
+                MQTT_CONNECTED.set(0)
 
     async def _handleMessages(self):
         async with self.client.messages() as messages:
@@ -140,6 +146,7 @@
 
     def _stateFromMqtt(self, payload: str) -> URIRef:
         return {
+            '': ROOM['unknownState'],
             'OFF': ROOM['locked'],
             'ON': ROOM['unlocked'],
         }[payload]
@@ -155,6 +162,7 @@
                 self.hw.writeHwLockStateToGraph(self._stateFromMqtt(payload))
             case 'status':
                 self.hw.setOnline(payload == 'online')
+                HW_CONNECTED.set(payload == 'online')
             case 'debug':
                 log.info(f'hw debug: {payload}')  # note: may include ansi colors
             case _:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/MetricRow.ts	Sun Oct 15 18:47:45 2023 -0700
@@ -0,0 +1,67 @@
+import { LitElement, PropertyValueMap, css, html } from "lit";
+import { customElement, property, state } from "lit/decorators.js";
+
+
+@customElement("metric-row")
+export class MetricRow extends LitElement {
+  static styles = [
+    css`
+      :host > div {
+        border: solid #eee;
+        border-width: 1px 0;
+      }
+      :host > div > span {
+        display: inline-block;
+      }
+      span.label {
+        width: 20em;
+      }
+      span.vmval {
+        width: 2em;
+      }
+      span.asof {
+        width: 15em;
+      }
+      .vmval {
+        font-weight: bold;
+      }
+      .asof {
+        color: gray;
+      }
+    `,
+  ];
+  @property() label: string = "??";
+  @property() q: string = "";
+  @state() resultTime?: Date;
+  @state() resultValue?: string;
+  render() {
+    const graphUrl = new URL("https://bigasterisk.com/m/vmui/#/");
+
+    graphUrl.searchParams.append("g0.expr", this.q);
+    graphUrl.searchParams.append("g0.range_input", "6h");
+    graphUrl.searchParams.append("g0.relative_time", "last_6_hours");
+    return html`<div>
+      <span class='label'>${this.label}</span>
+      <span class="vmval"> ${this.resultValue || "..."} </span>
+      <span class="asof">${this.resultTime ? html`as of ${this.resultTime.toLocaleString("sv")}` : []}</span>
+      <span class='graph'><a href="${graphUrl.toString()}">[graph]</a>
+    </div>`;
+  }
+
+  protected async update(changedProperties: PropertyValueMap<this>) {
+    if (changedProperties.has("q") && this.q) {
+      this.getMetricValue(this.q);
+    }
+    super.update(changedProperties);
+  }
+
+  async getMetricValue(q: string) {
+    const vmapi = "https://bigasterisk.com/m/prometheus/api/v1";
+    const queryUrl = new URL(vmapi + "/query");
+    queryUrl.searchParams.append("query", q);
+    const resp = await (await fetch(queryUrl)).json();
+    const v = resp.data.result[0].value;
+    this.resultTime = new Date(v[0] * 1000);
+    this.resultValue = v[1];
+  }
+}
--- a/src/main.ts	Sun Aug 27 13:18:36 2023 -0700
+++ b/src/main.ts	Sun Oct 15 18:47:45 2023 -0700
@@ -1,6 +1,7 @@
 import { LitElement, TemplateResult, css, html } from "lit";
 import { customElement, property } from "lit/decorators.js";
 export { SgSource, SgView, StreamedGraph } from "@bigasterisk/streamed-graph";
+export { MetricRow } from "./MetricRow";
 
 @customElement("fd-page")
 export class FdPage extends LitElement {
@@ -48,8 +49,18 @@
         <sg-view uri="#view"></sg-view>
       </streamed-graph>
       <p>
-        <a href="metrics">metrics</a> |
-        <a href="api/graph">graph</a>
+        <a href="metrics">metrics</a> | <a href="api/graph">graph</a> |
+        <a href="https://bigasterisk.com/k/clusters/local/namespaces/default/deployments/front-door-lock">deploy</a> |
+        <a href="https://bigasterisk.com/k/clusters/local/namespaces/default/deployments/front-door-lock/logs">logs</a> |
+        <a href="https://bigasterisk.com/vmalert/groups#group-14459482342649697182">alert group</a>
+      </p>
+      <p>
+        <metric-row label="reader esp32: mqtt connected  " q='hw_connected{job="fingerprint"}'></metric-row>
+        <metric-row label="reader service: up            " q='up{job="fingerprint"}'></metric-row>
+        <metric-row label="reader service: mqtt connected" q='mqtt_connected{job="fingerprint"}'></metric-row>
+        <metric-row label="Lock service (this page): up  " q='up{job="front-door-lock"}'></metric-row>
+        <metric-row label="Lock service: mqtt connected  " q='mqtt_connected{job="front-door-lock"}'></metric-row>
+        <metric-row label="Lock esp32: mqtt-connected    " q='hw_connected{job="front-door-lock"}'></metric-row>
       </p>
       <bigast-loginbar></bigast-loginbar>
     `;