From e0d91cadb11205c5f2c686c239a50cb2eef9795d Mon Sep 17 00:00:00 2001 From: Damien Arrachequesne Date: Wed, 22 Jun 2022 00:59:09 +0200 Subject: [PATCH] feat: add production mode There are two ways to enable this production mode: - either with the new "mode" option: ```js instrument(io, { mode: "production" // defaults to "development" }); ``` - or with the NODE_ENV environment variable: ``` NODE_ENV=production node index.js ``` In production mode, the server won't send all details about the socket instances and the rooms, thus reducing the memory footprint of the instrumentation. Related: - https://github.com/socketio/socket.io-admin-ui/issues/22 - https://github.com/socketio/socket.io-admin-ui/issues/23 --- lib/index.ts | 124 ++++++++++++-- lib/typed-events.ts | 17 ++ test/index.ts | 27 +++- ui/package-lock.json | 153 ++++++------------ ui/package.json | 5 +- ui/src/App.vue | 1 + .../components/Dashboard/BytesHistogram.vue | 113 +++++++++++++ .../components/Dashboard/ClientsOverview.vue | 55 +++++-- .../Dashboard/ConnectionsHistogram.vue | 113 +++++++++++++ ui/src/components/Dashboard/Doughnut.vue | 15 -- .../Dashboard/NamespacesOverview.vue | 21 ++- .../components/Dashboard/ServersOverview.vue | 20 ++- ui/src/components/NavigationDrawer.vue | 84 ++++++---- ui/src/locales/en.json | 10 +- ui/src/locales/fr.json | 10 +- ui/src/main.js | 1 + ui/src/plugins/chartjs.js | 22 +++ ui/src/store/modules/config.js | 11 ++ ui/src/store/modules/main.js | 39 ++++- ui/src/store/modules/servers.js | 18 +++ ui/src/views/Dashboard.vue | 26 ++- 21 files changed, 693 insertions(+), 192 deletions(-) create mode 100644 ui/src/components/Dashboard/BytesHistogram.vue create mode 100644 ui/src/components/Dashboard/ConnectionsHistogram.vue delete mode 100644 ui/src/components/Dashboard/Doughnut.vue create mode 100644 ui/src/plugins/chartjs.js diff --git a/lib/index.ts b/lib/index.ts index d8cef9b..a7d71a9 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -2,6 +2,8 @@ import { Namespace, RemoteSocket, Server, Socket } from "socket.io"; import { ClientEvents, Feature, + NamespaceDetails, + NamespaceEvent, SerializedSocket, ServerEvents, } from "./typed-events"; @@ -46,6 +48,10 @@ interface InstrumentOptions { * The store */ store: Store; + /** + * Whether to send all events or only aggregated events to the UI, for performance purposes. + */ + mode: "development" | "production"; } const initAuthenticationMiddleware = ( @@ -120,16 +126,26 @@ const initStatsEmitter = ( pid: process.pid, }; + const io = adminNamespace.server; + const emitStats = () => { debug("emit stats"); - // @ts-ignore private reference - const clientsCount = adminNamespace.server.engine.clientsCount; + const namespaces: NamespaceDetails[] = []; + io._nsps.forEach((namespace) => { + namespaces.push({ + name: namespace.name, + socketsCount: namespace.sockets.size, + }); + }); adminNamespace.emit( "server_stats", Object.assign({}, baseStats, { uptime: process.uptime(), - clientsCount, + clientsCount: io.engine.clientsCount, + pollingClientsCount: io._pollingClientsCount, + aggregatedEvents: io._eventBuffer.getValuesAndClear(), + namespaces, }) ); }; @@ -295,7 +311,7 @@ const registerFeatureHandlers = ( } }; -const registerListeners = ( +const registerVerboseListeners = ( adminNamespace: Namespace<{}, ServerEvents>, nsp: Namespace ) => { @@ -407,6 +423,81 @@ const serializeData = (data: any) => { return obj; }; +declare module "socket.io" { + interface Server { + _eventBuffer: EventBuffer; + _pollingClientsCount: number; + } +} + +class EventBuffer { + private buffer: Map = new Map(); + + public push(type: string, subType?: string, count = 1) { + const timestamp = new Date(); + timestamp.setMilliseconds(0); + const key = `${timestamp.getTime()};${type};${subType}`; + if (this.buffer.has(key)) { + this.buffer.get(key)!.count += count; + } else { + this.buffer.set(key, { + timestamp: timestamp.getTime(), + type, + subType, + count, + }); + } + } + + public getValuesAndClear() { + const values = [...this.buffer.values()]; + this.buffer.clear(); + return values; + } +} + +const registerEngineListeners = (io: Server) => { + io._eventBuffer = new EventBuffer(); + io._pollingClientsCount = 0; + + io.engine.on("connection", (rawSocket: any) => { + io._eventBuffer.push("rawConnection"); + + if (rawSocket.transport.name === "polling") { + io._pollingClientsCount++; + + const decr = () => { + io._pollingClientsCount--; + }; + + rawSocket.once("upgrade", () => { + rawSocket.removeListener("close", decr); + decr(); + }); + + rawSocket.once("close", decr); + } + + rawSocket.on("packetCreate", ({ data }: { data: string | Buffer }) => { + if (data) { + io._eventBuffer.push("packetsOut", undefined); + io._eventBuffer.push("bytesOut", undefined, Buffer.byteLength(data)); + } + }); + + rawSocket.on("packet", ({ data }: { data: string | Buffer }) => { + if (data) { + io._eventBuffer.push("packetsIn", undefined); + io._eventBuffer.push("bytesIn", undefined, Buffer.byteLength(data)); + } + }); + + rawSocket.on("close", (reason: string) => { + io._eventBuffer.push("rawDisconnection", reason); + }); + }); +}; + export function instrument(io: Server, opts: Partial) { const options: InstrumentOptions = Object.assign( { @@ -415,6 +506,7 @@ export function instrument(io: Server, opts: Partial) { readonly: false, serverId: undefined, store: new InMemoryStore(), + mode: process.env.NODE_ENV || "development", }, opts ); @@ -428,10 +520,13 @@ export function instrument(io: Server, opts: Partial) { initAuthenticationMiddleware(adminNamespace, options); const supportedFeatures = options.readonly ? [] : detectSupportedFeatures(io); + supportedFeatures.push(Feature.AGGREGATED_EVENTS); + const isDevelopmentMode = options.mode === "development"; + if (isDevelopmentMode) { + supportedFeatures.push(Feature.ALL_EVENTS); + } debug("supported features: %j", supportedFeatures); - initStatsEmitter(adminNamespace, options.serverId); - adminNamespace.on("connection", async (socket) => { registerFeatureHandlers(io, socket, supportedFeatures); @@ -439,11 +534,22 @@ export function instrument(io: Server, opts: Partial) { supportedFeatures, }); - socket.emit("all_sockets", await fetchAllSockets(io)); + if (isDevelopmentMode) { + socket.emit("all_sockets", await fetchAllSockets(io)); + } }); - io._nsps.forEach((nsp) => registerListeners(adminNamespace, nsp)); - io.on("new_namespace", (nsp) => registerListeners(adminNamespace, nsp)); + registerEngineListeners(io); + + if (isDevelopmentMode) { + const registerNamespaceListeners = (nsp: Namespace) => { + registerVerboseListeners(adminNamespace, nsp); + }; + io._nsps.forEach(registerNamespaceListeners); + io.on("new_namespace", registerNamespaceListeners); + } + + initStatsEmitter(adminNamespace, options.serverId); } export { InMemoryStore, RedisStore } from "./stores"; diff --git a/lib/typed-events.ts b/lib/typed-events.ts index 51cb8ec..62f13a1 100644 --- a/lib/typed-events.ts +++ b/lib/typed-events.ts @@ -7,18 +7,35 @@ export enum Feature { MJOIN = "MJOIN", MLEAVE = "MLEAVE", MDISCONNECT = "MDISCONNECT", + + AGGREGATED_EVENTS = "AGGREGATED_EVENTS", + ALL_EVENTS = "ALL_EVENTS", } interface Config { supportedFeatures: Feature[]; } +export type NamespaceEvent = { + timestamp: number; + type: string; + subType?: string; + count: number; +}; + +export type NamespaceDetails = { + name: string; + socketsCount: number; +}; + interface ServerStats { serverId: string; hostname: string; pid: number; uptime: number; clientsCount: number; + pollingClientsCount: number; + namespaces: NamespaceDetails[]; } export interface SerializedSocket { diff --git a/test/index.ts b/test/index.ts index ccf4b13..ff91704 100644 --- a/test/index.ts +++ b/test/index.ts @@ -3,7 +3,7 @@ import { Server } from "socket.io"; import { Server as ServerV3 } from "socket.io-v3"; import { io as ioc } from "socket.io-client"; import { AddressInfo } from "net"; -import { InMemoryStore, instrument, RedisStore } from ".."; +import { InMemoryStore, instrument, RedisStore } from "../lib"; import expect = require("expect.js"); import { createClient } from "redis"; @@ -189,6 +189,8 @@ describe("Socket.IO Admin (server instrumentation)", () => { "MJOIN", "MLEAVE", "MDISCONNECT", + "AGGREGATED_EVENTS", + "ALL_EVENTS", ]); } else { expect(config.supportedFeatures).to.eql([ @@ -196,6 +198,8 @@ describe("Socket.IO Admin (server instrumentation)", () => { "JOIN", "LEAVE", "DISCONNECT", + "AGGREGATED_EVENTS", + "ALL_EVENTS", ]); } adminSocket.disconnect(); @@ -212,7 +216,26 @@ describe("Socket.IO Admin (server instrumentation)", () => { const adminSocket = ioc(`http://localhost:${port}/admin`); adminSocket.on("config", (config: any) => { - expect(config.supportedFeatures).to.eql([]); + expect(config.supportedFeatures).to.eql([ + "AGGREGATED_EVENTS", + "ALL_EVENTS", + ]); + adminSocket.disconnect(); + done(); + }); + }); + + it("returns an empty list of supported features when in production mode", (done) => { + instrument(io, { + auth: false, + readonly: true, + mode: "production", + }); + + const adminSocket = ioc(`http://localhost:${port}/admin`); + + adminSocket.on("config", (config: any) => { + expect(config.supportedFeatures).to.eql(["AGGREGATED_EVENTS"]); adminSocket.disconnect(); done(); }); diff --git a/ui/package-lock.json b/ui/package-lock.json index 33c00bf..db4172f 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -8,9 +8,12 @@ "name": "ui", "version": "0.3.0", "dependencies": { + "chartjs-adapter-date-fns": "^2.0.0", "core-js": "^3.6.5", + "date-fns": "^2.28.0", "socket.io-msgpack-parser": "^3.0.1", "vue": "^2.6.11", + "vue-chartjs": "^4.1.1", "vue-i18n": "^8.22.3", "vue-router": "^3.2.0", "vuetify": "^2.4.0", @@ -24,7 +27,6 @@ "@vue/cli-service": "~4.5.0", "@vue/eslint-config-prettier": "^6.0.0", "babel-eslint": "^10.1.0", - "chart.js": "^2.9.4", "eslint": "^6.7.2", "eslint-plugin-prettier": "^3.3.1", "eslint-plugin-vue": "^6.2.2", @@ -34,7 +36,6 @@ "sass": "^1.32.0", "sass-loader": "^10.0.0", "socket.io-client": "^4.5.0", - "vue-chartjs": "^3.5.1", "vue-cli-plugin-i18n": "~2.0.3", "vue-cli-plugin-vuetify": "~2.3.1", "vue-template-compiler": "^2.6.11", @@ -1507,15 +1508,6 @@ "@types/node": "*" } }, - "node_modules/@types/chart.js": { - "version": "2.9.32", - "resolved": "https://registry.npmjs.org/@types/chart.js/-/chart.js-2.9.32.tgz", - "integrity": "sha512-d45JiRQwEOlZiKwukjqmqpbqbYzUX2yrXdH9qVn6kXpPDsTYCo6YbfFOlnUaJ8S/DhJwbBJiLsMjKpW5oP8B2A==", - "dev": true, - "dependencies": { - "moment": "^2.10.2" - } - }, "node_modules/@types/connect": { "version": "3.4.34", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz", @@ -3784,32 +3776,17 @@ "dev": true }, "node_modules/chart.js": { - "version": "2.9.4", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.4.tgz", - "integrity": "sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==", - "dev": true, - "dependencies": { - "chartjs-color": "^2.1.0", - "moment": "^2.10.2" - } + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.8.0.tgz", + "integrity": "sha512-cr8xhrXjLIXVLOBZPkBZVF6NDeiVIrPLHcMhnON7UufudL+CNeRrD+wpYanswlm8NpudMdrt3CHoLMQMxJhHRg==", + "peer": true }, - "node_modules/chartjs-color": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz", - "integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==", - "dev": true, - "dependencies": { - "chartjs-color-string": "^0.6.0", - "color-convert": "^1.9.3" - } - }, - "node_modules/chartjs-color-string": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz", - "integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==", - "dev": true, - "dependencies": { - "color-name": "^1.0.0" + "node_modules/chartjs-adapter-date-fns": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chartjs-adapter-date-fns/-/chartjs-adapter-date-fns-2.0.0.tgz", + "integrity": "sha512-rmZINGLe+9IiiEB0kb57vH3UugAtYw33anRiw5kS2Tu87agpetDDoouquycWc9pRsKtQo5j+vLsYHyr8etAvFw==", + "peerDependencies": { + "chart.js": "^3.0.0" } }, "node_modules/check-types": { @@ -5198,6 +5175,18 @@ "node": ">=0.10" } }, + "node_modules/date-fns": { + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz", + "integrity": "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==", + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, "node_modules/de-indent": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", @@ -9923,15 +9912,6 @@ "mkdirp": "bin/cmd.js" } }, - "node_modules/moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -14991,19 +14971,12 @@ "integrity": "sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg==" }, "node_modules/vue-chartjs": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-3.5.1.tgz", - "integrity": "sha512-foocQbJ7FtveICxb4EV5QuVpo6d8CmZFmAopBppDIGKY+esJV8IJgwmEW0RexQhxqXaL/E1xNURsgFFYyKzS/g==", - "dev": true, - "dependencies": { - "@types/chart.js": "^2.7.55" - }, - "engines": { - "node": ">=6.9.0", - "npm": ">= 3.0.0" - }, + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-4.1.1.tgz", + "integrity": "sha512-rKIQ3jPrjhwxjKdNJppnYxRuBSrx4QeM3nNHsfIxEqjX6QS4Jq6e6vnZBxh2MDpURDC2uvuI2N0eIt1cWXbBVA==", "peerDependencies": { - "chart.js": ">= 2.5" + "chart.js": "^3.7.0", + "vue": "^3.0.0-0 || ^2.6.0" } }, "node_modules/vue-cli-plugin-i18n": { @@ -17948,15 +17921,6 @@ "@types/node": "*" } }, - "@types/chart.js": { - "version": "2.9.32", - "resolved": "https://registry.npmjs.org/@types/chart.js/-/chart.js-2.9.32.tgz", - "integrity": "sha512-d45JiRQwEOlZiKwukjqmqpbqbYzUX2yrXdH9qVn6kXpPDsTYCo6YbfFOlnUaJ8S/DhJwbBJiLsMjKpW5oP8B2A==", - "dev": true, - "requires": { - "moment": "^2.10.2" - } - }, "@types/connect": { "version": "3.4.34", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz", @@ -19825,33 +19789,16 @@ "dev": true }, "chart.js": { - "version": "2.9.4", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.4.tgz", - "integrity": "sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==", - "dev": true, - "requires": { - "chartjs-color": "^2.1.0", - "moment": "^2.10.2" - } + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.8.0.tgz", + "integrity": "sha512-cr8xhrXjLIXVLOBZPkBZVF6NDeiVIrPLHcMhnON7UufudL+CNeRrD+wpYanswlm8NpudMdrt3CHoLMQMxJhHRg==", + "peer": true }, - "chartjs-color": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz", - "integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==", - "dev": true, - "requires": { - "chartjs-color-string": "^0.6.0", - "color-convert": "^1.9.3" - } - }, - "chartjs-color-string": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz", - "integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==", - "dev": true, - "requires": { - "color-name": "^1.0.0" - } + "chartjs-adapter-date-fns": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chartjs-adapter-date-fns/-/chartjs-adapter-date-fns-2.0.0.tgz", + "integrity": "sha512-rmZINGLe+9IiiEB0kb57vH3UugAtYw33anRiw5kS2Tu87agpetDDoouquycWc9pRsKtQo5j+vLsYHyr8etAvFw==", + "requires": {} }, "check-types": { "version": "8.0.3", @@ -20971,6 +20918,11 @@ "assert-plus": "^1.0.0" } }, + "date-fns": { + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz", + "integrity": "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==" + }, "de-indent": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", @@ -24695,12 +24647,6 @@ "minimist": "^1.2.5" } }, - "moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", - "dev": true - }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -28878,13 +28824,10 @@ "integrity": "sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg==" }, "vue-chartjs": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-3.5.1.tgz", - "integrity": "sha512-foocQbJ7FtveICxb4EV5QuVpo6d8CmZFmAopBppDIGKY+esJV8IJgwmEW0RexQhxqXaL/E1xNURsgFFYyKzS/g==", - "dev": true, - "requires": { - "@types/chart.js": "^2.7.55" - } + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-4.1.1.tgz", + "integrity": "sha512-rKIQ3jPrjhwxjKdNJppnYxRuBSrx4QeM3nNHsfIxEqjX6QS4Jq6e6vnZBxh2MDpURDC2uvuI2N0eIt1cWXbBVA==", + "requires": {} }, "vue-cli-plugin-i18n": { "version": "2.0.3", diff --git a/ui/package.json b/ui/package.json index 5df5287..79ddf4b 100644 --- a/ui/package.json +++ b/ui/package.json @@ -9,9 +9,12 @@ "i18n:report": "vue-cli-service i18n:report --src \"./src/**/*.?(js|vue)\" --locales \"./src/locales/**/*.json\"" }, "dependencies": { + "chartjs-adapter-date-fns": "^2.0.0", "core-js": "^3.6.5", + "date-fns": "^2.28.0", "socket.io-msgpack-parser": "^3.0.1", "vue": "^2.6.11", + "vue-chartjs": "^4.1.1", "vue-i18n": "^8.22.3", "vue-router": "^3.2.0", "vuetify": "^2.4.0", @@ -25,7 +28,6 @@ "@vue/cli-service": "~4.5.0", "@vue/eslint-config-prettier": "^6.0.0", "babel-eslint": "^10.1.0", - "chart.js": "^2.9.4", "eslint": "^6.7.2", "eslint-plugin-prettier": "^3.3.1", "eslint-plugin-vue": "^6.2.2", @@ -35,7 +37,6 @@ "sass": "^1.32.0", "sass-loader": "^10.0.0", "socket.io-client": "^4.5.0", - "vue-chartjs": "^3.5.1", "vue-cli-plugin-i18n": "~2.0.3", "vue-cli-plugin-vuetify": "~2.3.1", "vue-template-compiler": "^2.6.11", diff --git a/ui/src/App.vue b/ui/src/App.vue index 6338314..85acd73 100644 --- a/ui/src/App.vue +++ b/ui/src/App.vue @@ -154,6 +154,7 @@ export default { }); socket.on("server_stats", (serverStats) => { this.$store.commit("servers/onServerStats", serverStats); + this.$store.commit("main/onServerStats", serverStats); }); socket.on("all_sockets", (sockets) => { this.$store.commit("main/onAllSockets", sockets); diff --git a/ui/src/components/Dashboard/BytesHistogram.vue b/ui/src/components/Dashboard/BytesHistogram.vue new file mode 100644 index 0000000..a5a4b14 --- /dev/null +++ b/ui/src/components/Dashboard/BytesHistogram.vue @@ -0,0 +1,113 @@ + + + diff --git a/ui/src/components/Dashboard/ClientsOverview.vue b/ui/src/components/Dashboard/ClientsOverview.vue index b289f9e..1a46f21 100644 --- a/ui/src/components/Dashboard/ClientsOverview.vue +++ b/ui/src/components/Dashboard/ClientsOverview.vue @@ -10,7 +10,11 @@ - + diff --git a/ui/src/components/Dashboard/Doughnut.vue b/ui/src/components/Dashboard/Doughnut.vue deleted file mode 100644 index 7e5fcfd..0000000 --- a/ui/src/components/Dashboard/Doughnut.vue +++ /dev/null @@ -1,15 +0,0 @@ - diff --git a/ui/src/components/Dashboard/NamespacesOverview.vue b/ui/src/components/Dashboard/NamespacesOverview.vue index 8efde11..bb3340b 100644 --- a/ui/src/components/Dashboard/NamespacesOverview.vue +++ b/ui/src/components/Dashboard/NamespacesOverview.vue @@ -21,7 +21,7 @@ {{ namespace.name }} - {{ namespace.sockets.length }} + {{ namespace.socketsCount }} @@ -30,7 +30,7 @@ diff --git a/ui/src/components/Dashboard/ServersOverview.vue b/ui/src/components/Dashboard/ServersOverview.vue index 5a3acfc..1299a30 100644 --- a/ui/src/components/Dashboard/ServersOverview.vue +++ b/ui/src/components/Dashboard/ServersOverview.vue @@ -10,7 +10,11 @@ - +