Skip to content

Commit

Permalink
Merge pull request #151 from OpenAF/kube-nInput_JavaGC
Browse files Browse the repository at this point in the history
improvements to JavaGC, Kube_PodsMetrics, Shell
  • Loading branch information
nmaguiar authored Apr 16, 2023
2 parents c4943bd + a2c9c43 commit 67368af
Show file tree
Hide file tree
Showing 5 changed files with 308 additions and 135 deletions.
10 changes: 6 additions & 4 deletions .package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ name: nAttrMon
main: nattrmon.js
mainJob: ''
license: Apache 2.0 license
version: '20230212'
version: '20230415'
dependencies:
openaf: '>=20220822'
files:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
33 changes: 33 additions & 0 deletions config/inputs.disabled/yaml/15.javagc.yaml
Original file line number Diff line number Diff line change
@@ -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
270 changes: 202 additions & 68 deletions config/objects/nInput_JavaGC.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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) {
Expand All @@ -122,22 +256,22 @@ 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
ret[gcThreads] = arrGCThreads
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
Expand Down
Loading

0 comments on commit 67368af

Please sign in to comment.