mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-15 07:24:52 +09:00
Added new plugin for reporting production/kills/construction statistics to Prometheus
This commit is contained in:
1 parent
aaf4d8b6f1
commit
52d35ab955
4 files changed
+127
No files matched your search
@@ -0,0 +1,19 @@
|
||||
local statisticsData = "["
|
||||
for _, force in pairs(game.forces) do
|
||||
statisticsData = statisticsData .. '{"forceName":"'..force.name..'","data":{'
|
||||
local statistics = {"item_production_statistics", "fluid_production_statistics", "kill_count_statistics", "entity_build_count_statistics"}
|
||||
for key, stat in pairs(statistics) do
|
||||
statisticsData = statisticsData..'"'..stat..'":{"input":{'
|
||||
for name, value in pairs(force[stat].input_counts) do
|
||||
statisticsData = statisticsData..'"'..name..'":'..value..','
|
||||
end
|
||||
statisticsData = statisticsData..'},"output":{'
|
||||
for name, value in pairs(force[stat].output_counts) do
|
||||
statisticsData = statisticsData..'"'..name..'":'..value..','
|
||||
end
|
||||
statisticsData = statisticsData .. '}},'
|
||||
end
|
||||
statisticsData = statisticsData..'}},'
|
||||
end
|
||||
statisticsData = statisticsData..']'
|
||||
rcon.print(statisticsData)
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
Clusterio plugin for gathering ingame statistics
|
||||
*/
|
||||
module.exports = {
|
||||
name: "statisticsExporter",
|
||||
version: "1.0.0",
|
||||
binary: "nodePackage",
|
||||
description: "Gathers ingame stats such as production, consumption, kills and buildings placed",
|
||||
masterPlugin: "masterPlugin.js"
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
const needle = require("needle");
|
||||
const fs = require("fs-extra");
|
||||
const path = require("path");
|
||||
|
||||
const clusterTools = require("_app/clusterTools")();
|
||||
const pluginConfig = require("./config");
|
||||
|
||||
module.exports = class remoteCommands {
|
||||
constructor(mergedConfig, messageInterface, extras){
|
||||
this.messageInterface = messageInterface;
|
||||
this.config = mergedConfig;
|
||||
|
||||
const needleOptionsWithTokenAuthHeader = {
|
||||
headers: {
|
||||
'x-access-token': this.config.masterAuthToken
|
||||
},
|
||||
};
|
||||
|
||||
// Gather and submit statistics every 15 seconds
|
||||
setInterval(async () => {
|
||||
let stats = await this.getStats();
|
||||
stats.forEach(force => {
|
||||
needle.post(`${mergedConfig.masterIP}:${mergedConfig.masterPort}/api/logStats`, {
|
||||
instanceID: this.config.unique,
|
||||
force: force.forceName,
|
||||
data: force.data,
|
||||
}, needleOptionsWithTokenAuthHeader, (err, resp) => {
|
||||
if(!err && resp.body && resp.body.ok == false) console.log(resp.body);
|
||||
});
|
||||
});
|
||||
}, 15000);
|
||||
}
|
||||
async getStats(){
|
||||
let command = fs.readFileSync(path.join(__dirname, "Lua/exportStatistics.lua"), "utf8")//clusterTools.getLua(path.join(__dirname, "Lua/exportStatistics.lua"), false);
|
||||
let string = await this.messageInterface(`/silent-command ${command}`);
|
||||
var data;
|
||||
eval(`data = ${string}`);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
const fs = require("fs-extra");
|
||||
const path = require("path");
|
||||
|
||||
class masterPlugin {
|
||||
constructor({config, socketio, express, Prometheus}){
|
||||
const authenticate = require("./../../lib/authenticate")(config);
|
||||
|
||||
this.config = config;
|
||||
this.io = socketio;
|
||||
const app = express;
|
||||
|
||||
const prometheusStatisticsGauge = new Prometheus.Gauge({
|
||||
name: 'clusterio_statistics_gauge',
|
||||
help: 'Items produced/built/killed by a force',
|
||||
labelNames: ["instanceID", "force", "statistic", "direction", "itemName"],
|
||||
});
|
||||
|
||||
/** --- TODO: Replace this with a simpler Prometheus exporter. Requires changes to the mod as well.
|
||||
POST endpoint to log production graph statistics. Should contain an instanceID (also reffered to as "unique")
|
||||
and of course the timeSeries data organized by category.
|
||||
|
||||
@memberof clusterioMaster
|
||||
@instance
|
||||
@alias api/logStats
|
||||
@param {object} JSON {instanceID: "string", force: "string" data: {"item_production_statistics": {"input":{"iron-plate":150}, "output":{}}, ...}}
|
||||
@returns {string} failure
|
||||
*/
|
||||
app.post("/api/logStats", authenticate.middleware, function(req,res) {
|
||||
// endpointHitCounter.labels(req.route.path).inc();
|
||||
if(typeof req.body == "object"
|
||||
&& req.body.instanceID
|
||||
&& typeof req.body.instanceID == "string"
|
||||
&& req.body.instanceID.length < 100
|
||||
&& req.body.data
|
||||
&& typeof req.body.data == "object"
|
||||
&& !Array.isArray(req.body.data)){
|
||||
try{
|
||||
Object.keys(req.body.data).forEach(statisticName => {
|
||||
Object.keys(req.body.data[statisticName]).forEach(direction => {
|
||||
let statHash = req.body.data[statisticName][direction];
|
||||
Object.keys(statHash).forEach(item => {
|
||||
let value = Number(statHash[item]);
|
||||
if(value) prometheusStatisticsGauge.labels(req.body.instanceID, req.body.force, statisticName, direction, item).set(value);
|
||||
});
|
||||
});
|
||||
});
|
||||
res.send({ok:true, msg:`Statistics successfully reported at ${Date.now()}`});
|
||||
}catch(e){
|
||||
res.send({ok:false, msg:"Statistics reporter crashed, see sharedPlugins/statisticsExporter/masterPlugin.js"});
|
||||
console.log(e)
|
||||
};
|
||||
} else {
|
||||
res.send("failure");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
module.exports = masterPlugin;
|
||||
Reference in new issue
Block a user