import React, { Component } from 'react'; import './App.css'; import Service from './Service.js'; import ServicePlaceholder from './ServicePlaceholder.js'; import OP from '../ws/op.js'; import { log } from '../util.js'; const DOMAIN = 'https://elstatus.stayathomeserver.club'; // const ENDPOINT = 'http://localhost:8069/api/status' export default class App extends Component { websocket = null; reconnectionTime = 1000; state = { loading: true, error: null, metrics: null, }; async componentDidMount() { await this.loadMetrics(); this.connect(); } subscribeToChannels() { const channels = Object.keys(this.state.metrics.graph).map((channel) => `latency:${channel}`); log('subscribing to channels:', channels); this._send({ op: OP.SUBSCRIBE, channels, }); } handlePacket(packet) { const { op, c: channel, d: data } = packet; if (op !== OP.DATA) { log('ignoring boring packet:', packet); return; } const [, name] = channel.split(':'); log('updating from channel:', channel); const { metrics } = this.state; const graph = metrics.graph[name].slice(1); const newGraph = [data, ...graph]; log('adding data:', data); this.setState(({ metrics: oldMetrics }, _props) => { const newMetrics = { ...oldMetrics }; newMetrics.graph[name] = newGraph; const [, latency] = data; newMetrics.status[name].latency = latency; return { metrics: newMetrics, }; }); } connect() { log('connecting to ws'); const endpoint = (`${DOMAIN}/api/streaming`).replace('https', 'wss'); this.websocket = new WebSocket(endpoint); this.websocket.onopen = () => { log('ws opened'); this.subscribeToChannels(); }; this.websocket.onclose = ({ code, reason }) => { log(`ws closed with code ${code} (reason: ${reason || ''}); ` + `attempting to reconnect in ${this.reconnectionTime}ms`); setTimeout(() => this.connect(), this.reconnectionTime); this.reconnectionTime *= 2; }; this.websocket.onmessage = (message) => { const { data } = message; const parsed = JSON.parse(data); log('ws recv:', parsed); this.handlePacket(parsed); }; this.websocket.onerror = (event) => { log('ws error:', event); }; } _send(payload) { this.websocket.send(JSON.stringify(payload)); } async loadMetrics() { log('loading metrics'); try { const resp = await fetch(`${DOMAIN}/api/status`); const json = await resp.json(); this.setState({ metrics: json, loading: false }); } catch (err) { this.setState({ error: err.toString() }); } } render() { const metrics = !this.state.metrics ? null : (
{Object.entries(this.state.metrics.status) .map(([name, info]) => ( )) }
); return (

elstatus

{this.state.error ? (
Error: {this.state.error}
) : null} {this.state.loading ? ( ) : metrics}
); } }