Application Metrics for Java™ is composed of:
- An Agent which collects and publishes data
- API to allow data providers to send data to the Agent and listeners to receive data from the Agent
- Data providers
- Web application utilizing RuntimeTools/graphmetrics to visualize the data
com.ibm.javametrics.agent
package implements an Agent that stores data added via the API and emits data to receivers.
Javametrics provides a Java API to interface with the Agent. The interface in the com.ibm.javametrics
package consists of:
Javametrics
- provides API to send data to the agent and to register listeners.JavametricsListener
- implemented by registered listeners.Topic
- API to send data to the agent for a named topic.
com.ibm.javametrics.dataproviders.DataProviderManager
is instantiated by com.ibm.javametrics.impl.JavametricsImpl
.
It gathers data from the data providers every 2 seconds and sends the data to the agent using the Javametrics API.
Data providers in the com.ibm.javametrics.dataproviders
package are:
CPUDataProvider
- system and process cpu usage dataGCDataProvider
- garbage collection statisticsMemoryPoolDataProvider
- heap and native memory usage dataEnvironmentDataProvider
- runtime environment data
Bytecode Instrumentation is used to gather HTTP data. Servlet and JSP classes are instrumented with callbacks to track and time the requests. The callbacks use the Javametrics API to send the data to the agent.
The web application uses the javascript graphs from the RuntimeTools/graphmetrics project. The index.html communicates with the server side over a WebSocket connecting to com.ibm.javametrics.web.JavametricsWebSocket
which manages the session. JavametricsWebSocket
registers itself with com.ibm.javametrics.web.DataHandler
as an Emitter
.
DataHandler
registers itself as a listener using the Javametrics API and implements the receive(...)
method which receives data from the agent. Some processing of the data is performed, e.g. aggregating HTTP request data, before sending on the data via the emit(...)
method of any registered Emitters.
com.ibm.javametrics.instrument.Agent
uses the java.lang.instrument
package to create a java instrumentation agent. ASM is used to perform the code injection.
Agent
is defined as the Premain-Class in the jar manifest. Thepremain(...)
method is invoked on startup when the-javaagent:<path to jar>
command line option is used. This adds aClassFileTransformer
to the Java instrumentation.ClassTransformer
is ajava.lang.instrument.ClassFileTransformer
that implements thetransform(...)
method. The class bytecode is passed as a parameter totransform
. A chain of ASMClassReader
.ClassWriter
and JavametricsClassAdaptor
is set up which are called via a visitor pattern to perform any necessary byetcode changes.ClassAdapter
extends the ASMCLassVisitor
. In thevisit
code we determine which classes we want to instrument. In thevisitMethod
code we create an ASMMethodVisitor
for each method we want to instrument.
To instrument HTTP request we inject callbacks on method entry and exit for:
- Servlets - classes that extend
javax.servlet.http.HttpServlet
. MethodsdoGet
,doPost
andservice
- JSP pages - classes that implement
javax.servlet.jsp.HttpJspPage
. Method_jspService
com,ibm.javametrics.instrument.ClassAdapter
will create a ServletCallbackAdapter
which is the MethodVisitor that will inject the callback bytecode.
ServletCallbackAdapter
extends org.objectweb.asm.commons.AdviceAdapter
which provides the simplest methods for generating and injecting code. We implement the visitor methods onMethodEnter
and onMethodExit
to inject calls to the static methods in ServletCallback
.