2022-03-24 17:00:45 +01:00
|
|
|
|
2022-03-28 19:49:56 +02:00
|
|
|
const os = require('os');
|
|
|
|
const fs = require('fs');
|
2022-03-24 17:00:45 +01:00
|
|
|
|
2022-03-28 19:49:56 +02:00
|
|
|
let runtime;
|
|
|
|
let isContainerCached;
|
|
|
|
let isWSLCached;
|
2022-03-24 17:00:45 +01:00
|
|
|
|
2022-03-28 19:49:56 +02:00
|
|
|
const isInWsl = () => {
|
|
|
|
if (isWSLCached === undefined) {
|
|
|
|
isWSLCached = getIsInWSL();
|
|
|
|
}
|
|
|
|
return isWSLCached;
|
|
|
|
function getIsInWSL() {
|
|
|
|
if (process.platform !== 'linux') {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
if (os.release().toLowerCase().includes('microsoft')) {
|
|
|
|
if (isInContainer()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return fs.readFileSync('/proc/version', 'utf8').toLowerCase().includes('microsoft') ? !isInContainer() : false;
|
|
|
|
} catch (_) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const isInContainer = () => {
|
|
|
|
if (isContainerCached === undefined) {
|
|
|
|
isContainerCached = hasDockerEnv() || hasDockerCGroup();
|
|
|
|
}
|
|
|
|
return isContainerCached;
|
|
|
|
function hasDockerEnv() {
|
|
|
|
try {
|
|
|
|
fs.statSync('/.dockerenv');
|
|
|
|
return true;
|
|
|
|
} catch {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function hasDockerCGroup() {
|
|
|
|
try {
|
|
|
|
const s = fs.readFileSync('/proc/self/cgroup', 'utf8');
|
|
|
|
if (s.includes('docker')) {
|
|
|
|
return "docker"
|
|
|
|
} else if (s.includes('kubepod')) {
|
|
|
|
return "kubepod"
|
|
|
|
} else if (s.includes('lxc')) {
|
|
|
|
return "lxc"
|
|
|
|
}
|
|
|
|
} catch {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-03-24 17:00:45 +01:00
|
|
|
|
|
|
|
function buildDiagnosticReport(scope, callback) {
|
2022-03-28 19:49:56 +02:00
|
|
|
const modules = {};
|
|
|
|
const nl = runtime.nodes.getNodeList();
|
|
|
|
for (let i = 0; i < nl.length; i++) {
|
|
|
|
if (modules[nl[i].module]) {
|
|
|
|
continue;
|
2022-03-24 17:00:45 +01:00
|
|
|
}
|
2022-03-28 19:49:56 +02:00
|
|
|
modules[nl[i].module] = nl[i].version
|
2022-03-24 17:00:45 +01:00
|
|
|
}
|
2022-03-28 19:49:56 +02:00
|
|
|
|
|
|
|
const now = new Date();
|
2022-03-29 21:48:29 +02:00
|
|
|
const {locale, timeZone} = Intl.DateTimeFormat().resolvedOptions();
|
2022-03-28 19:49:56 +02:00
|
|
|
const report = {
|
|
|
|
report: "diagnostics",
|
|
|
|
scope: scope,
|
|
|
|
time: {
|
2022-03-29 21:48:29 +02:00
|
|
|
utc: now.toUTCString(),
|
|
|
|
local: now.toLocaleString(),
|
|
|
|
},
|
|
|
|
intl: {
|
|
|
|
locale, timeZone
|
2022-03-28 19:49:56 +02:00
|
|
|
},
|
|
|
|
nodejs: {
|
|
|
|
version: process.version,
|
|
|
|
arch: process.arch,
|
|
|
|
platform: process.platform,
|
|
|
|
memoryUsage: process.memoryUsage(),
|
|
|
|
},
|
|
|
|
os: {
|
2022-03-29 21:48:29 +02:00
|
|
|
containerised: isInContainer(),
|
|
|
|
wsl: isInWsl(),
|
2022-03-28 19:49:56 +02:00
|
|
|
totalmem: os.totalmem(),
|
|
|
|
freemem: os.freemem(),
|
|
|
|
arch: os.arch(),
|
|
|
|
loadavg: os.loadavg(),
|
|
|
|
platform: os.platform(),
|
|
|
|
release: os.release(),
|
|
|
|
type: os.type(),
|
|
|
|
uptime: os.uptime(),
|
|
|
|
version: os.version(),
|
|
|
|
},
|
|
|
|
runtime: {
|
2022-03-29 21:48:29 +02:00
|
|
|
isStarted: runtime.isStarted(),
|
2022-03-28 19:49:56 +02:00
|
|
|
modules: modules,
|
2022-03-29 21:48:29 +02:00
|
|
|
version: runtime.settings.version,
|
2022-03-28 19:49:56 +02:00
|
|
|
settings: {
|
|
|
|
available: runtime.settings.available(),
|
2022-03-29 21:48:29 +02:00
|
|
|
apiMaxLength: runtime.settings.apiMaxLength || "UNSET",
|
2022-03-28 19:49:56 +02:00
|
|
|
//coreNodesDir: runtime.settings.coreNodesDir,
|
|
|
|
disableEditor: runtime.settings.disableEditor,
|
|
|
|
contextStorage: listContextModules(),
|
2022-03-29 21:48:29 +02:00
|
|
|
debugMaxLength: runtime.settings.debugMaxLength || "UNSET",
|
|
|
|
editorTheme: runtime.settings.editorTheme || "UNSET",
|
|
|
|
flowFile: runtime.settings.flowFile || "UNSET",
|
|
|
|
mqttReconnectTime: runtime.settings.mqttReconnectTime || "UNSET",
|
|
|
|
serialReconnectTime: runtime.settings.serialReconnectTime || "UNSET",
|
2022-03-28 19:49:56 +02:00
|
|
|
|
2022-03-29 21:48:29 +02:00
|
|
|
adminAuth: runtime.settings.adminAuth ? "SET" : "UNSET",
|
2022-03-28 19:49:56 +02:00
|
|
|
|
2022-03-29 21:48:29 +02:00
|
|
|
httpAdminRoot: runtime.settings.httpAdminRoot || "UNSET",
|
|
|
|
httpAdminCors: runtime.settings.httpAdminCors ? "SET" : "UNSET",
|
2022-04-06 16:11:28 +02:00
|
|
|
httpNodeAuth: runtime.settings.httpNodeAuth ? "SET" : "UNSET",
|
2022-03-28 19:49:56 +02:00
|
|
|
|
2022-03-29 21:48:29 +02:00
|
|
|
httpNodeRoot: runtime.settings.httpNodeRoot || "UNSET",
|
|
|
|
httpNodeCors: runtime.settings.httpNodeCors ? "SET" : "UNSET",
|
2022-03-28 19:49:56 +02:00
|
|
|
|
2022-03-29 21:48:29 +02:00
|
|
|
httpStatic: runtime.settings.httpStatic ? "SET" : "UNSET",
|
2022-04-06 16:11:28 +02:00
|
|
|
httpStaticRoot: runtime.settings.httpStaticRoot || "UNSET",
|
2022-03-29 21:48:29 +02:00
|
|
|
httpStaticCors: runtime.settings.httpStaticCors ? "SET" : "UNSET",
|
2022-03-28 19:49:56 +02:00
|
|
|
|
2022-03-29 21:48:29 +02:00
|
|
|
uiHost: runtime.settings.uiHost ? "SET" : "UNSET",
|
|
|
|
uiPort: runtime.settings.uiPort ? "SET" : "UNSET",
|
|
|
|
userDir: runtime.settings.userDir ? "SET" : "UNSET",
|
2022-03-28 19:49:56 +02:00
|
|
|
}
|
2022-03-24 17:00:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-29 21:48:29 +02:00
|
|
|
// if (scope == "admin") {
|
|
|
|
// const moreSettings = {
|
|
|
|
// adminAuth_type: (runtime.settings.adminAuth && runtime.settings.adminAuth.type) ? runtime.settings.adminAuth.type : "UNSET",
|
|
|
|
// httpAdminCors: runtime.settings.httpAdminCors ? runtime.settings.httpAdminCors : "UNSET",
|
|
|
|
// httpNodeCors: runtime.settings.httpNodeCors ? runtime.settings.httpNodeCors : "UNSET",
|
|
|
|
// httpStaticCors: runtime.settings.httpStaticCors ? "SET" : "UNSET",
|
|
|
|
// settingsFile: runtime.settings.settingsFile ? runtime.settings.settingsFile : "UNSET",
|
|
|
|
// uiHost: runtime.settings.uiHost ? runtime.settings.uiHost : "UNSET",
|
|
|
|
// uiPort: runtime.settings.uiPort ? runtime.settings.uiPort : "UNSET",
|
|
|
|
// userDir: runtime.settings.userDir ? runtime.settings.userDir : "UNSET",
|
|
|
|
// }
|
|
|
|
// const moreNodejs = {
|
|
|
|
// execPath: process.execPath,
|
|
|
|
// pid: process.pid,
|
|
|
|
// }
|
|
|
|
// const moreOs = {
|
|
|
|
// cpus: os.cpus(),
|
|
|
|
// homedir: os.homedir(),
|
|
|
|
// hostname: os.hostname(),
|
|
|
|
// networkInterfaces: os.networkInterfaces(),
|
|
|
|
// }
|
|
|
|
// report.runtime.settings = Object.assign({}, report.runtime.settings, moreSettings);
|
|
|
|
// report.nodejs = Object.assign({}, report.nodejs, moreNodejs);
|
|
|
|
// report.os = Object.assign({}, report.os, moreOs);
|
|
|
|
// }
|
2022-03-24 17:00:45 +01:00
|
|
|
|
|
|
|
callback(report);
|
|
|
|
|
2022-03-28 19:49:56 +02:00
|
|
|
/** gets a sanitised list containing only the module name */
|
2022-03-24 17:00:45 +01:00
|
|
|
function listContextModules() {
|
2022-03-28 19:49:56 +02:00
|
|
|
const keys = Object.keys(runtime.settings.contextStorage);
|
|
|
|
const result = {};
|
2022-03-24 17:00:45 +01:00
|
|
|
keys.forEach(e => {
|
|
|
|
result[e] = {
|
2022-03-28 19:49:56 +02:00
|
|
|
module: String(runtime.settings.contextStorage[e].module)
|
2022-03-24 17:00:45 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-03-28 19:49:56 +02:00
|
|
|
module.exports = {
|
2022-03-24 17:00:45 +01:00
|
|
|
init: function (_runtime) {
|
|
|
|
runtime = _runtime;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* Gets the node-red diagnostics report
|
2022-03-28 19:49:56 +02:00
|
|
|
* @param {{scope: string}} opts - settings
|
|
|
|
* @return {Promise} the diagnostics information
|
2022-03-24 17:00:45 +01:00
|
|
|
* @memberof @node-red/diagnostics
|
|
|
|
*/
|
|
|
|
get: async function (opts) {
|
|
|
|
return new Promise(function (resolve, reject) {
|
|
|
|
opts = opts || {}
|
|
|
|
try {
|
2022-03-28 19:49:56 +02:00
|
|
|
runtime.log.audit({ event: "diagnostics.get", scope: opts.scope }, opts.req);
|
|
|
|
buildDiagnosticReport(opts.scope, (report) => resolve(report));
|
2022-03-24 17:00:45 +01:00
|
|
|
} catch (error) {
|
2022-03-28 19:49:56 +02:00
|
|
|
error.status = 500;
|
2022-03-24 17:00:45 +01:00
|
|
|
reject(error);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
},
|
|
|
|
}
|