add serverGraphDuration config option

This commit is contained in:
Nick Krecklow 2020-05-08 01:54:04 -05:00
parent aee7b565b2
commit f467fa1938
No known key found for this signature in database
GPG Key ID: 5F149FDE156FFA94
10 changed files with 52 additions and 55 deletions

@ -57,14 +57,15 @@ export class GraphDisplayManager {
return return
} }
// Trim any outdated entries by filtering the array into a new array const graphData = this._graphData[serverId]
const startTimestamp = new Date().getTime()
const newGraphData = this._graphData[serverId].filter(point => startTimestamp - point[0] <= this._app.publicConfig.graphDuration)
// Push the new data from the method call request // 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 () { loadLocalStorage () {

@ -76,8 +76,6 @@ export class ServerRegistry {
} }
} }
const SERVER_GRAPH_DATA_MAX_LENGTH = 72
export class ServerRegistration { export class ServerRegistration {
playerCount = 0 playerCount = 0
isVisible = true isVisible = true
@ -100,12 +98,6 @@ export class ServerRegistration {
// These points will be disregarded to prevent the graph starting at 0 player count // These points will be disregarded to prevent the graph starting at 0 player count
points = points.filter(point => !point.error || !point.error.placeholder) 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++) { for (let i = 0; i < points.length; i++) {
const point = points[i] const point = points[i]
const timestamp = timestampPoints[i] const timestamp = timestampPoints[i]
@ -127,7 +119,7 @@ export class ServerRegistration {
this._graphData.push([timestamp, this.playerCount]) this._graphData.push([timestamp, this.playerCount])
// Trim graphData to within the max length by shifting out the leading elements // 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() this._graphData.shift()
} }
@ -230,8 +222,6 @@ export class ServerRegistration {
} }
initServerStatus (latestPing) { initServerStatus (latestPing) {
const peakHourDuration = Math.floor(this._app.publicConfig.graphDuration / (60 * 60 * 1000)) + 'h Peak: '
const serverElement = document.createElement('div') const serverElement = document.createElement('div')
serverElement.id = 'container_' + this.serverId serverElement.id = 'container_' + this.serverId
@ -243,7 +233,7 @@ export class ServerRegistration {
'<h3 class="server-name"><span class="' + this._app.favoritesManager.getIconClass(this.isFavorite) + '" id="favorite-toggle_' + this.serverId + '"></span> ' + this.data.name + '</h3>' + '<h3 class="server-name"><span class="' + this._app.favoritesManager.getIconClass(this.isFavorite) + '" id="favorite-toggle_' + this.serverId + '"></span> ' + this.data.name + '</h3>' +
'<span class="server-error" id="error_' + this.serverId + '"></span>' + '<span class="server-error" id="error_' + this.serverId + '"></span>' +
'<span class="server-label" id="player-count_' + this.serverId + '">Players: <span class="server-value" id="player-count-value_' + this.serverId + '"></span></span>' + '<span class="server-label" id="player-count_' + this.serverId + '">Players: <span class="server-value" id="player-count-value_' + this.serverId + '"></span></span>' +
'<span class="server-label" id="peak_' + this.serverId + '">' + peakHourDuration + '<span class="server-value" id="peak-value_' + this.serverId + '">-</span></span>' + '<span class="server-label" id="peak_' + this.serverId + '">' + this._app.publicConfig.graphDurationLabel + ' Peak: <span class="server-value" id="peak-value_' + this.serverId + '">-</span></span>' +
'<span class="server-label" id="record_' + this.serverId + '">Record: <span class="server-value" id="record-value_' + this.serverId + '">-</span></span>' + '<span class="server-label" id="record_' + this.serverId + '">Record: <span class="server-value" id="record-value_' + this.serverId + '">-</span></span>' +
'<span class="server-label" id="version_' + this.serverId + '"></span>' + '<span class="server-label" id="version_' + this.serverId + '"></span>' +
'</div>' + '</div>' +

@ -8,7 +8,7 @@ const SORT_OPTIONS = [
}, },
{ {
getName: (app) => { getName: (app) => {
return Math.floor(app.publicConfig.graphDuration / (60 * 60 * 1000)) + 'h Peak' return app.publicConfig.graphDurationLabel + ' Peak'
}, },
sortFunc: (a, b) => { sortFunc: (a, b) => {
if (!a.lastPeakData && !b.lastPeakData) { if (!a.lastPeakData && !b.lastPeakData) {

@ -13,5 +13,6 @@
"skipUnfurlSrv": true "skipUnfurlSrv": true
}, },
"logToDatabase": true, "logToDatabase": true,
"graphDuration": 86400000 "graphDuration": 86400000,
"serverGraphDuration": 180000
} }

@ -15,7 +15,7 @@ class App {
this.mojangUpdater = new MojangUpdater(this) this.mojangUpdater = new MojangUpdater(this)
this.pingController = new PingController(this) this.pingController = new PingController(this)
this.server = new Server(this.handleClientConnection) this.server = new Server(this.handleClientConnection)
this.timeTracker = new TimeTracker() this.timeTracker = new TimeTracker(this)
} }
loadDatabase (callback) { loadDatabase (callback) {
@ -24,7 +24,7 @@ class App {
// Setup database instance // Setup database instance
this.database.ensureIndexes() this.database.ensureIndexes()
this.database.loadGraphPoints(config.graphDuration, () => { this.database.loadGraphPoints(this.pingController.getMaxGraphDataLength(), () => {
this.database.loadRecords(callback) this.database.loadRecords(callback)
}) })
} }
@ -68,7 +68,9 @@ class App {
// Send configuration data for rendering the page // Send configuration data for rendering the page
return { 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), servers: this.serverRegistrations.map(serverRegistration => serverRegistration.data),
minecraftVersions: minecraftVersionNames, minecraftVersions: minecraftVersionNames,
isGraphVisible: config.logToDatabase isGraphVisible: config.logToDatabase

@ -14,18 +14,11 @@ class Database {
}) })
} }
loadGraphPoints (graphDuration, callback) { loadGraphPoints (length, callback) {
// Query recent pings this.getRecentPings(length, pingData => {
const endTime = new Date().getTime()
const startTime = endTime - graphDuration
this.getRecentPings(startTime, endTime, pingData => {
const graphPointsByIp = [] const graphPointsByIp = []
for (const row of pingData) { 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 // Load into temporary array
// This will be culled prior to being pushed to the serverRegistration // This will be culled prior to being pushed to the serverRegistration
let graphPoints = graphPointsByIp[row.ip] let graphPoints = graphPointsByIp[row.ip]
@ -35,7 +28,6 @@ class Database {
graphPoints.push([row.timestamp, row.playerCount]) graphPoints.push([row.timestamp, row.playerCount])
} }
}
Object.keys(graphPointsByIp).forEach(ip => { Object.keys(graphPointsByIp).forEach(ip => {
// Match IPs to serverRegistration object // Match IPs to serverRegistration object
@ -80,10 +72,9 @@ class Database {
}) })
} }
getRecentPings (startTime, endTime, callback) { getRecentPings (length, callback) {
this._sql.all('SELECT * FROM pings WHERE timestamp >= ? AND timestamp <= ?', [ this._sql.all('SELECT * FROM pings WHERE 1 LIMIT ?', [
startTime, length
endTime
], (_, data) => callback(data)) ], (_, data) => callback(data))
} }

@ -151,6 +151,14 @@ class PingController {
}, version.protocolId) }, version.protocolId)
} }
} }
getMaxServerGraphDataLength () {
return Math.ceil(config.serverGraphDuration / config.rates.pingAll)
}
getMaxGraphDataLength () {
return Math.ceil(config.graphDuration / config.rates.pingAll)
}
} }
module.exports = PingController module.exports = PingController

@ -1,8 +1,6 @@
const config = require('../config') const config = require('../config')
const minecraftVersions = require('../minecraft_versions') const minecraftVersions = require('../minecraft_versions')
const SERVER_GRAPH_DATA_MAX_LENGTH = 72
class ServerRegistration { class ServerRegistration {
serverId serverId
lastFavicon lastFavicon
@ -10,7 +8,8 @@ class ServerRegistration {
recordData recordData
graphData = [] graphData = []
constructor (serverId, data) { constructor (app, serverId, data) {
this._app = app
this.serverId = serverId this.serverId = serverId
this.data = data this.data = data
this._pingHistory = [] this._pingHistory = []
@ -107,7 +106,7 @@ class ServerRegistration {
this._pingHistory.push(ping) this._pingHistory.push(ping)
// Trim pingHistory to avoid memory leaks // 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() this._pingHistory.shift()
} }
} }
@ -203,9 +202,10 @@ class ServerRegistration {
this.graphData.push([timestamp, playerCount]) this.graphData.push([timestamp, playerCount])
this._lastGraphDataPush = timestamp this._lastGraphDataPush = timestamp
// Trim old graphPoints according to graphDuration // Trim old graphPoints according to #getMaxGraphDataLength
const filterTimestamp = new Date().getTime() - config.graphDuration if (this.graphData.length > this._app.pingController.getMaxGraphDataLength()) {
this.graphData = this.graphData.filter(point => point[0] >= filterTimestamp) this.graphData.shift()
}
return true return true
} }

@ -1,7 +1,6 @@
const SERVER_GRAPH_DATA_MAX_LENGTH = require('./servers').SERVER_GRAPH_DATA_MAX_LENGTH
class TimeTracker { class TimeTracker {
constructor () { constructor (app) {
this._app = app
this._points = [] this._points = []
} }
@ -10,7 +9,7 @@ class TimeTracker {
this._points.push(timestamp) this._points.push(timestamp)
if (this._points.length > SERVER_GRAPH_DATA_MAX_LENGTH) { if (this._points.length > this._app.pingController.getMaxServerGraphDataLength()) {
this._points.shift() this._points.shift()
} }

@ -22,9 +22,14 @@ servers.forEach((server, serverId) => {
} }
// Init a ServerRegistration instance of each entry in servers.json // 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) { if (config.performance && config.performance.skipUnfurlSrv) {
logger.log('warn', '"performance.skipUnfurlSrv" is enabled. Any configured hosts using SRV records may not properly resolve.') logger.log('warn', '"performance.skipUnfurlSrv" is enabled. Any configured hosts using SRV records may not properly resolve.')
} }