diff --git a/.package.yaml b/.package.yaml index 56f391d..2d93c7f 100644 --- a/.package.yaml +++ b/.package.yaml @@ -19,7 +19,7 @@ name: nAttrMon main: nattrmon.js mainJob: '' license: Apache 2.0 license -version: '20230212' +version: '20230415' dependencies: openaf: '>=20220822' files: @@ -187,6 +187,7 @@ files: - config/inputs.disabled/yaml/10.kubeNodesMetrics.yaml - config/inputs.disabled/yaml/01.ping.yaml - config/inputs.disabled/yaml/25.bpmDebugFlags.yaml +- config/inputs.disabled/yaml/15.javagc.yaml - config/inputs.disabled/yaml/10.kubePodsMetrics.yaml - config/inputs.disabled/yaml/10.sessions.yaml - config/inputs.disabled/yaml/10.filesystem.yaml @@ -332,7 +333,7 @@ filesHash: config/objects/nInput_RAIDGCMemory.js: 28aefad8696236df00e681ea00d85679d9481a9f config/objects/nInput_Schedulers.js: 96771d166e2574b6d5a526cc6025ad3abf1363d4 config/objects/nInput_IMMemory.js: 69f6e3d39aa5a75c83d2e4f8e2ece0b28df7e3f1 - config/objects/nInput_JavaGC.js: e039c7a1ad618f432ca41fcc40fdb61b1f1b2eb1 + config/objects/nInput_JavaGC.js: a28bbf24766cff14d43ae23364dc6f43382b879a config/objects/nInput_nAttrMon.js: c8ec9f45f724e7372b02751b893178490587641b config/objects/nInput_CBPMDebugChecks.js: 737f33ddd852309d0322f57e7adeeb307627652f config/objects/nOutput_DSV.js: b723aefe236bd464d215c52406cec796cd47d97f @@ -350,7 +351,7 @@ filesHash: config/objects/nOutput_Channels.js: f6e277efa2c12c3d6dd8468facbfb1bb43828ed6 config/objects/nInput_OSInfo.js: b8548f6d69dea80553fbef3e6e8d6552c15362e9 config/objects/nInput_ESSearch.js: 0f825f81de288367fde87f13be5e1ccfe072bd1c - config/objects/nInput_Shell.js: e3f52cbf7fb1c7cabb724ec6111aebb3527f16d0 + config/objects/nInput_Shell.js: 5888cc365bddaeef4d9f293dc02897e86f6747a9 config/objects/nOutput_HTTP_JSON.js: 73c4619994bf56f923fc3d2860e0aa6b422e3748 config/objects/nInput_RAIDLookups.js: 9a56cb2550a5c254097337f4da7191f58a685caa config/objects/nOutput_Log2ES.js: 4ff766b80b2e03f08f9f38e5a8dba4115d62bf81 @@ -384,7 +385,7 @@ filesHash: config/objects/nOutput_Log.js: 69ef02bb37d306deb390f303a8bbf6e2234be792 config/objects/nInput_Kube_Events.js: 7a36aa2e72973d9369b856c6ef2ce4eddcab8459 config/objects/nInput_EndPoints.js: 5042270a025e040a844f79832c924aa20f0413b4 - config/objects/nInput_Kube_PodsMetrics.js: 0547c230ed520abf4fb41038cbfcb3c850bc5a4c + config/objects/nInput_Kube_PodsMetrics.js: c9255fc8c0e310dff7dd0181487a3e4b0dbb46a0 config/objects/nValidation_Yellows.js: 942478fcd710e392add0b6ef6349ef51a895b764 config/objects/nValidation_AFPing.js: f48325d605e693dee3ab2912224cda0fde11e490 config/objects/nValidation_Semaphores.js: 97b6c1850b80d95cc92c1c50b05fdfa26467fd94 @@ -418,6 +419,7 @@ filesHash: config/inputs.disabled/yaml/10.kubeNodesMetrics.yaml: e09e05bbd3eddf6caf819e5d90cf6c2be45d45ca config/inputs.disabled/yaml/01.ping.yaml: fe3c634d7b0beff66a59484a315fcc205ffe1ca9 config/inputs.disabled/yaml/25.bpmDebugFlags.yaml: 1b98caed366844383947a0caf05161f6b010ac7f + config/inputs.disabled/yaml/15.javagc.yaml: d2afec1ae2c0aa6583d5554c93959ff61211425c config/inputs.disabled/yaml/10.kubePodsMetrics.yaml: 99424c1726600399c7b83da537186048791a13b0 config/inputs.disabled/yaml/10.sessions.yaml: 460da54e61f71ae9b1f0ef325f70d87b55e6861c config/inputs.disabled/yaml/10.filesystem.yaml: e8b8a6149c8f32128cd3c601081f6f67b3822e70 diff --git a/config/inputs.disabled/yaml/15.javagc.yaml b/config/inputs.disabled/yaml/15.javagc.yaml new file mode 100644 index 0000000..b1333a6 --- /dev/null +++ b/config/inputs.disabled/yaml/15.javagc.yaml @@ -0,0 +1,33 @@ +input: +# ------------------------------- +- name : Test Java GC local + execFrom : nInput_JavaGC + execArgs : + type : local + +# ----------------------------- +- name : Test Java GC ssh + execFrom : nInput_JavaGC + execArgs : + type : ssh + chKeys : sshServers + attrTemplate: Servers/Java GC + +# ------------------------------ +- name : Test Java GC kube + execFrom : nInput_JavaGC + execArgs : + type : kube + kube : + namespace: my-namespace-1, my-namespace-2 + selector : + where: + - cond: starts + args: + - metadata.name + - my-pod + - cond: equals + args: + - status.phase + - Running + attrTemplate: Kube/Java GC \ No newline at end of file diff --git a/config/objects/nInput_JavaGC.js b/config/objects/nInput_JavaGC.js index 9376e8f..5aa2df3 100644 --- a/config/objects/nInput_JavaGC.js +++ b/config/objects/nInput_JavaGC.js @@ -20,6 +20,9 @@ var nInput_JavaGC = function(aMap) { ow.loadJava() ow.loadNet() + + this.params.type = _$(this.params.type, "type").oneOf(["local", "ssh", "kube"]).default("local") + if (isUnDef(this.params.attrTemplate)) this.params.attrTemplate = "Java/{{_name}}" nInput.call(this, this.input) @@ -37,76 +40,207 @@ nInput_JavaGC.prototype.get = function(keyData, extra) { res.gcThreads = [] res.gcSpaces = [] res.gcMem = [] - - ow.java.getLocalJavaPIDs().forEach(p => { - var data = ow.java.parseHSPerf(p.path) - var host = ow.net.getHostName() - var cmdH = sha512(host + data.sun.rt.javaCommand).substring(0, 7) - - res.gcSummary.push({ - key : cmdH, - pid : p.pid, - host : host, - cmd : data.sun.rt.javaCommand, - vendor : data.java.property.java.vm.vendor, - jre : data.java.property.java.vm.name, - version : data.java.property.java.vm.version, - totalRunningTimeMs: data.sun.rt.__totalRunningTime, - percAppTime : data.sun.rt.__percAppTime, - gcCause : data.sun.gc.cause, - gcLastCause : data.sun.gc.lastCause - }) - - res.gcCollectors = res.gcCollectors.concat(data.sun.gc.collector.map(c => ({ - key : cmdH, - pid : p.pid, - name : c.name, - invocations : c.invocations, - lastInvocationMsAgo: isDate(c.__lastExitDate) ? now() - c.__lastExitDate.getTime() : __, - lastExecTimeMs : c.__lastExecTime, - avgExecTimeMs : c.__avgExecTime - }))) - - var r = { max: 0, total: 0, used: 0, free: 0 } - data.sun.gc.generation.forEach(gen => { - gen.space.forEach(space => { - res.gcSpaces.push({ - key: cmdH, - pid: p.pid, - gen: gen.name, - space: space.name, - used : space.used > 0 ? space.used : 0, - total: space.capacity > 0 ? space.capacity : 0, - max : space.maxCapacity > 0 ? space.maxCapacity : 0 + + var _lst = [] + var setSec = aEntry => { + if (isDef(aEntry.secKey)) { + return __nam_getSec(aEntry) + } else { + return aEntry + } + } + + if (isUnDef(keyData)) return + + switch(this.params.type) { + case "local": + _lst = ow.java.getLocalJavaPIDs() + break + case "ssh" : + var __res + if (isString(keyData.key)) { + nattrmon.useObject(keyData.key, _ssh => { + __res = _ssh.exec("/bin/sh -c 'echo ${TMPDIR:-/tmp} && echo \"||\" && find ${TMPDIR:-/tmp} -type f'", __, __, __, true) }) + } else { + __res = nattrmon.shExec("ssh", keyData).exec("/bin/sh -c 'echo ${TMPDIR:-/tmp} && echo \"||\" && find ${TMPDIR:-/tmp} -type f'") + } + if (isDef(__res) && isDef(__res.stdout)) { + var _tmp = __res.stdout.split("||") + _lst = _tmp[1] + .split("\n") + .filter(l => l.indexOf(_tmp[0].replace(/\n/g, "") + "/hsperfdata_") == 0) + } + break + case "kube" : + if (isUnDef(getOPackPath("Kube"))) throw "Kube opack not installed." + loadLib("kube.js") + + this.params.kube = _$(this.params.kube, "kube").isMap().default({}) - r.max = (r.max < Number(space.maxCapacity)) ? Number(space.maxCapacity) : r.max - r.used = r.used + Number(space.used) - r.total = isNumber(space.capacity) ? r.total + Number(space.capacity) : r.total - }) + var m = setSec(this.params.kube) + m.kind = _$(m.kind, "kube.kind").isString().default("FPO") + m.namespace = _$(m.namespace, "kube.namespace").isString().default("default") + + var nss = m.namespace.split(/ *, */), lst = [] + + nss.forEach(ns => { + var its = $kube(m)["get" + m.kind](ns) + if (isMap(its) && isArray(its.items)) lst = lst.concat(its.items) }) - res.gcMem.push({ - key: cmdH, - pid: p.pid, - total: r.total, - used: r.used, - free: r.total - r.used, - metaMax : data.sun.gc.metaspace.maxCapacity, - metaTotal : data.sun.gc.metaspace.capacity, - metaUsed : data.sun.gc.metaspace.used, - metaFree : data.sun.gc.metaspace.capacity - data.sun.gc.metaspace.used + if (isMap(m.selector)) { + ow.obj.filter(lst, m.selector).forEach(r => { + var newM = clone(m) + traverse(newM, (aK, aV, aP, aO) => { + if (isString(aV)) aO[aK] = templify(aV, r) + }) + }) + } + + ow.obj.filter(lst, m.selector).forEach(r => { + var newM = clone(m) + newM.pod = r.metadata.name + newM.namespace = r.metadata.namespace + try { + var res = nattrmon.shExec("kube", newM).exec(["/bin/sh", "-c", "/bin/sh -c 'echo ${TMPDIR:-/tmp} && echo \"||\" && find ${TMPDIR:-/tmp} -type f'"]) + if (isDef(res.stdout)) { + var _tmp = String(res.stdout).split("||") + var lst = _tmp[1] + .split("\n") + .filter(l => l.indexOf(_tmp[0].replace(/\n/g, "") + "/hsperfdata_") == 0) + + lst.forEach(_l => { + _lst.push({ + path: _l, + pid: Number(_l.substring(_l.lastIndexOf("/")+1)), + k: newM + }) + }) + } + } catch(fe) { logErr("nInput_JavaGC | Kube " + newM.namespace + "::" + newM.pod + " | " + fe) } }) - var _t = { - key: cmdH, - pid: p.pid + break + } + + _lst.forEach(p => { + var data, host + + try { + switch(this.params.type) { + case "local": + data = ow.java.parseHSPerf(p.path) + host = ow.net.getHostName() + break + case "ssh" : + try { + var __res + if (isString(p)) p = { cmd: p, pid: p.substring(p.lastIndexOf("/") + 1) } + if (isString(keyData.key)) { + nattrmon.useObject(keyData.key, _ssh => { + __res = _ssh.exec("base64 -w0 " + p.cmd, __, __, __, true) + }) + } else { + __res = nattrmon.shExec("ssh", keyData).exec("base64 -w0 " + p.cmd) + } + if (isMap(__res) && isDef(__res.stdout) && __res.stdout.length > 0) { + var ostream = af.newOutputStream() + ioStreamCopy(ostream, af.fromBytes2InputStream(af.fromBase64(af.fromString2Bytes(__res.stdout)))) + data = ow.java.parseHSPerf( ostream.toByteArray() ) + } else { + data = {} + } + } catch(fe) { logErr("nInput_JavaGC | SSH " + p.cmd + " | " + fe); throw fe } + break + case "kube" : + host = p.k.namespace + "::" + p.k.pod + try { + var __res = nattrmon.shExec("kube", p.k).exec("base64 -w0 " + p.path) + if (isDef(__res) && isDef(__res.stdout)) { + data = ow.java.parseHSPerf( af.fromBase64(String(__res.stdout)) ) + } + } catch(kfe) { logErr("nInput_JavaGC | Kube " + host + " | " + kfe) } + break + } + + if (isMap(data) && isDef(data.sun) && isDef(data.java)) { + var cmdH = ((isMap(keyData) && isString(keyData.key)) ? keyData.key + ":" : "") + (isDef(host) ? host + ":" : "") + p.pid + + res.gcSummary.push({ + key : cmdH, + pid : p.pid, + host : host, + cmd : data.sun.rt.javaCommand, + vendor : data.java.property.java.vm.vendor, + jre : data.java.property.java.vm.name, + version : data.java.property.java.vm.version, + totalRunningTimeMs: data.sun.rt.__totalRunningTime, + percAppTime : data.sun.rt.__percAppTime, + gcCause : data.sun.gc.cause, + gcLastCause : data.sun.gc.lastCause + }) + + if (isArray(data.sun.gc.collector)) { + res.gcCollectors = res.gcCollectors.concat(data.sun.gc.collector.map(c => ({ + key : cmdH, + pid : p.pid, + name : c.name, + invocations : c.invocations, + lastInvocationMsAgo: isDate(c.__lastExitDate) ? now() - c.__lastExitDate.getTime() : __, + lastExecTimeMs : c.__lastExecTime, + avgExecTimeMs : c.__avgExecTime + }))) + } + + var r = { max: 0, total: 0, used: 0, free: 0 } + if (isArray(data.sun.gc.generation)) { + data.sun.gc.generation.forEach(gen => { + gen.space.forEach(space => { + res.gcSpaces.push({ + key: cmdH, + pid: p.pid, + gen: gen.name, + space: space.name, + used : space.used > 0 ? space.used : 0, + total: space.capacity > 0 ? space.capacity : 0, + max : space.maxCapacity > 0 ? space.maxCapacity : 0 + }) + + r.max = (r.max < Number(space.maxCapacity)) ? Number(space.maxCapacity) : r.max + r.used = r.used + Number(space.used) + r.total = isNumber(space.capacity) ? r.total + Number(space.capacity) : r.total + }) + }) + } + + res.gcMem.push({ + key: cmdH, + pid: p.pid, + total: r.total, + used: r.used, + free: r.total - r.used, + metaMax : data.sun.gc.metaspace.maxCapacity, + metaTotal : data.sun.gc.metaspace.capacity, + metaUsed : data.sun.gc.metaspace.used, + metaFree : data.sun.gc.metaspace.capacity - data.sun.gc.metaspace.used + }) + + var _t = { + key: cmdH, + pid: p.pid + } + if (isMap(data.java.threads)) Object.keys(data.java.threads).forEach(k => _t[k] = data.java.threads[k]) + res.gcThreads.push(_t) + } else { + throw "nInput_JavaGC | Couldn't retrieve data from " + af.toSLON(p) + "." + } + } catch(eee) { + logErr("nInput_JavaGC | Problem: " + eee) } - Object.keys(data.java.threads).forEach(k => _t[k] = data.java.threads[k]) - res.gcThreads.push(_t) }) - return merge(res, extra) + return res } nInput_JavaGC.prototype.input = function(scope, args) { @@ -122,14 +256,14 @@ nInput_JavaGC.prototype.input = function(scope, args) { var gcMem = templify(this.params.attrTemplate, { _name: "Memory" }) if (isDef(this.params.chKeys)) { - var arrGCSummary = [], arrGCCollectors = [], arrGCThreads = [], arrGCSpaces = [] + var arrGCSummary = [], arrGCCollectors = [], arrGCThreads = [], arrGCSpaces = [], arrGCMem = [] $ch(this.params.chKeys).forEach((k, v) => { var data = this.get(merge(k, v)) - arrGCSummary.push(data.gcSummary) - arrGCCollectors.push(data.gcCollectors) - arrGCThreads.push(data.gcThreads) - arrGCSpaces.push(data.gcSpaces) - arrGCMem.push(data.gcMem) + arrGCSummary = arrGCSummary.concat(data.gcSummary) + arrGCCollectors = arrGCCollectors.concat(data.gcCollectors) + arrGCThreads = arrGCThreads.concat(data.gcThreads) + arrGCSpaces = arrGCSpaces.concat(data.gcSpaces) + arrGCMem = arrGCMem.concat(data.gcMem) }) ret[gcSummary] = arrGCSummary ret[gcCollectors] = arrGCCollectors @@ -137,7 +271,7 @@ nInput_JavaGC.prototype.input = function(scope, args) { ret[gcSpaces] = arrGCSpaces ret[gcMem] = arrGCMem } else { - var data = this.get() + var data = this.get(this.params) ret[gcSummary] = data.gcSummary ret[gcCollectors] = data.gcCollectors ret[gcThreads] = data.gcThreads diff --git a/config/objects/nInput_Kube_PodsMetrics.js b/config/objects/nInput_Kube_PodsMetrics.js index c8cfda8..60f3556 100644 --- a/config/objects/nInput_Kube_PodsMetrics.js +++ b/config/objects/nInput_Kube_PodsMetrics.js @@ -83,7 +83,7 @@ nInput_Kube_PodsMetrics.prototype.input = function(scope, args) { $from(r.containers) .select(s => { var cA = $from(s.usage).equals("key", "cpu").select(t => _r(_fromSIAbbrev(String(t.value.amount) + t.value.format))) - var mA = $from(s.usage).equals("key", "memory").select(t => ow.format.fromBytesAbbreviation(String(t.value.amount) + t.value.format)) + var mA = $from(s.usage).equals("key", "memory").select(t => (Number(t.value.amount) > 0 ? ow.format.fromBytesAbbreviation(String(t.value.amount) + t.value.format) : "")) res.push({ namespace: r.metadata.namespace, name : s.name, diff --git a/config/objects/nInput_Shell.js b/config/objects/nInput_Shell.js index f7ad93d..6120153 100644 --- a/config/objects/nInput_Shell.js +++ b/config/objects/nInput_Shell.js @@ -49,76 +49,80 @@ nInput_Shell.prototype.input = function(scope, args) { var v = $ch(this.params.chKeys).get({ key: this.params.keys[i] }); v = __nam_getSec(v); - switch(v.type) { - case "kube": - if (isUnDef(getOPackPath("Kube"))) { - throw "Kube opack not installed."; - } - - var s = $sec(v.secRepo, v.secBucket, v.secBucketPass, v.secMainPass, v.secFile); - var k; - if (isDef(v.secObjKey)) { - var k = s.getObj(v.secObjKey); - } - if (isDef(v.secKey)) { - var ka = s.get(v.secKey); - k = new Kube(ka.url, ka.user, ka.pass, ka.wsTimeout, ka.token); - } - if (isUnDef(k) || isUnDef(k.getNamespaces)) { - throw "The secObjKey = '" + v.secObjKey + "' is not a valid Kube object."; - } - - var epods = []; - if (isUnDef(v.pod)) { - if (isDef(v.podTemplate)) { - var pods = k.getPods(v.namespace); - epods = $from(pods) - .equals("Kind", "Pod") - .match("Metadata.Name", v.podTemplate) - .select(r => r.Metadata.Name); + try { + switch(v.type) { + case "kube": + if (isUnDef(getOPackPath("Kube"))) { + throw "Kube opack not installed."; + } + + var s = $sec(v.secRepo, v.secBucket, v.secBucketPass, v.secMainPass, v.secFile); + var k; + if (isDef(v.secObjKey)) { + var k = s.getObj(v.secObjKey); + } + if (isDef(v.secKey)) { + var ka = s.get(v.secKey); + k = new Kube(ka.url, ka.user, ka.pass, ka.wsTimeout, ka.token); + } + if (isUnDef(k) || isUnDef(k.getNamespaces)) { + throw "The secObjKey = '" + v.secObjKey + "' is not a valid Kube object."; + } + + var epods = []; + if (isUnDef(v.pod)) { + if (isDef(v.podTemplate)) { + var pods = k.getPods(v.namespace); + epods = $from(pods) + .equals("Kind", "Pod") + .match("Metadata.Name", v.podTemplate) + .select(r => r.Metadata.Name); + } else { + throw "No pod determined for '" + v.secObjKey + "'"; + } } else { - throw "No pod determined for '" + v.secObjKey + "'"; + epods = [ v.pod ]; } - } else { - epods = [ v.pod ]; - } - - epods.forEach(pod => { - try { - var rr = String(k.exec(v.namespace, pod, [ templify(parent.cmd) ], void 0, true)); - if (parent.parseJson) { + + epods.forEach(pod => { + try { + var rr = String(k.exec(v.namespace, pod, [ templify(parent.cmd) ], void 0, true)); + if (parent.parseJson) { + res.push({ + key: parent.params.keys[i], + result: jsonParse(rr, true) + }); + } else { + res.push({ + key: parent.params.keys[i], + result: rr + }); + } + ; + } catch(e) { + logErr("nInput_Shell | Error on namespace '"+ v.namespace + "', pod '" + pod + "': " + String(e)); + } + }); + + break; + case "ssh": + default: + nattrmon.useObject(this.params.keys[i], (ssh) => { + if (this.parseJson) { res.push({ - key: parent.params.keys[i], - result: jsonParse(rr, true) + key: this.params.keys[i], + result: jsonParse(ssh.exec(templify(this.cmd)), true) }); } else { res.push({ - key: parent.params.keys[i], - result: rr + key: this.params.keys[i], + result: ssh.exec(templify(this.cmd)) }); } - ; - } catch(e) { - logErr("nInput_Shell | Error on namespace '"+ v.namespace + "', pod '" + pod + "': " + String(e)); - } - }); - - break; - case "ssh": - default: - nattrmon.useObject(this.params.keys[i], (ssh) => { - if (this.parseJson) { - res.push({ - key: this.params.keys[i], - result: jsonParse(ssh.exec(templify(this.cmd)), true) - }); - } else { - res.push({ - key: this.params.keys[i], - result: ssh.exec(templify(this.cmd)) - }); - } - }); + }); + } + } catch(pke) { + logErr(" nInput_Shell | " + this.params.keys[i] + " | " + pke) } }