@daemonitor/plugins 1.1.18 → 1.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -28,6 +28,7 @@ const SYS = {
|
|
|
28
28
|
name: "1.3.6.1.2.1.1.5.0", // sysName
|
|
29
29
|
ifOper: "1.3.6.1.2.1.2.2.1.8", // ifOperStatus (walk): 1=up 2=down
|
|
30
30
|
ifAdmin: "1.3.6.1.2.1.2.2.1.7", // ifAdminStatus (walk): 1=up (enabled)
|
|
31
|
+
ifName: "1.3.6.1.2.1.31.1.1.1.1", // ifName (walk) — eth0/eth1/itf0/...
|
|
31
32
|
ifHCIn: "1.3.6.1.2.1.31.1.1.1.6", // ifHCInOctets (walk, Counter64)
|
|
32
33
|
ifHCOut: "1.3.6.1.2.1.31.1.1.1.10", // ifHCOutOctets (walk, Counter64)
|
|
33
34
|
};
|
|
@@ -45,9 +46,9 @@ const UCD = {
|
|
|
45
46
|
memCached: "1.3.6.1.4.1.2021.4.15.0", // memCached (KB)
|
|
46
47
|
hrProcLoad: "1.3.6.1.2.1.25.3.3.1.2", // hrProcessorLoad (walk, per-core %) — CPU fallback
|
|
47
48
|
};
|
|
48
|
-
//
|
|
49
|
-
//
|
|
50
|
-
const
|
|
49
|
+
// Previous cumulative octet counters PER INTERFACE (target ip -> ifIndex), for
|
|
50
|
+
// per-link throughput rates across polls.
|
|
51
|
+
const netPrevIf = {};
|
|
51
52
|
// QNAP enterprise MIB (NAS-MIB, 1.3.6.1.4.1.24681.1.2). A full walk of this
|
|
52
53
|
// subtree times out on QTS, so everything here is fetched by exact OID.
|
|
53
54
|
const QNAP = {
|
|
@@ -189,10 +190,11 @@ async function collectDevice(t) {
|
|
|
189
190
|
// CPU / RAM / load / network — best-effort UCD-SNMP + IF-MIB counters. Absent
|
|
190
191
|
// on gear without the UCD MIB (returns "No Such Object" fast → null), so every
|
|
191
192
|
// field is optional and simply omitted when unsupported.
|
|
192
|
-
const [cpuIdle, load1, load5, load15, memTotal, memAvail, memBuffer, memCached, procLoads,
|
|
193
|
+
const [cpuIdle, load1, load5, load15, memTotal, memAvail, memBuffer, memCached, procLoads, ifNames, hcInIdx, hcOutIdx] = await Promise.all([
|
|
193
194
|
snmpGet(t, UCD.cpuIdle), snmpGet(t, UCD.load1), snmpGet(t, UCD.load5), snmpGet(t, UCD.load15),
|
|
194
195
|
snmpGet(t, UCD.memTotal), snmpGet(t, UCD.memAvail), snmpGet(t, UCD.memBuffer), snmpGet(t, UCD.memCached),
|
|
195
|
-
snmpWalk(t, UCD.hrProcLoad),
|
|
196
|
+
snmpWalk(t, UCD.hrProcLoad), snmpWalkIndexed(t, SYS.ifName),
|
|
197
|
+
snmpWalkIndexed(t, SYS.ifHCIn), snmpWalkIndexed(t, SYS.ifHCOut),
|
|
196
198
|
]);
|
|
197
199
|
// CPU %: prefer ssCpuIdle (100 - idle); fall back to avg per-core hrProcessorLoad.
|
|
198
200
|
let cpuPct;
|
|
@@ -216,24 +218,57 @@ async function collectDevice(t) {
|
|
|
216
218
|
memPct = Math.round((usedKb / mTot) * 100);
|
|
217
219
|
memTotalMB = Math.round(mTot / 1024);
|
|
218
220
|
}
|
|
219
|
-
// Network throughput (
|
|
220
|
-
//
|
|
221
|
-
//
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
221
|
+
// Network throughput, PER INTERFACE (bytes/sec).
|
|
222
|
+
//
|
|
223
|
+
// Summing every interface is meaningless on a router: a transiting packet is
|
|
224
|
+
// counted once arriving on the WAN and again leaving on the LAN, so
|
|
225
|
+
// sum(in) === sum(out) by construction — and vendors add aggregate pseudo
|
|
226
|
+
// interfaces (EdgeOS `itf0`) that mirror the whole load a second time. The
|
|
227
|
+
// observed effect was ~5x inflation with in/out identical to the eye.
|
|
228
|
+
//
|
|
229
|
+
// So: rate each interface separately, skip loopback/pseudo, and let the target
|
|
230
|
+
// name its WAN (`wanInterface`) to headline the figure that actually means
|
|
231
|
+
// "internet traffic". Without one, the headline is left undefined rather than
|
|
232
|
+
// reporting a number we know to be wrong.
|
|
233
|
+
const PSEUDO = /^(lo|imq\d*|itf\d*|ifb\d*|sit\d*|gre\d*|teql\d*|tunl\d*)$/i;
|
|
234
|
+
const idxOf = (rows) => {
|
|
235
|
+
const m = {};
|
|
236
|
+
for (const r of rows)
|
|
237
|
+
m[r.idx] = r.val;
|
|
238
|
+
return m;
|
|
239
|
+
};
|
|
240
|
+
const nameByIdx = idxOf(ifNames);
|
|
241
|
+
const inByIdx = idxOf(hcInIdx);
|
|
242
|
+
const outByIdx = idxOf(hcOutIdx);
|
|
243
|
+
const now = Date.now();
|
|
244
|
+
const prevIf = netPrevIf[t.ip] || {};
|
|
245
|
+
const nextIf = {};
|
|
246
|
+
const interfaces = [];
|
|
247
|
+
for (const idx of Object.keys(inByIdx)) {
|
|
248
|
+
const name = (nameByIdx[idx] || `if${idx}`).replace(/^"|"$/g, "");
|
|
249
|
+
const cin = Number(inByIdx[idx]), cout = Number(outByIdx[idx]);
|
|
250
|
+
if (isNaN(cin) || isNaN(cout))
|
|
251
|
+
continue;
|
|
252
|
+
nextIf[idx] = { in: cin, out: cout, ts: now };
|
|
253
|
+
if (PSEUDO.test(name))
|
|
254
|
+
continue;
|
|
255
|
+
const p = prevIf[idx];
|
|
256
|
+
let inBps, outBps;
|
|
257
|
+
if (p && cin >= p.in && cout >= p.out && now > p.ts) {
|
|
258
|
+
const dt = (now - p.ts) / 1000;
|
|
230
259
|
if (dt > 0) {
|
|
231
|
-
|
|
232
|
-
|
|
260
|
+
inBps = Math.round((cin - p.in) / dt);
|
|
261
|
+
outBps = Math.round((cout - p.out) / dt);
|
|
233
262
|
}
|
|
234
263
|
}
|
|
235
|
-
|
|
264
|
+
interfaces.push({ name, inBps, outBps });
|
|
236
265
|
}
|
|
266
|
+
netPrevIf[t.ip] = nextIf;
|
|
267
|
+
// Headline = the WAN link when the target names one.
|
|
268
|
+
const wanName = t.wanInterface;
|
|
269
|
+
const wan = wanName ? interfaces.find((i) => i.name === wanName) : undefined;
|
|
270
|
+
const netIn = wan?.inBps;
|
|
271
|
+
const netOut = wan?.outBps;
|
|
237
272
|
return {
|
|
238
273
|
name: t.name,
|
|
239
274
|
ip: t.ip,
|
|
@@ -252,6 +287,11 @@ async function collectDevice(t) {
|
|
|
252
287
|
memTotalMB,
|
|
253
288
|
netIn,
|
|
254
289
|
netOut,
|
|
290
|
+
wanInterface: wanName,
|
|
291
|
+
// Per-link rates (loopback/pseudo excluded), busiest first.
|
|
292
|
+
interfaces: interfaces
|
|
293
|
+
.slice()
|
|
294
|
+
.sort((a, b) => ((b.inBps || 0) + (b.outBps || 0)) - ((a.inBps || 0) + (a.outBps || 0))),
|
|
255
295
|
};
|
|
256
296
|
}
|
|
257
297
|
// Walk that keeps each row's index (numeric OID suffix) — needed to resolve the
|