Added new plugin for reporting production/kills/construction statistics to Prometheus

This commit is contained in:
Daniel Vestøl committed 2018-10-23 11:10:59 +02:00
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"
}
+40
View File
@@ -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;