mirror of
https://github.com/Sithranduil/srcds_exporter.git
synced 2025-07-23 08:28:00 +02:00
feat: add support for source 2
This commit is contained in:
9
index.js
9
index.js
@@ -1,6 +1,6 @@
|
|||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { connect } from 'working-rcon';
|
|
||||||
import module from './modules/index.js';
|
import module from './modules/index.js';
|
||||||
|
import SourceRcon from '@hellz.fr/sourcecon';
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
@@ -30,16 +30,17 @@ app.get('/metrics', async (req, res) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!['csgo', 'cstrike', 'gmod'].includes(config.game)) {
|
if (!['csgo', 'cstrike', 'gmod', 'cs2'].includes(config.game)) {
|
||||||
res.send('Incorrect game value, currently supported games are : csgo, gmod, cstrike');
|
res.send('Incorrect game value, currently supported games are : csgo, gmod, cstrike');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const client = await connect(config.ip, config.port, config.rconPassword, 5000);
|
const client = new SourceRcon.default(config.ip, Number.parseInt(config.port));
|
||||||
|
await client.connect();
|
||||||
|
await client.auth(config.rconPassword);
|
||||||
const response = await module.request(config, client);
|
const response = await module.request(config, client);
|
||||||
await module.send(config, response, res);
|
await module.send(config, response, res);
|
||||||
await client.disconnect();
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.code === 'EHOSTUNREACH') {
|
if (e.code === 'EHOSTUNREACH') {
|
||||||
console.error(`Unreachable host : ${e.address}:${e.port}`);
|
console.error(`Unreachable host : ${e.address}:${e.port}`);
|
||||||
|
@@ -6,6 +6,8 @@ export default {
|
|||||||
const stats = await utils.rconCommand(client, 'status');
|
const stats = await utils.rconCommand(client, 'status');
|
||||||
let statusLine = null;
|
let statusLine = null;
|
||||||
let res = null;
|
let res = null;
|
||||||
|
let tv = null;
|
||||||
|
let regexStatus = null;
|
||||||
if (stats) {
|
if (stats) {
|
||||||
statusLine = stats.split(/\r?\n/);
|
statusLine = stats.split(/\r?\n/);
|
||||||
} else {
|
} else {
|
||||||
@@ -17,32 +19,70 @@ export default {
|
|||||||
statusLine.shift();
|
statusLine.shift();
|
||||||
statusLine.shift();
|
statusLine.shift();
|
||||||
statusLine.shift();
|
statusLine.shift();
|
||||||
if (game === 'csgo') {
|
|
||||||
if (statusLine[0].search('gotv') !== -1) {
|
if (game === "csgo") {
|
||||||
statusLine.shift();
|
tv = "gotv";
|
||||||
}
|
regexStatus = /players : (\d+) humans, (\d+) bots \((\d+)\/0 max\)/;
|
||||||
res = statusLine[0].split(/players : (\d+) humans, (\d+) bots \((\d+)\/0 max\)/);
|
} else {
|
||||||
} else {
|
tv = "sourcetv";
|
||||||
if (statusLine[0].search('sourcetv') !== -1) {
|
regexStatus = /players : (\d+) humans, (\d+) bots \((\d+) max\)/;
|
||||||
statusLine.shift();
|
}
|
||||||
}
|
|
||||||
res = statusLine[0].split(/players : (\d+) humans, (\d+) bots \((\d+) max\)/);
|
|
||||||
}
|
if (statusLine[0].search(tv) !== -1) {
|
||||||
res.pop();
|
statusLine.shift();
|
||||||
res.shift();
|
}
|
||||||
|
res = statusLine[0].split(regexStatus);
|
||||||
|
res.pop();
|
||||||
|
res.shift();
|
||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
setStatusMetrics(response) {
|
async requestStatusCs2(client, game) {
|
||||||
let players = 0;
|
let stats = await utils.rconCommand(client, 'status_json');
|
||||||
let bots = 0;
|
stats = JSON.parse(stats)
|
||||||
let maxPlayers = 0;
|
return stats;
|
||||||
if (response) {
|
},
|
||||||
[players, bots, maxPlayers] = response;
|
setStatusMetrics(response) {
|
||||||
}
|
let players = 0;
|
||||||
metrics.players.set((Number(players)));
|
let bots = 0;
|
||||||
metrics.bots.set((Number(bots)));
|
let maxPlayers = 0;
|
||||||
metrics.maxPlayers.set((Number(maxPlayers)));
|
if (response) {
|
||||||
},
|
[players, bots, maxPlayers] = response;
|
||||||
|
}
|
||||||
|
metrics.players.set((Number(players)));
|
||||||
|
metrics.bots.set((Number(bots)));
|
||||||
|
metrics.maxPlayers.set((Number(maxPlayers)));
|
||||||
|
},
|
||||||
|
setCs2StatusMetrics(response) {
|
||||||
|
let clients_human = 0;
|
||||||
|
let clients_bot = 0;
|
||||||
|
let cpu = 0;
|
||||||
|
let status = 0;
|
||||||
|
let uptime = 0;
|
||||||
|
let maps = '';
|
||||||
|
if (response) {
|
||||||
|
let { server } = response;
|
||||||
|
uptime = response.process_uptime
|
||||||
|
clients_human = server.clients_human;
|
||||||
|
clients_bot = server.clients_bot;
|
||||||
|
cpu = server.cpu_usage;
|
||||||
|
maps = server.maps;
|
||||||
|
status = 1;
|
||||||
|
}
|
||||||
|
metrics.players.set((Number(clients_human)));
|
||||||
|
metrics.bots.set((Number(clients_bot)));
|
||||||
|
//metrics.maxPlayers.set((Number(maxPlayers)));
|
||||||
|
metrics.status.set((Number(status)));
|
||||||
|
metrics.cpu.set((Number(cpu)));
|
||||||
|
//metrics.netin.set((Number(netin)));
|
||||||
|
//metrics.netout.set((Number(netout)));
|
||||||
|
metrics.uptime.set((Number(uptime)));
|
||||||
|
//metrics.maps.set((Number(maps)));
|
||||||
|
// metrics.fps.set((Number(fps)));
|
||||||
|
// metrics.svms.set((Number(svms)));
|
||||||
|
// metrics.varms.set((Number(varms)));
|
||||||
|
//metrics.svMaxUpdateRate.set((Number(maxUpdateRate)));
|
||||||
|
},
|
||||||
async requestStats(client, game) {
|
async requestStats(client, game) {
|
||||||
const stats = await utils.rconCommand(client, 'stats');
|
const stats = await utils.rconCommand(client, 'stats');
|
||||||
let statusLine = null;
|
let statusLine = null;
|
||||||
|
@@ -35,10 +35,17 @@ export default {
|
|||||||
let metamodResponse;
|
let metamodResponse;
|
||||||
let sourcemodResponse;
|
let sourcemodResponse;
|
||||||
let sourcepythonResponse;
|
let sourcepythonResponse;
|
||||||
|
let infoResponse;
|
||||||
|
let statsResponse;
|
||||||
|
let statusResponse;
|
||||||
|
|
||||||
const infoResponse = await game.requeseInfo(client, config.game);
|
if (config.game === 'cs2') {
|
||||||
const statsResponse = await game.requestStats(client, config.game);
|
statusResponse = await game.requestStatusCs2(client, config.game);
|
||||||
const statusResponse = await game.requestStatus(client, config.game);
|
} else {
|
||||||
|
infoResponse = await game.requeseInfo(client, config.game);
|
||||||
|
statsResponse = await game.requestStats(client, config.game);
|
||||||
|
statusResponse = await game.requestStatus(client, config.game);
|
||||||
|
}
|
||||||
if (config.metamod) {
|
if (config.metamod) {
|
||||||
metamodResponse = await metamod.request(client);
|
metamodResponse = await metamod.request(client);
|
||||||
}
|
}
|
||||||
@@ -64,10 +71,12 @@ export default {
|
|||||||
sourcemod.setMetrics(response ? response.sourcemod : null);
|
sourcemod.setMetrics(response ? response.sourcemod : null);
|
||||||
sourcepython.setMetrics(response ? response.sourcepython : null);
|
sourcepython.setMetrics(response ? response.sourcepython : null);
|
||||||
gametracker.setMetrics(response ? response.gametracker : null);
|
gametracker.setMetrics(response ? response.gametracker : null);
|
||||||
game.setStatsMetrics(response ? response.stats : null, config.game);
|
if (config.game !== 'cs2') {
|
||||||
game.setInfoMetrics(response ? response.info : null);
|
game.setStatsMetrics(response ? response.stats : null, config.game);
|
||||||
game.setStatusMetrics(response ? response.status : null);
|
game.setInfoMetrics(response ? response.info : null);
|
||||||
|
} else {
|
||||||
|
game.setCs2StatusMetrics(response ? response.status : null);
|
||||||
|
}
|
||||||
registry.setDefaultLabels(
|
registry.setDefaultLabels(
|
||||||
config.ip,
|
config.ip,
|
||||||
config.port,
|
config.port,
|
||||||
@@ -77,7 +86,6 @@ export default {
|
|||||||
response ? response.sourcemod : null,
|
response ? response.sourcemod : null,
|
||||||
response ? response.sourcepython : null,
|
response ? response.sourcepython : null,
|
||||||
);
|
);
|
||||||
|
|
||||||
registry.sendMetrics(config.game, res);
|
registry.sendMetrics(config.game, res);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@@ -4,16 +4,19 @@ import utils from '../utils/utils.js';
|
|||||||
const csgoRegistry = new prometheus.Registry();
|
const csgoRegistry = new prometheus.Registry();
|
||||||
const gmodRegistry = new prometheus.Registry();
|
const gmodRegistry = new prometheus.Registry();
|
||||||
const cstrikeRegistry = new prometheus.Registry();
|
const cstrikeRegistry = new prometheus.Registry();
|
||||||
|
const cs2Registry = new prometheus.Registry();
|
||||||
const allGameMetrics = [
|
const allGameMetrics = [
|
||||||
csgoRegistry,
|
csgoRegistry,
|
||||||
gmodRegistry,
|
gmodRegistry,
|
||||||
cstrikeRegistry,
|
cstrikeRegistry,
|
||||||
|
cs2Registry,
|
||||||
];
|
];
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
csgoRegistry,
|
csgoRegistry,
|
||||||
gmodRegistry,
|
gmodRegistry,
|
||||||
cstrikeRegistry,
|
cstrikeRegistry,
|
||||||
|
cs2Registry,
|
||||||
allGameMetrics,
|
allGameMetrics,
|
||||||
|
|
||||||
setDefaultLabels(ip, port, game, tags, metamodResponse, sourcemodResponse, sourcepythonResponse) {
|
setDefaultLabels(ip, port, game, tags, metamodResponse, sourcemodResponse, sourcepythonResponse) {
|
||||||
@@ -36,9 +39,11 @@ export default {
|
|||||||
const version = line.replace('SP version : ', '').trim();
|
const version = line.replace('SP version : ', '').trim();
|
||||||
defaultLabels.sourcepython = version;
|
defaultLabels.sourcepython = version;
|
||||||
}
|
}
|
||||||
if (game === 'csgo') {
|
if (game === 'cs2') {
|
||||||
csgoRegistry.setDefaultLabels(defaultLabels);
|
cs2Registry.setDefaultLabels(defaultLabels);
|
||||||
} else if (game === 'cstrike') {
|
} else if (game === 'csgo') {
|
||||||
|
csgoRegistry.setDefaultLabels(defaultLabels);
|
||||||
|
} else if (game === 'cstrike') {
|
||||||
cstrikeRegistry.setDefaultLabels(defaultLabels);
|
cstrikeRegistry.setDefaultLabels(defaultLabels);
|
||||||
} else if (game === 'gmod') {
|
} else if (game === 'gmod') {
|
||||||
gmodRegistry.setDefaultLabels(defaultLabels);
|
gmodRegistry.setDefaultLabels(defaultLabels);
|
||||||
@@ -46,9 +51,11 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
sendMetrics(game, res) {
|
sendMetrics(game, res) {
|
||||||
if (game === 'csgo') {
|
if (game === 'cs2') {
|
||||||
res.end(csgoRegistry.metrics());
|
res.end(cs2Registry.metrics());
|
||||||
} else if (game === 'cstrike') {
|
} else if (game === 'csgo') {
|
||||||
|
res.end(csgoRegistry.metrics());
|
||||||
|
} else if (game === 'cstrike') {
|
||||||
res.end(cstrikeRegistry.metrics());
|
res.end(cstrikeRegistry.metrics());
|
||||||
} else if (game === 'gmod') {
|
} else if (game === 'gmod') {
|
||||||
res.end(gmodRegistry.metrics());
|
res.end(gmodRegistry.metrics());
|
||||||
|
18
package.json
18
package.json
@@ -11,28 +11,24 @@
|
|||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/Unyxos/srcds-exporter.git"
|
"url": "git+https://github.com/Sithranduil/srcds-exporter.git"
|
||||||
},
|
},
|
||||||
"author": "Corentin Closs <me@corentincloss.fr>",
|
"author": "Corentin Closs <me@corentincloss.fr>, Sithranduil",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/Unyxos/srcds-exporter/issues"
|
"url": "https://github.com/Sithranduil/srcds-exporter/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/Unyxos/srcds-exporter#readme",
|
"homepage": "https://github.com/Sithranduil/srcds-exporter#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@hellz.fr/sourcecon": "^1.0.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"got": "^11.8.0",
|
"got": "^11.8.0",
|
||||||
"jsdom": "^16.4.0",
|
"jsdom": "^16.4.0",
|
||||||
"prom-client": "^11.5.3",
|
"prom-client": "^11.5.3"
|
||||||
"srcds-rcon": "^2.2.1",
|
|
||||||
"working-rcon": "^0.2.8"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^7.2.0",
|
"eslint": "^7.2.0",
|
||||||
"eslint-config-airbnb": "^18.2.0",
|
"eslint-config-airbnb": "^18.2.0",
|
||||||
"eslint-plugin-import": "^2.22.1",
|
"eslint-plugin-import": "^2.22.1"
|
||||||
"eslint-plugin-jsx-a11y": "^6.3.1",
|
|
||||||
"eslint-plugin-react": "^7.21.3",
|
|
||||||
"eslint-plugin-react-hooks": "^4.0.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
import { TimeoutError } from 'working-rcon';
|
|
||||||
import got from 'got';
|
import got from 'got';
|
||||||
import jsdom from 'jsdom';
|
import jsdom from 'jsdom';
|
||||||
|
|
||||||
@@ -22,13 +21,9 @@ export default {
|
|||||||
},
|
},
|
||||||
async rconCommand(client, command) {
|
async rconCommand(client, command) {
|
||||||
try {
|
try {
|
||||||
return client.command(command);
|
return client.send(command);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof TimeoutError) {
|
|
||||||
console.error('request timed out');
|
|
||||||
} else {
|
|
||||||
throw err;
|
throw err;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user