MeshCentral/monitoring.js

114 lines
7.5 KiB
JavaScript
Raw Normal View History

/**
* @description MeshCentral monitoring module
* @author Simon Smith
* @license Apache-2.0
* @version v0.0.1
*/
"use strict";
module.exports.CreateMonitoring = function (parent, args) {
var obj = {};
obj.args = args;
obj.parent = parent;
obj.express = require('express');
obj.app = obj.express();
obj.prometheus = null;
if (args.compression !== false) { obj.app.use(require('compression')()); }
obj.app.disable('x-powered-by');
obj.counterMetrics = { // Counter Metrics always start at 0 and increase but never decrease
RelayErrors: { description: "Relay Errors" }, // parent.webserver.relaySessionErrorCount
UnknownGroup: { description: "Unknown Group" }, // meshDoesNotExistCount
InvalidPKCSsignature: { description: "Invalid PKCS signature" }, // invalidPkcsSignatureCount
InvalidRSAsignature: { description: "Invalid RSA signature" }, // invalidRsaSignatureCount
InvalidJSON: { description: "Invalid JSON" }, // invalidJsonCount
UnknownAction: { description: "Unknown Action" }, // unknownAgentActionCount
BadWebCertificate: { description: "Bad Web Certificate" }, // agentBadWebCertHashCount
BadSignature: { description: "Bad Signature" }, // (agentBadSignature1Count + agentBadSignature2Count)
MaxSessionsReached: { description: "Max Sessions Reached" }, // agentMaxSessionHoldCount
UnknownDeviceGroup: { description: "Unknown Device Group" }, // (invalidDomainMeshCount + invalidDomainMesh2Count)
InvalidDeviceGroupType: { description: "Invalid Device Group Type" }, // invalidMeshTypeCount
DuplicateAgent: { description: "Duplicate Agent" }, // duplicateAgentCount
blockedUsers: { description: "Blocked Users" }, // blockedUsers
blockedAgents: { description: "Blocked Agents" }, // blockedAgents
};
obj.guageMetrics = { // Guage Metrics always start at 0 and can increase and decrease
ConnectedIntelAMT: { description: "Connected Intel AMT" }, // parent.mpsserver.ciraConnections[i].length
UserAccounts: { description: "User Accounts" }, // Object.keys(parent.webserver.users).length
DeviceGroups: { description: "Device Groups" }, // parent.webserver.meshes (ONLY WHERE deleted=null)
AgentSessions: { description: "Agent Sessions" }, // Object.keys(parent.webserver.wsagents).length
ConnectedUsers: { description: "Connected Users" }, // Object.keys(parent.webserver.wssessions).length
UsersSessions: { description: "Users Sessions" }, // Object.keys(parent.webserver.wssessions2).length
RelaySessions: { description: "Relay Sessions" }, // parent.webserver.relaySessionCount
RelayCount: { description: "Relay Count" } // Object.keys(parent.webserver.wsrelays).length30bb4fb74dfb758d36be52a7
}
if (parent.config.settings.prometheus != null) { // Create Prometheus Monitoring Endpoint
if ((typeof parent.config.settings.prometheus == 'number') && ((parent.config.settings.prometheus < 1) || (parent.config.settings.prometheus > 65535))) {
console.log('Promethus port number is invalid, Prometheus metrics endpoint has be disabled');
delete parent.config.settings.prometheus;
} else {
const port = ((typeof parent.config.settings.prometheus == 'number') ? parent.config.settings.prometheus : 9464);
obj.prometheus = require('prom-client');
const collectDefaultMetrics = obj.prometheus.collectDefaultMetrics;
collectDefaultMetrics();
for (const key in obj.guageMetrics) {
obj.guageMetrics[key].prometheus = new obj.prometheus.Gauge({ name: 'meshcentral_' + String(key).toLowerCase(), help: obj.guageMetrics[key].description });
}
for (const key in obj.counterMetrics) {
obj.counterMetrics[key].prometheus = new obj.prometheus.Counter({ name: 'meshcentral_' + String(key).toLowerCase(), help: obj.counterMetrics[key].description });
}
obj.app.get('/', function (req, res) { res.send('MeshCentral Prometheus server.'); });
obj.app.listen(port, function () {
console.log('MeshCentral Prometheus server running on port ' + port + '.');
obj.parent.updateServerState('prometheus-port', port);
});
obj.app.get('/metrics', async (req, res) => {
try {
// Count the number of device groups that are not deleted
var activeDeviceGroups = 0;
for (var i in parent.webserver.meshes) { if (parent.webserver.meshes[i].deleted == null) { activeDeviceGroups++; } } // This is not ideal for performance, we want to dome something better.
var guages = {
UserAccounts: Object.keys(parent.webserver.users).length,
DeviceGroups: activeDeviceGroups,
AgentSessions: Object.keys(parent.webserver.wsagents).length,
ConnectedUsers: Object.keys(parent.webserver.wssessions).length,
UsersSessions: Object.keys(parent.webserver.wssessions2).length,
RelaySessions: parent.webserver.relaySessionCount,
RelayCount: Object.keys(parent.webserver.wsrelays).length,
ConnectedIntelAMT: 0
};
if (parent.mpsserver != null) {
for (var i in parent.mpsserver.ciraConnections) {
guages.ConnectedIntelAMT += parent.mpsserver.ciraConnections[i].length;
}
}
for (const key in guages) { obj.guageMetrics[key].prometheus.set(guages[key]); }
// Take a look at agent errors
var agentstats = parent.webserver.getAgentStats();
const counters = {
RelayErrors: parent.webserver.relaySessionErrorCount,
UnknownGroup: agentstats.meshDoesNotExistCount,
InvalidPKCSsignature: agentstats.invalidPkcsSignatureCount,
InvalidRSAsignature: agentstats.invalidRsaSignatureCount,
InvalidJSON: agentstats.invalidJsonCount,
UnknownAction: agentstats.unknownAgentActionCount,
BadWebCertificate: agentstats.agentBadWebCertHashCount,
BadSignature: (agentstats.agentBadSignature1Count + agentstats.agentBadSignature2Count),
MaxSessionsReached: agentstats.agentMaxSessionHoldCount,
UnknownDeviceGroup: (agentstats.invalidDomainMeshCount + agentstats.invalidDomainMesh2Count),
InvalidDeviceGroupType: (agentstats.invalidMeshTypeCount + agentstats.invalidMeshType2Count),
DuplicateAgent: agentstats.duplicateAgentCount,
blockedUsers: parent.webserver.blockedUsers,
blockedAgents: parent.webserver.blockedAgents
};
for (const key in counters) { obj.counterMetrics[key].prometheus.reset(); obj.counterMetrics[key].prometheus.inc(counters[key]); }
res.set('Content-Type', obj.prometheus.register.contentType);
res.end(await obj.prometheus.register.metrics());
} catch (ex) {
console.log(ex);
res.status(500).end();
}
});
}
}
}