jmxtrans-agent is a version of jmxtrans intended to be used as a java agent. JmxTrans Agent has zero dependencies to ease integration.
Download the latest release of jmxtrans-agent-<version>.jar
Sample setenv.sh
for Apache Tomcat
export JAVA_OPTS="$JAVA_OPTS -javaagent:/path/to/jmxtrans-agent-1.2.10.jar=jmxtrans-agent.xml"
jmxtrans-agent.xml
is the configuration file, can be classpath relative (classpath:…
), http(s) (http(s)://...
) or file system based (relative to the working dir)For some application servers like JBoss, delaying premain is needed to start the agent, see WFLY-3054
This has been confirmed to be needed with JBoss 5.x, 6.x, 7.x and Wildfly 8.x. This is because a
custom MBeanServer
is used by programmatically setting the "javax.management.builder.initial"
system property
in JBoss's startup sequence. If the PlatformMBeanServer
is initialized before this is set, the
PlatformMBeanServer
will not use the implementation JBoss expects.
For versions >=1.2.8, you can wait for the custom MBeanServer to be defined, set jmxtrans.agent.premain.waitForCustomMBeanServer=true
:
# delays calling premain() in jmxtrans agent until javax.management.builder.initial is set, up to 2 minutes
java -Djmxtrans.agent.premain.waitForCustomMBeanServer=true
This usually takes less than a second. If needed, you can optionally increase the timeout to wait by setting jmxtrans.agent.premain.waitForCustomMBeanServer.timeoutInSeconds
(defaults to 2 minutes):
# delays calling premain() in jmxtrans agent until javax.management.builder.initial is set, up to 5 minutes
java -Djmxtrans.agent.premain.waitForCustomMBeanServer=true -Djmxtrans.agent.premain.waitForCustomMBeanServer.timeoutInSeconds=300
For versions <1.2.8, you have to add a flat delay. To add a flat delay set jmxtrans.agent.premain.delay
(value in seconds):
# delays calling premain() in jmxtrans agent for 30 seconds
java -Djmxtrans.agent.premain.delay=30
To select which attributes to collect, use the attribute
or attributes
attribute on the query
element. attribute
accepts a
single attribute while attributes
accepts a comma-separated list of attributes to collect. If you do not specify any attributes, all attributes
of the MBean will be dynamically discovered and collected. Use the expression language #attribute#
in the resultAlias
to use the attribute name in the metric name when collecting many attributes.
Example - collect the ThreadCount
attribute from the Threading MBean:
<query objectName="java.lang:type=Threading" attribute="ThreadCount"
resultAlias="jvm.thread.count"/>
Example - collect the SystemLoadAverage
gauge attribute from the OperatingSystem MBean:
<query objectName="java.lang:type=OperatingSystem" attributes="SystemLoadAverage"
type="gauge" resultAlias="#attribute#"/>
(i) Note that the type
attribute is customizable. Output writers such as the LibratoWriter, StatsDOutputWriter and PerMinuteSummarizerOutputWriter are aware of the type
s counter
and gauge
and assume that non defined type
means counter
.
Example - collect ThreadCount
and TotalStartedThreadCount
from the Threading MBean:
<query objectName="java.lang:type=Threading" attributes="ThreadCount,TotalStartedThreadCount"
resultAlias="jvm.threads.#attribute#"/>
Example - collect all attributes from the Threading MBean:
<query objectName="java.lang:type=Threading" resultAlias="jvm.threads.#attribute#"/>
Use attribute
or attributes
to specify the values to lookup. No additional configuration is required.
See javax.management.MBeanServer.getAttribute(objectName, attribute)
.
<query objectName="java.lang:type=Threading" attribute="ThreadCount"
resultAlias="jvm.thread"/>
Use key
to specify the key of the CompositeData or Map. See javax.management.openmbean.CompositeData#get(key)
.
<query objectName="java.lang:type=Memory" attribute="HeapMemoryUsage" key="used"
resultAlias="jvm.heapMemoryUsage.used"/>
key
in the <query />
declaration.#key#
(or its synonym #compositeDataKey#
) in the resultAlias
to use the composite data key in the metric name. Sample: <query objectName="java.lang:type=Memory" attribute="HeapMemoryUsage" resultAlias="jvm.heapMemoryUsage.#key#"/>
Use position
to specify the value to lookup. Position is `0 based.
<query objectName="MyApp:type=MyMBean" attribute="MyMultiValuedAttribute" position="2"
resultAlias="myMBean.myMultiValuedAttributeValue"/>
position
is 0 basedposition
in the <query />
declaration.#position#
in the resultAlias
to use the multi-valued data position in the metric name. Sample: <query objectName="MyApp:type=MyMBean" attribute="MyMultiValuedAttribute" resultAlias="myMBean.myMultiValuedAttributeValue.#position#"/>
resultAlias
is specified, the generated metric name is suffixed by _#position#
. Sample:myMBean.myMultiValuedAttributeValue_0`
The configuration can be dynamically reloaded at runtime. To enable this feature, enable it with the reloadConfigurationCheckIntervalInSeconds
element, e.g.:
<reloadConfigurationCheckIntervalInSeconds>60</reloadConfigurationCheckIntervalInSeconds>
The interval for collecting data using the specified queries and invocations can be specified with the element collectIntervalInSeconds
, e.g.:
<collectIntervalInSeconds>20</collectIntervalInSeconds>
The collect interval can be overridden for a specific query or invocation by setting the collectIntervalInSeconds
attribute, e.g.:
<query objectName="java.lang:type=Threading" attributes="ThreadCount,TotalStartedThreadCount"
resultAlias="jvm.threads.#attribute#" collectIntervalInSeconds="5"/>
The ResultNameStrategy
is the component in charge of building the metric name. The default implementation uses the resultAlias
if provided
and otherwise will build the metric name using the ObjectName
.
You can use your own implementation for the ResultNameStrategy
<resultNameStrategy class="com.mycompany.jmxtrans.agent.MyResultNameStrategyImpl">
<attrA>valA</attrA>
<attrB>valB</attrB>
</resultNameStrategy>
You then have to make this implementation available in the classpath (adding it the the jmxtrans-agent jar, adding it to the boot classpath ...)
Sample jmxtrans-agent.xml
configuration file for Tomcat:
<jmxtrans-agent>
<queries>
<!-- OS -->
<query objectName="java.lang:type=OperatingSystem" attribute="SystemLoadAverage" resultAlias="os.systemLoadAverage"/>
<!-- JVM -->
<query objectName="java.lang:type=Memory" attribute="HeapMemoryUsage" key="used"
resultAlias="jvm.heapMemoryUsage.used"/>
<query objectName="java.lang:type=Memory" attribute="HeapMemoryUsage" key="committed"
resultAlias="jvm.heapMemoryUsage.committed"/>
<query objectName="java.lang:type=Memory" attribute="NonHeapMemoryUsage" key="used"
resultAlias="jvm.nonHeapMemoryUsage.used"/>
<query objectName="java.lang:type=Memory" attribute="NonHeapMemoryUsage" key="committed"
resultAlias="jvm.nonHeapMemoryUsage.committed"/>
<query objectName="java.lang:type=ClassLoading" attribute="LoadedClassCount" resultAlias="jvm.loadedClasses"/>
<query objectName="java.lang:type=Threading" attribute="ThreadCount" resultAlias="jvm.thread"/>
<!-- TOMCAT -->
<query objectName="Catalina:type=GlobalRequestProcessor,name=*" attribute="requestCount"
resultAlias="tomcat.requestCount"/>
<query objectName="Catalina:type=GlobalRequestProcessor,name=*" attribute="errorCount"
resultAlias="tomcat.errorCount"/>
<query objectName="Catalina:type=GlobalRequestProcessor,name=*" attribute="processingTime"
resultAlias="tomcat.processingTime"/>
<query objectName="Catalina:type=GlobalRequestProcessor,name=*" attribute="bytesSent"
resultAlias="tomcat.bytesSent"/>
<query objectName="Catalina:type=GlobalRequestProcessor,name=*" attribute="bytesReceived"
resultAlias="tomcat.bytesReceived"/>
<!-- APPLICATION -->
<query objectName="Catalina:type=Manager,context=/,host=localhost" attribute="activeSessions"
resultAlias="application.activeSessions"/>
</queries>
<outputWriter class="org.jmxtrans.agent.GraphitePlainTextTcpOutputWriter">
<host>localhost</host>
<port>2003</port>
<namePrefix>app_123456.servers.i876543.</namePrefix>
</outputWriter>
<outputWriter class="org.jmxtrans.agent.ConsoleOutputWriter"/>
<collectIntervalInSeconds>20</collectIntervalInSeconds>
</jmxtrans-agent>
Note why XML and not JSON ? because XML parsing is out of the box in the JVM when JSON requires additional libraries.
OutputWriters are very simple to develop, you just have to extend AbstractOutputWriter.java or to implement OutputWriter.java.
Out of the box output writers:
enabled
: to enable/disable the output writer. Optional, default value true
host
: Graphite Carbon listener hostport
: Graphite Carbon Plain Text TCP listener port. Optional, default value 2003
namePrefix
; prefix of the metric name. Optional, default values servers.#hostname#.
where #hostname#
is the auto discovered hostname of computer with .
escaped as _
(InetAddress.getLocalHost().getHostName()
).fileName
: name of the file in which the collected metrics are stored. Optional, default value jmxtrans-agent.data
(in JVM working dir, for example $TOMCAT_HOME/bin
)showTimeStamp
: true or false value that determines if the time stamp is printed with the lines. Optional tag, default is `false.FileOverwriterOutputWriter
but displays "per minute" values for counters of type counter
stdout
ConsoleOutputWriter
but displays "per minute" values for counters of type counter
fileName
: Name of the file in which the collected metrics are stored. Optional, default value jmxtrans-agent.data
(in JVM working dir, for example $TOMCAT_HOME/bin
)maxFileSize
: Maximum file size in MB before file is rolled. Optional, default is 10
maxBackupIndex
: Maximum number of backup files. Optional, default is `5singleLine
: true or false value that determines if all values are printed on a single line. Optional, default is false host
: StatsD listener hostport
: StatsD listener portstatsd
: Optional StatsD server type, statsd, dd or sysdigtags
: Optional StatsD tags for dd and sysdig, i.e. serviceid:SERVICE_ID,environment:devmetricName
: metric name prefix. Optional, default value is machine hostname or IP (all .
are scaped as _
).bufferSize
: max buffer size. Holds data to be sent. Optional, default value is 1024.url
: url to the influxdb server, e.g. <url>http://influx.company.com:8086</url>
- requireddatabase
: name of the database to write to - requireduser
: username for authentication - optionalpassword
: password for authentication - optionaltags
: additional tags to use for all metrics on n1=v1,n2=v2
format, e.g. <tags>#hostname#</tags>
- optionalretentionPolicy
: retention policy to use - optionalconnectTimeoutMillis
: connect timeout for the HTTP connection to influx - optional, defaults to 3000readTimeoutMillis
: read timeout for the HTTP connection to influx - optional, defaults to 5000Output writers configuration support an expression language based on property placeholders with the {prop-name[:default-value]}
syntax (e.g. "${graphite.port:2003}
").
The default-value
is optional. An exception is raised if no default value is defined and the property placeholder is not found.
Environment variables are looked-up in the following order:
System.getProperty("graphite.host")
)System.getenv("graphite.host")
)System.getenv("GRAPHITE_HOST")
)This writer is currently in beta, it might have bugs and the behavior and options might change.
When using the InfluxDbOutputWriter
, the queries' resultAlias
have special semantics. The result alias is a comma-separated list where the first
item is the name of the measurement and the rest of the items are tags to add to metrics collected by the query. For example, the query
<query objectName="java.lang:type=GarbageCollector,name=*"
attributes="CollectionTime,CollectionCount"
resultAlias="#attribute#,garbageCollector=%name%,myTag=foo" />
will result in measurements named as the attributes collected (CollectionTime
and CollectionCount
).
The additional tag garbageCollector
will be added which will correspond to the
name attribute of the object name. In addition, a tag called myTag
with value foo
will be added.
All measurements sent to InfluxDb will have only one field called value
. Multiple fields are currently not supported.
Example complete output writer configuration:
<outputWriter class="org.jmxtrans.agent.influxdb.InfluxDbOutputWriter">
<url>http://localhost:8086</url>
<database>mydb</database>
<user>admin</user>
<password>shadow</password>
<tags>host=#hostname#</tags>
</outputWriter>
os.systemLoadAverage 1.80419921875 1366199958
jvm.heapMemoryUsage.used 20438792 1366199958
jvm.heapMemoryUsage.committed 119668736 1366199958
jvm.nonHeapMemoryUsage.used 15953560 1366199958
jvm.nonHeapMemoryUsage.committed 24313856 1366199958
jvm.loadedClasses 2162 1366199958
jvm.thread 13 1366199958
tomcat.requestCount 0 1366199958
tomcat.requestCount 0 1366199958
tomcat.errorCount 0 1366199958
tomcat.errorCount 0 1366199958
tomcat.processingTime 0 1366199958
tomcat.processingTime 0 1366199958
tomcat.bytesSent 0 1366199958
tomcat.bytesSent 0 1366199958
tomcat.bytesReceived 0 1366199958
tomcat.bytesReceived 0 1366199958
application.activeSessions 0 1366199958
os.systemLoadAverage 1.27734375
jvm.heapMemoryUsage.used 33436016
jvm.heapMemoryUsage.committed 133365760
jvm.nonHeapMemoryUsage.used 23623096
jvm.nonHeapMemoryUsage.committed 24707072
jvm.loadedClasses 3002
jvm.thread 21
tomcat.requestCount 27
tomcat.requestCount 0
tomcat.errorCount 0
tomcat.errorCount 0
tomcat.processingTime 881
tomcat.processingTime 0
tomcat.bytesSent 135816
tomcat.bytesSent 0
tomcat.bytesReceived 0
tomcat.bytesReceived 0
application.activeSessions 0
${ACTIVEMQ_HOME}/jmxtrans-agent/
jmxtrans-agent-1.2.4.jar
under ${ACTIVEMQ_HOME}/jmxtrans-agent/
${ACTIVEMQ_HOME}/bin/activemq
, add in invoke_start()
and invoke_console()
:JMXTRANS_AGENT="-javaagent:${ACTIVEMQ_HOME}/jmxtrans-agent/jmxtrans-agent-1.2.4.jar=${ACTIVEMQ_HOME}/jmxtrans-agent/jmxtrans-agent-activemq.xml"
ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS $JMXTRANS_AGENT"
${ACTIVEMQ_HOME}/jmxtrans-agent/
a config file similar to<jmxtrans-agent>
<queries>
<!-- OS -->
<query objectName="java.lang:type=OperatingSystem" attribute="SystemLoadAverage"
resultAlias="os.systemLoadAverage"/>
<!-- JVM -->
<query objectName="java.lang:type=Memory" attribute="HeapMemoryUsage" key="used"
resultAlias="jvm.heapMemoryUsage.used"/>
<query objectName="java.lang:type=Memory" attribute="HeapMemoryUsage" key="committed"
resultAlias="jvm.heapMemoryUsage.committed"/>
<query objectName="java.lang:type=Memory" attribute="NonHeapMemoryUsage" key="used"
resultAlias="jvm.nonHeapMemoryUsage.used"/>
<query objectName="java.lang:type=Memory" attribute="NonHeapMemoryUsage" key="committed"
resultAlias="jvm.nonHeapMemoryUsage.committed"/>
<query objectName="java.lang:type=ClassLoading" attribute="LoadedClassCount" resultAlias="jvm.loadedClasses"/>
<query objectName="java.lang:type=Threading" attribute="ThreadCount" resultAlias="jvm.thread"/>
<!-- ACTIVE MQ -->
<query objectName="org.apache.activemq:type=Broker,brokerName=*,destinationType=Queue,destinationName=*"
attribute="QueueSize" resultAlias="activemq.%brokerName%.queue.%destinationName%.QueueSize"/>
<query objectName="org.apache.activemq:type=Broker,brokerName=*,destinationType=Queue,destinationName=*"
attribute="EnqueueCount" resultAlias="activemq.%brokerName%.queue.%destinationName%.EnqueueCount"/>
<query objectName="org.apache.activemq:type=Broker,brokerName=*,destinationType=Queue,destinationName=*"
attribute="ExpiredCount" resultAlias="activemq.%brokerName%.queue.%destinationName%.ExpiredCount"/>
<query objectName="org.apache.activemq:type=Broker,brokerName=*,destinationType=Queue,destinationName=*"
attribute="DequeueCount" resultAlias="activemq.%brokerName%.queue.%destinationName%.DequeueCount"/>
<query objectName="org.apache.activemq:type=Broker,brokerName=*,destinationType=Topic,destinationName=*"
attribute="EnqueueCount" resultAlias="activemq.%brokerName%.topic.%destinationName%.EnqueueCount"/>
</queries>
<outputWriter class="org.jmxtrans.agent.GraphitePlainTextTcpOutputWriter">
<host>localhost</host>
<port>2203</port>
</outputWriter>
<outputWriter class="org.jmxtrans.agent.ConsoleOutputWriter">
<enabled>false</enabled>
</outputWriter>
<outputWriter class="org.jmxtrans.agent.RollingFileOutputWriter">
<fileName>rollingJMXOutputFile</fileName>
<maxFileSize>10</maxFileSize>
<maxBackupIndex>4</maxBackupIndex>
</outputWriter>
</jmxtrans-agent>