diff options
author | Udo Walter | 2019-02-26 10:31:45 +0100 |
---|---|---|
committer | Udo Walter | 2019-02-26 10:31:45 +0100 |
commit | 4ef7abb2958085e3872ed5f7c433c5ddbd10d79a (patch) | |
tree | f0f13e53672cd409763e3c94d379f0c9701abffd | |
parent | Support serverCount field from dnbd3 RPC (diff) | |
download | dnbd3-status-4ef7abb2958085e3872ed5f7c433c5ddbd10d79a.tar.gz dnbd3-status-4ef7abb2958085e3872ed5f7c433c5ddbd10d79a.tar.xz dnbd3-status-4ef7abb2958085e3872ed5f7c433c5ddbd10d79a.zip |
table.html: (hopefully) fix crashes; keep offline servers greyed out for the timespan;
add ability to display ports (url query parameter 'ports'); fix display bug with ipv6 addresses;
-rw-r--r-- | static/table.html | 144 |
1 files changed, 91 insertions, 53 deletions
diff --git a/static/table.html b/static/table.html index eb4ca4c..060c6c7 100644 --- a/static/table.html +++ b/static/table.html @@ -21,7 +21,7 @@ justify-content: center; overflow-y: auto; } - + .server { border-spacing: 2px 4px; background-color: #eee; @@ -30,6 +30,10 @@ max-width: 360px; margin: 3px; } + + .server-offline { + filter: brightness(50%); + } .first-row { font-weight: bold; @@ -56,7 +60,7 @@ <div id="app"> <div class="server-container"> - <table v-for="(server, index) in servers" class="server" :style="{ border: '4px solid ' + GRAPH_COLORS[index] }"> + <table v-for="server in servers" class="server" :class="{ 'server-offline': server.offline }" :style="{ border: '4px solid ' + server.graphColor }"> <tbody> <tr class="first-row"><td colspan="2" class="server-ip">{{ server.address }}</td></tr> <tr><td>Uptime:</td><td class="expand">{{ formatSeconds(server.uptime) }}</td></tr> @@ -77,7 +81,7 @@ <tr><td>Client count:</td><td>{{ server.clientCount }}</td></tr> <tr><td>Server count:</td><td>{{ server.serverCount }}</td></tr> <tr v-for="client in server.clients"> - <td class="client-label">{{ client.address.split( ":" )[0] }}</td> + <td class="client-label">{{ formatIpAddress(client.address) }}</td> <td class="client-speed" :style="calcBackgroundStyle(peak ? client.peakUploadSpeed : client.avgUploadSpeed)"> <span>{{ formatBytes(peak ? client.peakUploadSpeed : client.avgUploadSpeed) }}/s</span> </td> @@ -88,7 +92,7 @@ <canvas ref="chart" :width="this.canvasWidth"></canvas> </div> -<script src="vue.min.js"></script> +<script src="vue.js"></script> <script src="smoothie.js"></script> <script> @@ -97,45 +101,83 @@ var app = new Vue({ el: '#app', data: { rawData: {}, - servers: [], - logs: {}, + serverMap: {}, timespan: 120, peak: false, + ports: false, canvasWidth: 0, smoothie: null, - graphLines: {}, - GRAPH_COLORS: ["#3366cc", "#dc3912", "#ff9900", "#109618", "#990099", "#0099c6", "#dd4477", "#66aa00", "#b82e2e", "#316395", "#994499", "#22aa99", "#aaaa11", "#6633cc", "#e67300", "#8b0707", "#651067", "#329262", "#5574a6", "#3b3eac"] + graphColors: ["#3366cc", "#dc3912", "#ff9900", "#109618", "#990099", "#0099c6", "#dd4477", "#66aa00", "#b82e2e", "#316395", "#994499", "#22aa99", "#aaaa11", "#6633cc", "#e67300", "#8b0707", "#651067", "#329262", "#5574a6", "#3b3eac"] + }, + computed: { + servers () { + const servers = Object.values(this.serverMap) + servers.sort(this.compareObjectIps) + servers.forEach(server => { + if (this.rawData.timestamp - server.timestamp > 6000) server.offline = true + const clients = Object.values(server.clientMap) + if (this.peak) { + server.clients = clients.filter(client => client.peakUploadSpeed > 0) + server.clients.sort((a, b) => b.peakUploadSpeed - a.peakUploadSpeed) + } else { + server.clients = clients.filter(client => client.avgUploadSpeed > 0) + server.clients.sort((a, b) => b.avgUploadSpeed - a.avgUploadSpeed) + } + }) + return servers + } }, watch: { rawData () { if (this.rawData.servers) { - const servers = this.rawData.servers.slice(0) - servers.sort(this.compareObjectIps) - const currentTime = new Date().getTime() - servers.forEach((server, index) => { - this.calcSpeed(server) - - // Update the graph - if (!this.graphLines[server.address]) { - Vue.set(this.graphLines, server.address, new TimeSeries({ logarithmicScale: true })) - this.smoothie.addTimeSeries(this.graphLines[server.address], { lineWidth: 2, strokeStyle: this.GRAPH_COLORS[index] }) + this.rawData.servers.forEach(serverData => { + // Update server + var server = this.serverMap[serverData.address] + if (server) { + Object.assign(server, serverData) + } else { + server = { + ...serverData, + log: [], + clientMap: {}, + graphColor: this.graphColors.shift(), + graphLine: new TimeSeries({ logarithmicScale: true }) + } + Vue.set(this.serverMap, serverData.address, server) + this.smoothie.addTimeSeries(server.graphLine, { lineWidth: 2, strokeStyle: server.graphColor }) } - this.graphLines[server.address].append(currentTime, server.uploadSpeed) + server.log.push(serverData) + this.calcSpeed(server) + server.graphLine.append(server.timestamp, server.uploadSpeed) // Update clients - server.clients.forEach(client => { - client.timestamp = server.timestamp + serverData.clients.forEach(clientData => { + clientData.timestamp = server.timestamp + var client = server.clientMap[clientData.address] + if (client) server.clientMap[clientData.address] = { ...client, ...clientData } + else Vue.set(server.clientMap, clientData.address, { ...clientData, log: [] }) + client = server.clientMap[clientData.address] + client.log.push(clientData) this.calcSpeed(client) }) - if (this.peak) { - server.clients = server.clients.filter(client => client.peakUploadSpeed > 0) - server.clients.sort((a, b) => b.peakUploadSpeed - a.peakUploadSpeed) - } else { - server.clients = server.clients.filter(client => client.avgUploadSpeed > 0) - server.clients.sort((a, b) => b.avgUploadSpeed - a.avgUploadSpeed) - } }) - this.servers = servers + } + + // Remove outdated values + for (let serverIp in this.serverMap) { + const server = this.serverMap[serverIp] + server.log = server.log.filter(x => x.timestamp > this.rawData.timestamp - this.timespan * 1000) + if (server.log.length === 0) { + this.smoothie.removeTimeSeries(server.graphLine) + this.graphColors.unshift(server.graphColor) + Vue.delete(this.serverMap, serverIp) + } else { + for (let clientIp in server.clientMap) { + const client = server.clientMap[clientIp] + client.log = client.log.filter(x => x.timestamp > this.rawData.timestamp - this.timespan * 1000) + if (client.log.length === 0) Vue.delete(server.clientMap, clientIp) + } + } } } }, @@ -146,33 +188,25 @@ var app = new Vue({ setTimeout(this.updateData, 2000) }, calcSpeed (obj) { - // Create a log for this ip if it doesn't exist already - if(!this.logs[obj.address]) Vue.set(this.logs, obj.address, []) - // Remove outdated values - this.logs[obj.address] = this.logs[obj.address].filter(x => x.timestamp > this.rawData.timestamp - this.timespan * 1000) - // Get the all the old values accumulated over the timespan - const log = this.logs[obj.address] - // Add new values to the log - if (log.length === 0 || obj.timestamp > log[log.length - 1].timestamp) log.push(obj) + // Need a minimum of two values to calculate the speed + if (obj.log.length <= 1) return - if (log.length > 1) { - // Calculate current speeds - var a = log[log.length - 2] - const b = log[log.length - 1] - var time = (b.timestamp - a.timestamp) / 1000 - obj.uploadSpeed = (b.bytesSent - a.bytesSent) / time - obj.downloadSpeed = (b.bytesReceived - a.bytesReceived) / time + // Calculate current speeds + var a = obj.log[obj.log.length - 2] + const b = obj.log[obj.log.length - 1] + var time = (b.timestamp - a.timestamp) / 1000 + obj.uploadSpeed = (b.bytesSent - a.bytesSent) / time + obj.downloadSpeed = (b.bytesReceived - a.bytesReceived) / time - // Calculate peak speeds - obj.peakUploadSpeed = Math.max(...log.map(x => x.uploadSpeed || 0)) - obj.peakDownloadSpeed = Math.max(...log.map(x => x.downloadSpeed || 0)) + // Calculate peak speeds + obj.peakUploadSpeed = Math.max(...obj.log.map(x => x.uploadSpeed || 0)) + obj.peakDownloadSpeed = Math.max(...obj.log.map(x => x.downloadSpeed || 0)) - // Calculate average speeds - a = log[0] - time = (b.timestamp - a.timestamp) / 1000 - obj.avgUploadSpeed = (b.bytesSent - a.bytesSent) / time - obj.avgDownloadSpeed = (b.bytesReceived - a.bytesReceived) / time - } + // Calculate average speeds + a = obj.log[0] + time = (b.timestamp - a.timestamp) / 1000 + obj.avgUploadSpeed = (b.bytesSent - a.bytesSent) / time + obj.avgDownloadSpeed = (b.bytesReceived - a.bytesReceived) / time }, formatBytes (bytes) { if (bytes < 1024) return bytes.toFixed(2) + ' B' @@ -206,12 +240,16 @@ var app = new Vue({ }, logScale (value) { return Math.log(value/100000 + 1) + }, + formatIpAddress (ip) { + return this.ports ? ip : ip.substring(0, ip.lastIndexOf(':')) } }, created () { const urlParams = new URLSearchParams(window.location.search) this.timespan = parseInt(urlParams.get('timespan')) || 120 this.peak = urlParams.get('peak') === 'true' || urlParams.get('peak') === '' + this.ports = urlParams.get('ports') === 'true' || urlParams.get('ports') === '' this.updateData() }, mounted () { |