EverydayTech Platform - Developer Reference
Complete Source Code Documentation - All Applications
Loading...
Searching...
No Matches
monitoring.js
Go to the documentation of this file.
1/**
2* @description MeshCentral monitoring module
3* @author Simon Smith
4* @license Apache-2.0
5* @version v0.0.1
6*/
7
8"use strict";
9
10module.exports.CreateMonitoring = function (parent, args) {
11 var obj = {};
12 obj.args = args;
13 obj.parent = parent;
14 obj.express = require('express');
15 obj.app = obj.express();
16 obj.prometheus = null;
17 obj.app.disable('x-powered-by');
18 obj.counterMetrics = { // Counter Metrics always start at 0 and increase but never decrease
19 RelayErrors: { description: "Relay Errors" }, // parent.webserver.relaySessionErrorCount
20 UnknownGroup: { description: "Unknown Group" }, // meshDoesNotExistCount
21 InvalidPKCSsignature: { description: "Invalid PKCS signature" }, // invalidPkcsSignatureCount
22 InvalidRSAsignature: { description: "Invalid RSA signature" }, // invalidRsaSignatureCount
23 InvalidJSON: { description: "Invalid JSON" }, // invalidJsonCount
24 UnknownAction: { description: "Unknown Action" }, // unknownAgentActionCount
25 BadWebCertificate: { description: "Bad Web Certificate" }, // agentBadWebCertHashCount
26 BadSignature: { description: "Bad Signature" }, // (agentBadSignature1Count + agentBadSignature2Count)
27 MaxSessionsReached: { description: "Max Sessions Reached" }, // agentMaxSessionHoldCount
28 UnknownDeviceGroup: { description: "Unknown Device Group" }, // (invalidDomainMeshCount + invalidDomainMesh2Count)
29 InvalidDeviceGroupType: { description: "Invalid Device Group Type" }, // invalidMeshTypeCount
30 DuplicateAgent: { description: "Duplicate Agent" }, // duplicateAgentCount
31 blockedUsers: { description: "Blocked Users" }, // blockedUsers
32 blockedAgents: { description: "Blocked Agents" }, // blockedAgents
33 };
34 obj.gaugeMetrics = { // Gauge Metrics always start at 0 and can increase and decrease
35 ConnectedIntelAMT: { description: "Connected Intel AMT" }, // parent.parent.connectivityByNode[i].connectivity == 4
36 ConnectedIntelAMTCira: { description: "Connected Intel AMT CIRA" }, // parent.mpsserver.ciraConnections[i].length
37 UserAccounts: { description: "User Accounts" }, // Object.keys(parent.webserver.users).length
38 DeviceGroups: { description: "Device Groups" }, // parent.webserver.meshes (ONLY WHERE deleted=null)
39 AgentSessions: { description: "Agent Sessions" }, // Object.keys(parent.webserver.wsagents).length
40 ConnectedUsers: { description: "Connected Users" }, // Object.keys(parent.webserver.wssessions).length
41 UsersSessions: { description: "Users Sessions" }, // Object.keys(parent.webserver.wssessions2).length
42 RelaySessions: { description: "Relay Sessions" }, // parent.webserver.relaySessionCount
43 RelayCount: { description: "Relay Count" } // Object.keys(parent.webserver.wsrelays).length30bb4fb74dfb758d36be52a7
44 }
45 obj.collectors = [];
46 if (parent.config.settings.prometheus != null) { // Create Prometheus Monitoring Endpoint
47 if ((typeof parent.config.settings.prometheus == 'number') && ((parent.config.settings.prometheus < 1) || (parent.config.settings.prometheus > 65535))) {
48 console.log('Promethus port number is invalid, Prometheus metrics endpoint has be disabled');
49 delete parent.config.settings.prometheus;
50 } else {
51 const port = ((typeof parent.config.settings.prometheus == 'number') ? parent.config.settings.prometheus : 9464);
52 obj.prometheus = require('prom-client');
53 const collectDefaultMetrics = obj.prometheus.collectDefaultMetrics;
54 collectDefaultMetrics();
55 for (const key in obj.gaugeMetrics) {
56 obj.gaugeMetrics[key].prometheus = new obj.prometheus.Gauge({ name: 'meshcentral_' + String(key).toLowerCase(), help: obj.gaugeMetrics[key].description });
57 }
58 for (const key in obj.counterMetrics) {
59 obj.counterMetrics[key].prometheus = new obj.prometheus.Counter({ name: 'meshcentral_' + String(key).toLowerCase(), help: obj.counterMetrics[key].description });
60 }
61 obj.app.get('/', function (req, res) { res.send('MeshCentral Prometheus server.'); });
62 obj.app.listen(port, function () {
63 console.log('MeshCentral Prometheus server running on port ' + port + '.');
64 obj.parent.updateServerState('prometheus-port', port);
65 });
66 obj.app.get('/metrics', async (req, res) => {
67 try {
68 // Count the number of device groups that are not deleted
69 var activeDeviceGroups = 0;
70 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.
71 var gauges = {
72 UserAccounts: Object.keys(parent.webserver.users).length,
73 DeviceGroups: activeDeviceGroups,
74 AgentSessions: Object.keys(parent.webserver.wsagents).length,
75 ConnectedUsers: Object.keys(parent.webserver.wssessions).length,
76 UsersSessions: Object.keys(parent.webserver.wssessions2).length,
77 RelaySessions: parent.webserver.relaySessionCount,
78 RelayCount: Object.keys(parent.webserver.wsrelays).length,
79 ConnectedIntelAMT: 0
80 };
81 if (parent.mpsserver != null) {
82 gauges.ConnectedIntelAMTCira = 0;
83 for (var i in parent.mpsserver.ciraConnections) {
84 gauges.ConnectedIntelAMTCira += parent.mpsserver.ciraConnections[i].length;
85 }
86 }
87 for (var i in parent.connectivityByNode) {
88 const node = parent.connectivityByNode[i];
89 if (node && typeof node.connectivity !== 'undefined' && node.connectivity === 4) { gauges.ConnectedIntelAMT++; }
90 }
91 for (const key in gauges) { obj.gaugeMetrics[key].prometheus.set(gauges[key]); }
92 // Take a look at agent errors
93 var agentstats = parent.webserver.getAgentStats();
94 const counters = {
95 RelayErrors: parent.webserver.relaySessionErrorCount,
96 UnknownGroup: agentstats.meshDoesNotExistCount,
97 InvalidPKCSsignature: agentstats.invalidPkcsSignatureCount,
98 InvalidRSAsignature: agentstats.invalidRsaSignatureCount,
99 InvalidJSON: agentstats.invalidJsonCount,
100 UnknownAction: agentstats.unknownAgentActionCount,
101 BadWebCertificate: agentstats.agentBadWebCertHashCount,
102 BadSignature: (agentstats.agentBadSignature1Count + agentstats.agentBadSignature2Count),
103 MaxSessionsReached: agentstats.agentMaxSessionHoldCount,
104 UnknownDeviceGroup: (agentstats.invalidDomainMeshCount + agentstats.invalidDomainMesh2Count),
105 InvalidDeviceGroupType: (agentstats.invalidMeshTypeCount + agentstats.invalidMeshType2Count),
106 DuplicateAgent: agentstats.duplicateAgentCount,
107 blockedUsers: parent.webserver.blockedUsers,
108 blockedAgents: parent.webserver.blockedAgents
109 };
110 for (const key in counters) { obj.counterMetrics[key].prometheus.reset(); obj.counterMetrics[key].prometheus.inc(counters[key]); }
111 res.set('Content-Type', obj.prometheus.register.contentType);
112 await Promise.all(obj.collectors.map((collector) => (collector(req, res))));
113 res.end(await obj.prometheus.register.metrics());
114 } catch (ex) {
115 console.log(ex);
116 res.status(500).end();
117 }
118 });
119 }
120 }
121 return obj;
122}