This repository has been archived by the owner on May 9, 2022. It is now read-only.
/
MBean.scala
99 lines (77 loc) · 3.46 KB
/
MBean.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package zapush
import management.ManagementFactory
import collection.JavaConversions._
import javax.management.openmbean._
import javax.management.{MBeanAttributeInfo, ObjectName}
object MBeans {
lazy val mbeanServer = ManagementFactory.getPlatformMBeanServer
def mbeanNames = mbeanServer.queryNames(null, null).toList
def all = mbeanNames.map(new MBean(_))
}
case class MBeanProperty(bean: MBean, propertyName: String, attributeType: String) {
lazy val objectName = bean.name
lazy val zabbixName = "java[" + Config.zabbixAppname + ":" + objectName.toString + ":" + propertyName + "]"
def value = bean(propertyName)
}
case class MBeanValue(rawValue: AnyRef) {
override def toString = rawValue match {
case a: Array[_] => a.mkString(", ")
case t: TabularData => "[tabular data not yet supported by zapush]"
case m: Map[_, _] => m.mkString("map: ", ", ", "end")
case other => other.toString
}
def child(childName: String): MBeanValue = {
rawValue match {
case c: CompositeData => MBeanValue(c.get(childName))
case t: TabularData => error("tabular data not yet supported by zapush")
// t.values
// .collect { case cd: CompositeData if cd.get("key") == childName => MBeanValue(cd.get("value")) }
// .headOption.getOrElse(error("failed to parse tabular data for " + childName + " from " + rawValue))
case _ => error("could not find child named " + childName + " from " + rawValue)
}
}
}
class MBean(val name: ObjectName) {
lazy val mbeanServer = ManagementFactory.getPlatformMBeanServer
// naming convention:
// "attribute" refers to a jmx attribute
// "property" refers to our flattened name, dot separated, including the values within composite attributes
lazy val readableAttributes =
mbeanServer.getMBeanInfo(name).getAttributes.filter(_.isReadable).toSet
lazy val compositeAttributes =
readableAttributes.filter(_.getType == classOf[CompositeData].getName)
lazy val topLevelReadableAttributes = readableAttributes -- compositeAttributes
lazy val properties = readableAttributes flatMap { attr =>
def parseOpenType(path: String, ot: OpenType[_]): List[MBeanProperty] = ot match {
case c: CompositeType =>
c.keySet.toList.flatMap(itemName => parseOpenType(path + "." + itemName, c.getType(itemName)))
case arr: ArrayType[_] =>
List(MBeanProperty(this, path, "Array[" + arr.getElementOpenType.getTypeName + "]"))
case other =>
List(MBeanProperty(this, path, other.getTypeName))
}
attr match {
case open: OpenMBeanAttributeInfo =>
parseOpenType(attr.getName, open.getOpenType)
case closed: MBeanAttributeInfo =>
List(MBeanProperty(this, attr.getName, closed.getType))
}
}
lazy val shortName = name.getKeyPropertyListString
lazy val fullName = name.toString
def apply(attributeName: String) = {
def parseComposite(path: List[String], data: MBeanValue): MBeanValue =
path match {
case Nil => error("erm something went wong")
case key :: Nil => data.child(key)
case key :: rest => parseComposite(rest, data.child(key))
}
attributeName.split('.').toList match {
case Nil => error("bad attibute name: " + attributeName)
case value :: Nil =>
MBeanValue(mbeanServer.getAttribute(name, value))
case compositeName :: rest =>
parseComposite(rest, MBeanValue(mbeanServer.getAttribute(name, compositeName)))
}
}
}