diff --git a/grafana-dashboard.json b/grafana-dashboard.json new file mode 100644 index 0000000..e916c29 --- /dev/null +++ b/grafana-dashboard.json @@ -0,0 +1,424 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 7, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 2, + "panels": [], + "title": "All Server Stats", + "type": "row" + }, + { + "datasource": { + "type": "influxdb", + "uid": "face5ed9-19c5-419c-ac67-e80ed8945e49" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 0, + "y": 1 + }, + "id": 5, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.2.0", + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "face5ed9-19c5-419c-ac67-e80ed8945e49" + }, + "query": "from(bucket: \"mc-tracker\")\r\n |> range(start: -1h)\r\n |> filter(fn: (r) => r[\"_measurement\"] == \"playerCount\")\r\n |> filter(fn: (r) => r[\"_field\"] == \"playerCount\")\r\n |> last()\r\n |> map(fn: (r) => ({_value: r._value}))\r\n |> group(columns: [])\r\n |> sum()\r\n", + "refId": "A" + } + ], + "title": "Total Players Online (now)", + "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "face5ed9-19c5-419c-ac67-e80ed8945e49" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "displayName": "${__field.labels.name}", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 16, + "x": 4, + "y": 1 + }, + "id": 1, + "options": { + "legend": { + "calcs": ["min", "max", "mean"], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "face5ed9-19c5-419c-ac67-e80ed8945e49" + }, + "query": "from(bucket: \"mc-tracker\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r[\"_measurement\"] == \"playerCount\")\r\n |> filter(fn: (r) => r[\"_field\"] == \"playerCount\")\r\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\r\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Player Counts", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "face5ed9-19c5-419c-ac67-e80ed8945e49" + }, + "gridPos": { + "h": 10, + "w": 4, + "x": 20, + "y": 1 + }, + "id": 17, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "Tracking historical data for Minecraft servers, this was inspired by [Minetrack](https://github.com/Cryptkeeper/Minetrack).
\nPlease contact me on Discord if there is any issues: `fascinated7`.\n\nWant to add a server? Open a PR [here](https://git.fascinated.cc/Fascinated/mc-tracker/pulls)", + "mode": "markdown" + }, + "pluginVersion": "10.2.0", + "title": "Information", + "type": "text" + }, + { + "datasource": { + "type": "influxdb", + "uid": "face5ed9-19c5-419c-ac67-e80ed8945e49" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 0, + "y": 6 + }, + "id": 6, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.2.0", + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "face5ed9-19c5-419c-ac67-e80ed8945e49" + }, + "query": "from(bucket: \"mc-tracker\")\r\n |> range(start: -1mo)\r\n |> distinct(column: \"ip\")\r\n |> group()\r\n |> count()", + "refId": "A" + } + ], + "title": "Total Tracked Servers", + "type": "stat" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 11 + }, + "id": 3, + "panels": [], + "title": "Per Server Stats", + "type": "row" + }, + { + "datasource": { + "type": "influxdb", + "uid": "face5ed9-19c5-419c-ac67-e80ed8945e49" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "displayName": "Players Online", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 12 + }, + "id": 4, + "maxPerRow": 3, + "options": { + "legend": { + "calcs": ["max", "min", "mean"], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "repeat": "server", + "repeatDirection": "h", + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "face5ed9-19c5-419c-ac67-e80ed8945e49" + }, + "query": "from(bucket: \"mc-tracker\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r[\"_measurement\"] == \"playerCount\")\r\n |> filter(fn: (r) => r[\"_field\"] == \"playerCount\")\r\n |> filter(fn: (r) => r[\"name\"] == \"${server}\")\r\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\r\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Player Count (${server})", + "type": "timeseries" + } + ], + "refresh": "30s", + "schemaVersion": 38, + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": true, + "text": ["All"], + "value": ["$__all"] + }, + "datasource": { + "type": "influxdb", + "uid": "face5ed9-19c5-419c-ac67-e80ed8945e49" + }, + "definition": "from(bucket: \"mc-tracker\")\r\n |> range(start: -6h)\r\n |> group()\r\n |> distinct(column: \"name\")\r\n", + "hide": 2, + "includeAll": true, + "multi": true, + "name": "server", + "options": [], + "query": "from(bucket: \"mc-tracker\")\r\n |> range(start: -6h)\r\n |> group()\r\n |> distinct(column: \"name\")\r\n", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-30d", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Mc Tracker", + "uid": "c4d923ad-b588-4953-a302-2af1514fddd0", + "version": 26, + "weekStart": "" +} diff --git a/src/index.ts b/src/index.ts index d41efae..78e0026 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,20 +1,9 @@ import Influx from "./influx/influx"; -import Scanner from "./scanner/scanner"; import ServerManager from "./server/serverManager"; -/** - * The server manager instance. - */ -export const serverManager = new ServerManager(); - /** * The influx database instance. */ export const influx = new Influx(); -(async () => { - await serverManager.init(); - - // The scanner is responsible for scanning all servers - new Scanner(); -})(); +new ServerManager(); diff --git a/src/scanner/scanner.ts b/src/scanner/scanner.ts deleted file mode 100644 index 59948b0..0000000 --- a/src/scanner/scanner.ts +++ /dev/null @@ -1,27 +0,0 @@ -import cron from "node-cron"; - -import { serverManager } from ".."; -import Config from "../../data/config.json"; -import { logger } from "../utils/logger"; - -export default class Scanner { - constructor() { - cron.schedule(Config.scanner.updateCron, () => { - this.scanServers(); - }); - } - - /** - * Start a server scan to ping all servers. - */ - private async scanServers(): Promise { - logger.info(`Scanning servers ${serverManager.getServers().length}`); - - // ping all servers in parallel - await Promise.all( - serverManager.getServers().map((server) => server.pingServer()) - ); - - logger.info("Finished scanning servers"); - } -} diff --git a/src/server/server.ts b/src/server/server.ts index eb5c38d..86663d2 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -15,10 +15,6 @@ import { logger } from "../utils/logger"; */ export type ServerType = "PC" | "PE"; -export enum ServerStatus { - OFFLINE = "Unable to reach host", -} - type ServerOptions = { name: string; ip: string; @@ -52,11 +48,6 @@ export default class Server { */ private type: ServerType; - /** - * The favicon of the server. - */ - private favicon: string | undefined; - /** * The resolved server information from * DNS records for a PC server. @@ -148,12 +139,11 @@ export default class Server { const serverPing = new javaPing.MinecraftServer(ip, port); return new Promise((resolve, reject) => { - serverPing.ping(Config.scanner.timeout, 765, (err, res) => { + serverPing.ping(Config.pinger.timeout, 765, (err, res) => { if (err || res == undefined) { return reject(err); } - this.favicon = res.favicon; // Set the favicon resolve({ timestamp: Date.now(), ip: ip, @@ -224,13 +214,4 @@ export default class Server { public getType(): ServerType { return this.type; } - - /** - * Returns the favicon of the server. - * - * @returns the favicon - */ - public getFavicon(): string | undefined { - return this.favicon; - } } diff --git a/src/server/serverManager.ts b/src/server/serverManager.ts index af16b9b..b761847 100644 --- a/src/server/serverManager.ts +++ b/src/server/serverManager.ts @@ -1,18 +1,15 @@ +import cron from "node-cron"; +import { logger } from "../utils/logger"; import Server, { ServerType } from "./server"; +import Config from "../../data/config.json"; import Servers from "../../data/servers.json"; -import { logger } from "../utils/logger"; export default class ServerManager { private servers: Server[] = []; - constructor() {} - - /** - * Loads the servers from the config file. - */ - async init() { - logger.info("Loading servers"); + constructor() { + logger.info("Loading servers..."); for (const configServer of Servers) { const server = new Server({ ip: configServer.ip, @@ -21,7 +18,23 @@ export default class ServerManager { }); this.servers.push(server); } - logger.info(`Loaded ${this.servers.length} servers`); + logger.info(`Loaded ${this.servers.length} servers!`); + + cron.schedule(Config.pinger.pingCron, () => { + this.pingServers(); + }); + } + + /** + * Ping all servers to update their status. + */ + private async pingServers(): Promise { + logger.info(`Pinging servers ${this.servers.length}`); + + // ping all servers in parallel + await Promise.all(this.servers.map((server) => server.pingServer())); + + logger.info("Finished pinging servers"); } /**