diff --git a/assets/js/graph.js b/assets/js/graph.js index 8c72c97..058b10d 100644 --- a/assets/js/graph.js +++ b/assets/js/graph.js @@ -57,14 +57,15 @@ export class GraphDisplayManager { return } - // Trim any outdated entries by filtering the array into a new array - const startTimestamp = new Date().getTime() - const newGraphData = this._graphData[serverId].filter(point => startTimestamp - point[0] <= this._app.publicConfig.graphDuration) + const graphData = this._graphData[serverId] // Push the new data from the method call request - newGraphData.push([timestamp, playerCount]) + graphData.push([timestamp, playerCount]) - this._graphData[serverId] = newGraphData + // Trim any outdated entries by filtering the array into a new array + if (graphData.length > this._app.publicConfig.graphMaxLength) { + graphData.shift() + } } loadLocalStorage () { diff --git a/assets/js/servers.js b/assets/js/servers.js index 40cc517..1aee659 100644 --- a/assets/js/servers.js +++ b/assets/js/servers.js @@ -76,8 +76,6 @@ export class ServerRegistry { } } -const SERVER_GRAPH_DATA_MAX_LENGTH = 72 - export class ServerRegistration { playerCount = 0 isVisible = true @@ -100,12 +98,6 @@ export class ServerRegistration { // These points will be disregarded to prevent the graph starting at 0 player count points = points.filter(point => !point.error || !point.error.placeholder) - // The backend should never return more data elements than the max - // but trim the data result regardless for safety and performance purposes - if (points.length > SERVER_GRAPH_DATA_MAX_LENGTH) { - points.slice(points.length - SERVER_GRAPH_DATA_MAX_LENGTH, points.length) - } - for (let i = 0; i < points.length; i++) { const point = points[i] const timestamp = timestampPoints[i] @@ -127,7 +119,7 @@ export class ServerRegistration { this._graphData.push([timestamp, this.playerCount]) // Trim graphData to within the max length by shifting out the leading elements - if (this._graphData.length > SERVER_GRAPH_DATA_MAX_LENGTH) { + if (this._graphData.length > this._app.publicConfig.serverGraphMaxLength) { this._graphData.shift() } @@ -230,8 +222,6 @@ export class ServerRegistration { } initServerStatus (latestPing) { - const peakHourDuration = Math.floor(this._app.publicConfig.graphDuration / (60 * 60 * 1000)) + 'h Peak: ' - const serverElement = document.createElement('div') serverElement.id = 'container_' + this.serverId @@ -243,7 +233,7 @@ export class ServerRegistration { '

' + this.data.name + '

' + '' + 'Players: ' + - '' + peakHourDuration + '-' + + '' + this._app.publicConfig.graphDurationLabel + ' Peak: -' + 'Record: -' + '' + '' + diff --git a/assets/js/sort.js b/assets/js/sort.js index 74f7b89..ad6a25f 100644 --- a/assets/js/sort.js +++ b/assets/js/sort.js @@ -8,7 +8,7 @@ const SORT_OPTIONS = [ }, { getName: (app) => { - return Math.floor(app.publicConfig.graphDuration / (60 * 60 * 1000)) + 'h Peak' + return app.publicConfig.graphDurationLabel + ' Peak' }, sortFunc: (a, b) => { if (!a.lastPeakData && !b.lastPeakData) { diff --git a/config.json b/config.json index 33ac9bf..ce470b7 100644 --- a/config.json +++ b/config.json @@ -13,5 +13,6 @@ "skipUnfurlSrv": true }, "logToDatabase": true, - "graphDuration": 86400000 + "graphDuration": 86400000, + "serverGraphDuration": 180000 } diff --git a/lib/app.js b/lib/app.js index 28a302f..a94e238 100644 --- a/lib/app.js +++ b/lib/app.js @@ -15,7 +15,7 @@ class App { this.mojangUpdater = new MojangUpdater(this) this.pingController = new PingController(this) this.server = new Server(this.handleClientConnection) - this.timeTracker = new TimeTracker() + this.timeTracker = new TimeTracker(this) } loadDatabase (callback) { @@ -24,7 +24,7 @@ class App { // Setup database instance this.database.ensureIndexes() - this.database.loadGraphPoints(config.graphDuration, () => { + this.database.loadGraphPoints(this.pingController.getMaxGraphDataLength(), () => { this.database.loadRecords(callback) }) } @@ -68,7 +68,9 @@ class App { // Send configuration data for rendering the page return { - graphDuration: config.graphDuration, + graphDurationLabel: config.graphDurationLabel || (Math.floor(config.graphDuration / (60 * 60 * 1000)) + 'h'), + graphMaxLength: this.pingController.getMaxGraphDataLength(), + serverGraphMaxLength: this.pingController.getMaxServerGraphDataLength(), servers: this.serverRegistrations.map(serverRegistration => serverRegistration.data), minecraftVersions: minecraftVersionNames, isGraphVisible: config.logToDatabase diff --git a/lib/database.js b/lib/database.js index 821896a..aef9af9 100644 --- a/lib/database.js +++ b/lib/database.js @@ -14,27 +14,19 @@ class Database { }) } - loadGraphPoints (graphDuration, callback) { - // Query recent pings - const endTime = new Date().getTime() - const startTime = endTime - graphDuration - - this.getRecentPings(startTime, endTime, pingData => { + loadGraphPoints (length, callback) { + this.getRecentPings(length, pingData => { const graphPointsByIp = [] for (const row of pingData) { - // Avoid loading outdated records - // This shouldn't happen and is mostly a sanity measure - if (startTime - row.timestamp <= graphDuration) { - // Load into temporary array - // This will be culled prior to being pushed to the serverRegistration - let graphPoints = graphPointsByIp[row.ip] - if (!graphPoints) { - graphPoints = graphPointsByIp[row.ip] = [] - } - - graphPoints.push([row.timestamp, row.playerCount]) + // Load into temporary array + // This will be culled prior to being pushed to the serverRegistration + let graphPoints = graphPointsByIp[row.ip] + if (!graphPoints) { + graphPoints = graphPointsByIp[row.ip] = [] } + + graphPoints.push([row.timestamp, row.playerCount]) } Object.keys(graphPointsByIp).forEach(ip => { @@ -80,10 +72,9 @@ class Database { }) } - getRecentPings (startTime, endTime, callback) { - this._sql.all('SELECT * FROM pings WHERE timestamp >= ? AND timestamp <= ?', [ - startTime, - endTime + getRecentPings (length, callback) { + this._sql.all('SELECT * FROM pings WHERE 1 LIMIT ?', [ + length ], (_, data) => callback(data)) } diff --git a/lib/ping.js b/lib/ping.js index a9dda14..b19a37d 100644 --- a/lib/ping.js +++ b/lib/ping.js @@ -151,6 +151,14 @@ class PingController { }, version.protocolId) } } + + getMaxServerGraphDataLength () { + return Math.ceil(config.serverGraphDuration / config.rates.pingAll) + } + + getMaxGraphDataLength () { + return Math.ceil(config.graphDuration / config.rates.pingAll) + } } module.exports = PingController diff --git a/lib/servers.js b/lib/servers.js index f5c2f87..b5d51e7 100644 --- a/lib/servers.js +++ b/lib/servers.js @@ -1,8 +1,6 @@ const config = require('../config') const minecraftVersions = require('../minecraft_versions') -const SERVER_GRAPH_DATA_MAX_LENGTH = 72 - class ServerRegistration { serverId lastFavicon @@ -10,7 +8,8 @@ class ServerRegistration { recordData graphData = [] - constructor (serverId, data) { + constructor (app, serverId, data) { + this._app = app this.serverId = serverId this.data = data this._pingHistory = [] @@ -107,7 +106,7 @@ class ServerRegistration { this._pingHistory.push(ping) // Trim pingHistory to avoid memory leaks - if (this._pingHistory.length > SERVER_GRAPH_DATA_MAX_LENGTH) { + if (this._pingHistory.length > this._app.pingController.getMaxServerGraphDataLength()) { this._pingHistory.shift() } } @@ -203,9 +202,10 @@ class ServerRegistration { this.graphData.push([timestamp, playerCount]) this._lastGraphDataPush = timestamp - // Trim old graphPoints according to graphDuration - const filterTimestamp = new Date().getTime() - config.graphDuration - this.graphData = this.graphData.filter(point => point[0] >= filterTimestamp) + // Trim old graphPoints according to #getMaxGraphDataLength + if (this.graphData.length > this._app.pingController.getMaxGraphDataLength()) { + this.graphData.shift() + } return true } diff --git a/lib/time.js b/lib/time.js index a7ac7ec..1269b46 100644 --- a/lib/time.js +++ b/lib/time.js @@ -1,7 +1,6 @@ -const SERVER_GRAPH_DATA_MAX_LENGTH = require('./servers').SERVER_GRAPH_DATA_MAX_LENGTH - class TimeTracker { - constructor () { + constructor (app) { + this._app = app this._points = [] } @@ -10,7 +9,7 @@ class TimeTracker { this._points.push(timestamp) - if (this._points.length > SERVER_GRAPH_DATA_MAX_LENGTH) { + if (this._points.length > this._app.pingController.getMaxServerGraphDataLength()) { this._points.shift() } diff --git a/main.js b/main.js index e972b92..094e496 100644 --- a/main.js +++ b/main.js @@ -22,9 +22,14 @@ servers.forEach((server, serverId) => { } // Init a ServerRegistration instance of each entry in servers.json - app.serverRegistrations.push(new ServerRegistration(serverId, server)) + app.serverRegistrations.push(new ServerRegistration(app, serverId, server)) }) +if (!config.serverGraphDuration) { + logger.log('warn', '"serverGraphDuration" is not defined in config.json - defaulting to 3 minutes!') + config.serverGraphDuration = 3 * 60 * 10000 +} + if (config.performance && config.performance.skipUnfurlSrv) { logger.log('warn', '"performance.skipUnfurlSrv" is enabled. Any configured hosts using SRV records may not properly resolve.') }