Added database counters.

This commit is contained in:
Ylian Saint-Hilaire 2021-03-01 19:32:19 -08:00
parent 8d8285b916
commit c9035b80c8
3 changed files with 65 additions and 10 deletions

58
db.js
View File

@ -38,9 +38,26 @@ module.exports.CreateDB = function (parent, func) {
obj.dbRecordsDecryptKey = null;
obj.changeStream = false;
obj.pluginsActive = ((parent.config) && (parent.config.settings) && (parent.config.settings.plugins != null) && (parent.config.settings.plugins != false) && ((typeof parent.config.settings.plugins != 'object') || (parent.config.settings.plugins.enabled != false)));
obj.dbCounters = {
fileSet: 0,
fileRemove: 0,
powerSet: 0,
eventsSet: 0
}
// MongoDB bulk operations state
if (parent.config.settings.mongodbbulkoperations) {
// Added counters
obj.dbCounters.fileSetPending = 0;
obj.dbCounters.fileSetBulk = 0;
obj.dbCounters.fileRemovePending = 0;
obj.dbCounters.fileRemoveBulk = 0;
obj.dbCounters.powerSetPending = 0;
obj.dbCounters.powerSetBulk = 0;
obj.dbCounters.eventsSetPending = 0;
obj.dbCounters.eventsSetBulk = 0;
/// Added bulk accumulators
obj.filePendingGet = null;
obj.filePendingGets = null;
obj.filePendingRemove = null;
@ -514,12 +531,15 @@ module.exports.CreateDB = function (parent, func) {
// Setup the changeStream on the MongoDB main collection if possible
if (parent.args.mongodbchangestream == true) {
obj.dbCounters.changeStream = { change: 0, update: 0, insert: 0, delete: 0 };
if (typeof obj.file.watch != 'function') {
console.log('WARNING: watch() is not a function, MongoDB ChangeStream not supported.');
} else {
obj.fileChangeStream = obj.file.watch([{ $match: { $or: [{ 'fullDocument.type': { $in: ['node', 'mesh', 'user', 'ugrp'] } }, { 'operationType': 'delete' }] } }], { fullDocument: 'updateLookup' });
obj.fileChangeStream.on('change', function (change) {
obj.dbCounters.changeStream.change++;
if ((change.operationType == 'update') || (change.operationType == 'replace')) {
obj.dbCounters.changeStream.update++;
switch (change.fullDocument.type) {
case 'node': { dbNodeChange(change, false); break; } // A node has changed
case 'mesh': { dbMeshChange(change, false); break; } // A device group has changed
@ -527,6 +547,7 @@ module.exports.CreateDB = function (parent, func) {
case 'ugrp': { dbUGrpChange(change, false); break; } // A user account has changed
}
} else if (change.operationType == 'insert') {
obj.dbCounters.changeStream.insert++;
switch (change.fullDocument.type) {
case 'node': { dbNodeChange(change, true); break; } // A node has added
case 'mesh': { dbMeshChange(change, true); break; } // A device group has created
@ -534,6 +555,7 @@ module.exports.CreateDB = function (parent, func) {
case 'ugrp': { dbUGrpChange(change, true); break; } // A user account has created
}
} else if (change.operationType == 'delete') {
obj.dbCounters.changeStream.delete++;
if ((change.documentKey == null) || (change.documentKey._id == null)) return;
var splitId = change.documentKey._id.split('/');
switch (splitId[0]) {
@ -898,6 +920,7 @@ module.exports.CreateDB = function (parent, func) {
if ((obj.databaseType == 4) || (obj.databaseType == 5)) {
// Database actions on the main collection (MariaDB or MySQL)
obj.Set = function (value, func) {
obj.dbCounters.fileSet++;
var extra = null, extraex = null;
value = common.escapeLinksFieldNameEx(value);
if (value.meshid) { extra = value.meshid; } else if (value.email) { extra = 'email/' + value.email; } else if (value.nodeid) { extra = value.nodeid; }
@ -947,6 +970,7 @@ module.exports.CreateDB = function (parent, func) {
// Database actions on the events collection
obj.GetAllEvents = function (func) { sqlDbQuery('SELECT doc FROM meshcentral.events', null, func); };
obj.StoreEvent = function (event, func) {
obj.dbCounters.eventsSet++;
var batchQuery = [['INSERT INTO meshcentral.events VALUE (?, ?, ?, ?, ?, ?, ?)', [null, event.time, ((typeof event.domain == 'string') ? event.domain : null), event.action, event.nodeid ? event.nodeid : null, event.userid ? event.userid : null, JSON.stringify(event)]]];
for (var i in event.ids) { if (event.ids[i] != '*') { batchQuery.push(['INSERT INTO meshcentral.eventids VALUE (LAST_INSERT_ID(), ?)', [event.ids[i]]]); } }
sqlDbBatchExec(batchQuery, function (err, docs) { if (func != null) { func(err, docs); } });
@ -991,7 +1015,7 @@ module.exports.CreateDB = function (parent, func) {
// Database actions on the power collection
obj.getAllPower = function (func) { sqlDbQuery('SELECT doc FROM meshcentral.power', null, func); };
obj.storePowerEvent = function (event, multiServer, func) { if (multiServer != null) { event.server = multiServer.serverid; } sqlDbQuery('INSERT INTO meshcentral.power VALUE (?, ?, ?, ?)', [null, event.time, event.nodeid ? event.nodeid : null, JSON.stringify(event)], func); };
obj.storePowerEvent = function (event, multiServer, func) { obj.dbCounters.powerSet++; if (multiServer != null) { event.server = multiServer.serverid; } sqlDbQuery('INSERT INTO meshcentral.power VALUE (?, ?, ?, ?)', [null, event.time, event.nodeid ? event.nodeid : null, JSON.stringify(event)], func); };
obj.getPowerTimeline = function (nodeid, func) { sqlDbQuery('SELECT doc FROM meshcentral.power WHERE ((nodeid = ?) OR (nodeid = "*")) ORDER BY time DESC', [nodeid], func); };
obj.removeAllPowerEvents = function () { sqlDbQuery('DELETE FROM meshcentral.power', null, function (err, docs) { }); };
obj.removeAllPowerEventsForNode = function (nodeid) { sqlDbQuery('DELETE FROM meshcentral.power WHERE nodeid = ?', [nodeid], function (err, docs) { }); };
@ -1055,11 +1079,13 @@ module.exports.CreateDB = function (parent, func) {
obj.Set = function (data, func) { // Fast Set operation using bulkWrite(), this is much faster then using replaceOne()
if (obj.filePendingSet == false) {
// Perform the operation now
obj.dbCounters.fileSet++;
obj.filePendingSet = true; obj.filePendingSets = null;
if (func != null) { obj.filePendingCbs = [func]; }
obj.file.bulkWrite([{ replaceOne: { filter: { _id: data._id }, replacement: performTypedRecordEncrypt(common.escapeLinksFieldNameEx(data)), upsert: true } }], fileBulkWriteCompleted);
} else {
// Add this operation to the pending list
obj.dbCounters.fileSetPending++;
if (obj.filePendingSets == null) { obj.filePendingSets = {} }
obj.filePendingSets[data._id] = data;
if (func != null) { if (obj.filePendingCb == null) { obj.filePendingCb = [func]; } else { obj.filePendingCb.push(func); } }
@ -1093,7 +1119,11 @@ module.exports.CreateDB = function (parent, func) {
}
};
} else {
obj.Set = function (data, func) { data = common.escapeLinksFieldNameEx(data); obj.file.replaceOne({ _id: data._id }, performTypedRecordEncrypt(data), { upsert: true }, func); };
obj.Set = function (data, func) {
obj.dbCounters.fileSet++;
data = common.escapeLinksFieldNameEx(data);
obj.file.replaceOne({ _id: data._id }, performTypedRecordEncrypt(data), { upsert: true }, func);
};
obj.Get = function (id, func) {
if (arguments.length > 2) {
var parms = [func];
@ -1145,18 +1175,20 @@ module.exports.CreateDB = function (parent, func) {
if (parent.config.settings.mongodbbulkoperations) {
obj.Remove = function (id, func) { // Fast remove operation using a bulk find() to reduce round trips to the database.
if (obj.filePendingRemoves == null) {
// No pending gets, perform the operation now.
// No pending removes, perform the operation now.
obj.dbCounters.fileRemove++;
obj.filePendingRemoves = {};
obj.filePendingRemoves[id] = [func];
obj.file.deleteOne({ _id: id }, fileBulkRemoveCompleted);
} else {
// Add remove to pending list.
obj.dbCounters.fileRemovePending++;
if (obj.filePendingRemove == null) { obj.filePendingRemove = {}; }
if (obj.filePendingRemove[id] == null) { obj.filePendingRemove[id] = [func]; } else { obj.filePendingRemove[id].push(func); }
}
};
} else {
obj.Remove = function (id, func) { obj.file.deleteOne({ _id: id }, func); };
obj.Remove = function (id, func) { obj.dbCounters.fileRemove++; obj.file.deleteOne({ _id: id }, func); };
}
obj.RemoveAll = function (func) { obj.file.deleteMany({}, { multi: true }, func); };
@ -1189,18 +1221,20 @@ module.exports.CreateDB = function (parent, func) {
obj.StoreEvent = function (event, func) { // Fast MongoDB event store using bulkWrite()
if (obj.eventsFilePendingSet == false) {
// Perform the operation now
obj.dbCounters.eventsSet++;
obj.eventsFilePendingSet = true; obj.eventsFilePendingSets = null;
if (func != null) { obj.eventsFilePendingCbs = [func]; }
obj.eventsfile.bulkWrite([{ insertOne: { document: event } }], eventsFileBulkWriteCompleted);
} else {
// Add this operation to the pending list
obj.dbCounters.eventsSetPending++;
if (obj.eventsFilePendingSets == null) { obj.eventsFilePendingSets = [] }
obj.eventsFilePendingSets.push(event);
if (func != null) { if (obj.eventsFilePendingCb == null) { obj.eventsFilePendingCb = [func]; } else { obj.eventsFilePendingCb.push(func); } }
}
};
} else {
obj.StoreEvent = function (event, func) { obj.eventsfile.insertOne(event, func); };
obj.StoreEvent = function (event, func) { obj.dbCounters.eventsSet++; obj.eventsfile.insertOne(event, func); };
}
obj.GetEvents = function (ids, domain, func) { obj.eventsfile.find({ domain: domain, ids: { $in: ids } }).project({ type: 0, _id: 0, domain: 0, ids: 0, node: 0 }).sort({ time: -1 }).toArray(func); };
@ -1230,18 +1264,20 @@ module.exports.CreateDB = function (parent, func) {
if (multiServer != null) { event.server = multiServer.serverid; }
if (obj.powerFilePendingSet == false) {
// Perform the operation now
obj.dbCounters.powerSet++;
obj.powerFilePendingSet = true; obj.powerFilePendingSets = null;
if (func != null) { obj.powerFilePendingCbs = [func]; }
obj.powerfile.bulkWrite([{ insertOne: { document: event } }], powerFileBulkWriteCompleted);
} else {
// Add this operation to the pending list
obj.dbCounters.powerSetPending++;
if (obj.powerFilePendingSets == null) { obj.powerFilePendingSets = [] }
obj.powerFilePendingSets.push(event);
if (func != null) { if (obj.powerFilePendingCb == null) { obj.powerFilePendingCb = [func]; } else { obj.powerFilePendingCb.push(func); } }
}
};
} else {
obj.storePowerEvent = function (event, multiServer, func) { if (multiServer != null) { event.server = multiServer.serverid; } obj.powerfile.insertOne(event, func); };
obj.storePowerEvent = function (event, multiServer, func) { obj.dbCounters.powerSet++; if (multiServer != null) { event.server = multiServer.serverid; } obj.powerfile.insertOne(event, func); };
}
obj.getPowerTimeline = function (nodeid, func) { obj.powerfile.find({ nodeid: { $in: ['*', nodeid] } }).project({ _id: 0, nodeid: 0, s: 0 }).sort({ time: 1 }).toArray(func); };
@ -1304,7 +1340,11 @@ module.exports.CreateDB = function (parent, func) {
} else {
// Database actions on the main collection (NeDB and MongoJS)
obj.Set = function (data, func) { data = common.escapeLinksFieldNameEx(data); var xdata = performTypedRecordEncrypt(data); obj.file.update({ _id: xdata._id }, xdata, { upsert: true }, func); };
obj.Set = function (data, func) {
obj.dbCounters.fileSet++;
data = common.escapeLinksFieldNameEx(data);
var xdata = performTypedRecordEncrypt(data); obj.file.update({ _id: xdata._id }, xdata, { upsert: true }, func);
};
obj.Get = function (id, func) {
if (arguments.length > 2) {
var parms = [func];
@ -1578,6 +1618,7 @@ module.exports.CreateDB = function (parent, func) {
obj.filePendingRemoves = obj.filePendingRemove;
obj.filePendingRemove = null;
if (obj.filePendingRemoves != null) {
obj.dbCounters.fileRemoveBulk++;
var findlist = [], count = 0;
for (var i in obj.filePendingRemoves) { findlist.push(i); count++; }
obj.file.deleteMany({ _id: { $in: findlist } }, { multi: true }, fileBulkRemoveCompleted);
@ -1593,6 +1634,7 @@ module.exports.CreateDB = function (parent, func) {
}
if (obj.filePendingSets != null) {
// Perform pending operations
obj.dbCounters.fileSetBulk++;
var ops = [];
obj.filePendingCbs = obj.filePendingCb;
obj.filePendingCb = null;
@ -1611,6 +1653,7 @@ module.exports.CreateDB = function (parent, func) {
if (obj.eventsFilePendingCbs != null) { for (var i in obj.eventsFilePendingCbs) { obj.eventsFilePendingCbs[i](); } obj.eventsFilePendingCbs = null; }
if (obj.eventsFilePendingSets != null) {
// Perform pending operations
obj.dbCounters.eventsSetBulk++;
var ops = [];
for (var i in obj.eventsFilePendingSets) { ops.push({ document: obj.eventsFilePendingSets[i] }); }
obj.eventsFilePendingCbs = obj.eventsFilePendingCb;
@ -1629,6 +1672,7 @@ module.exports.CreateDB = function (parent, func) {
if (obj.powerFilePendingCbs != null) { for (var i in obj.powerFilePendingCbs) { obj.powerFilePendingCbs[i](); } obj.powerFilePendingCbs = null; }
if (obj.powerFilePendingSets != null) {
// Perform pending operations
obj.dbCounters.powerSetBulk++;
var ops = [];
for (var i in obj.powerFilePendingSets) { ops.push({ document: obj.powerFilePendingSets[i] }); }
obj.powerFilePendingCbs = obj.powerFilePendingCb;

View File

@ -887,7 +887,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
switch (cmd) {
case 'help': {
var fin = '', f = '', availcommands = 'help,maintenance,info,versions,resetserver,usersessions,closeusersessions,tasklimiter,setmaxtasks,cores,migrationagents,agentstats,agentissues,webstats,mpsstats,swarmstats,acceleratorsstats,updatecheck,serverupdate,nodeconfig,heapdump,relays,autobackup,backupconfig,dupagents,dispatchtable,badlogins,showpaths,le,lecheck,leevents,dbstats,sms,amtacm,certhashes,watchdog,amtmanager';
var fin = '', f = '', availcommands = 'help,maintenance,info,versions,resetserver,usersessions,closeusersessions,tasklimiter,setmaxtasks,cores,migrationagents,agentstats,agentissues,webstats,mpsstats,swarmstats,acceleratorsstats,updatecheck,serverupdate,nodeconfig,heapdump,relays,autobackup,backupconfig,dupagents,dispatchtable,badlogins,showpaths,le,lecheck,leevents,dbstats,dbcounters,sms,amtacm,certhashes,watchdog,amtmanager';
if (parent.parent.config.settings.heapdump === true) { availcommands += ',heapdump'; }
availcommands = availcommands.split(',').sort();
while (availcommands.length > 0) { if (f.length > 80) { fin += (f + ',\r\n'); f = ''; } f += (((f != '') ? ', ' : ' ') + availcommands.shift()); }
@ -1135,7 +1135,11 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
var r2 = '';
for (var i in stats) { r2 += (i + ': ' + stats[i] + '\r\n'); }
try { ws.send(JSON.stringify({ action: 'serverconsole', value: r2, tag: command.tag })); } catch (ex) { }
})
});
break;
}
case 'dbcounters': {
try { ws.send(JSON.stringify({ action: 'serverconsole', value: JSON.stringify(parent.parent.db.dbCounters, null, 2), tag: command.tag })); } catch (ex) { }
break;
}
case 'serverupdate': {

View File

@ -6483,7 +6483,14 @@
}
function deskClipboardOutFunction() {
if ((navigator.clipboard != null) && (navigator.clipboard.readText != null)) { navigator.clipboard.readText().then(function(text) { meshserver.send({ action: 'msg', type: 'setclip', nodeid: currentNode._id, data: text }); }).catch(function(err) { }); }
if ((navigator.clipboard != null) && (navigator.clipboard.readText != null)) {
try {
navigator.clipboard.readText().then(function(text) {
meshserver.send({ action: 'msg', type: 'setclip', nodeid: currentNode._id, data: text });
}).catch(function(err) { console.log(err); });
} catch (ex) { console.log(ex); }
}
return true;
}
function deskRefreshFunction() {