import React, { Component } from 'react' import './App.css' import Service from './Service.js' import ServicePlaceholder from './ServicePlaceholder.js' import DegradedNotice from './DegradedNotice.js' import StreamingClient from '../ws/client' import { log, objectFromEntries } from '../util.js' import { domain as DOMAIN } from '../config.json' export default class App extends Component { client = null state = { loading: true, error: null, metrics: null, } async componentDidMount () { await this.loadMetrics() const endpoint = `${DOMAIN}/api/streaming` .replace('https', 'wss') .replace('http', 'ws') this.client = new StreamingClient(endpoint, this.state.metrics) this.client.connect() this.client.on('status', this.handleStatus.bind(this)) this.client.on('latency', this.handleLatency.bind(this)) } handleStatus (name, [, status]) { const { status: statuses } = this.state.metrics log('updating status on:', name) if (!(name in statuses)) { log(`failed to locate channel ${name} to update statuses`) return } if (statuses[name].status === status) { log(`ignoring stale status (${status}) for ${name}`) return } this.setState(({ metrics: old }, _props) => { const metrics = { ...old } metrics.status[name].status = status return { metrics } }) } handleLatency (name, data) { const { metrics } = this.state log('adding latency entry:', data) // latency entries come in newest to oldest, so remove the oldest entry const graph = metrics.graph[name].slice(0, metrics.graph[name].length - 1) // make new data come in first const newGraph = [data, ...graph] this.setState(({ metrics: old }, _props) => { const metrics = { ...old } metrics.graph[name] = newGraph const [, latency] = data metrics.status[name].latency = latency return { metrics } }) } async loadMetrics () { log('loading metrics') try { var resp = await fetch(`${DOMAIN}/api/status`) } catch (err) { this.setState({ error: `Network error: ${err}`, }) } if (!resp.ok) { this.setState({ error: `Failed to fetch stats (${resp.status} ${resp.statusText})`, }) return } const json = await resp.json() this.setState({ metrics: json, loading: false }) } render () { let metrics = null if (this.state.metrics) { const allServices = Object.entries(this.state.metrics.status) const graphs = this.state.metrics.graph const services = allServices.map(([name, info]) => ( )) const down = allServices.filter(([, { status }]) => !status) const notice = down.length > 0 ? : null metrics = (
{notice} {services}
) } return (

elstatus

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