Using a Java Agent to monitor application runtime behavior using Metrics

Shehan Akalanka Perera
4 min readDec 26, 2017

--

Why metrics ? When we are running an application in production we want to get an idea about run time behavior of a product . If we miss this our product will be less effective so people will not interest in our product . Metrics gives a knowledge of product runtime , we can analysis it to get a idea of the runtime of our product. Not only code that we have to care, we must look performance of them to make a good product.

Standard Java Agent

Actually, Java agent is a program that can be executed separately without interfering other processes.We can use Agent to track the methods in a program without changing it.
JVM specify different, separate environments for each agent. And they are independent of others and changes of one do not affect to another.
We can use the agent for different purposes. An agent can Monitor threads, suspend and resume them.Also, monitor classes , change them and do many other functions.
Agents can inspect and modify the shared state of the VM, they also share the native environment in which they execute. Also, an agent can fail other agents. But JVM TI implementations are not capable of preventing destructive interactions between agents.

Sample Agent

This is simple code for Java agent. When we executing the program VM will try to locate our class that we specify in our -javaagent parameter to the VM, and execute its premain method before the main method.

import java.lang.instrument.Instrumentation;

public class Agent {
public static void premain(String arguments, Instrumentation instrumentation){
System.out.println("Premain");
}
}

The parameter Instrumentation we can use it for many things like transform byte-codes , measuring execution time , change byte-codes and etc….

Byte-Buddy

This is a library written by Rafael Winterhalter which can do runtime code generation for the Java virtual machine.
Byte Buddy is a code generation and manipulation library for creating and modifying Java classes during the runtime of a Java application and without the help of a compiler.
It allows the creation of arbitrary classes and is not limited to implementing interfaces for the creation of runtime proxies. Furthermore, Byte Buddy offers a convenient API for changing classes either manually, using a Java agent or during a build.

Instrumentation

Using byte-code instrumentation we can add events to code of methods. For example we can add a event at the beginning of a method,But this will not modify the state or behavior of application.

Instrumentation can simply maintain counters or can statistically sample events and they can be inserted in one of three ways:

  • Static Instrumentation: The class file is instrumented before it is loaded into the VM.
  • Load-Time Instrumentation: When a class file is loaded by the VM, the raw bytes of the class file are sent for instrumentation to the agent.
  • Dynamic Instrumentation: A class which is already loaded (and possibly even running) is modified.

Metrics

We can use Metrics data to get a understand about the runtime behavior of program.There are 5 types of metrics that we can use.

  1. Meters

A meter measures the rate of events over time. In addition to the mean rate, meters also track 1-, 5-, and 15-minute moving averages.

2. Timers

A timer measures both the rate that a particular piece of code is called and the distribution of its duration.

3.Counters

A counter is just a gauge for an atomic instance. We can increment or decrement its value.

4.Histogram

A histogram measures the statistical distribution of values in a stream of data. In addition to minimum, maximum, mean, etc., it also measures median, 75th, 90th, 95th, 98th, 99th, and 99.9th percentiles.

5.Gauges

A gauge is an instantaneous measurement of a any value that we need .

Wso2-performance-common

In this we use Netty-server for send a request for the server and get the same output back.

How use wso2-performance-common

  1. Go to the wso2-performance-common in github and clone it.
git clone https://github.com/wso2/performance-common.git

2.Go to the directory and install the package

 mvn clean install

3.Run Netty-server

3.1 Go to performance-common/distribution/target and extract performance-common-distribution-0.1.0-SNAPSHOT.tar.gz

3.2 Then go to performance-common-distribution-0.1.0-SNAPSHOT/netty-service and run netty-server

./netty-start.sh

4.Sending Request for netty-server

curl -v http://localhost:8688 -d ‘Request’

5.Output

* Rebuilt URL to: http://localhost:8688/
* Trying 127.0.0.1…
* Connected to localhost (127.0.0.1) port 8688 (#0)
> POST / HTTP/1.1
> Host: localhost:8688
> User-Agent: curl/7.47.0
> Accept: */*
> Content-Length: 7
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 7 out of 7 bytes
< HTTP/1.1 200 OK
< content-type: application/x-www-form-urlencoded
< content-length: 7
< connection: keep-alive
<
* Connection #0 to host localhost left intact
Request

How set Java agent for measure metrics

  1. Download Javaagent-Metrics from hithub
git clone https://github.com/ShehanPerera/Javaagent-Metrics.git

2. Go to Javaagent-Metrics directory and install it

mvn clean install

3.Go to target folder and copy javaagent-metrics-1.01.0-SNAPSHOT.jar file and paste to performance-common/distribution/target/performance-common-distribution-0.1.0-SNAPSHOT folder.

4.Change netty-start.sh file and add javaagent

....echo "Starting Netty"
nohup java -Xms4g -Xmx4g -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:$gc_log_file -javaagent:javaagent-metrics-1.01.0-SNAPSHOT.jar \
-jar $service_name-0.1.0-SNAPSHOT.jar --worker-threads 2000 --sleep-time $sleep_time > netty.out 2>&1 &
.....

5. Run netty-server and send request ,Goto `jconsole` and we can get metrics data from it

Sample Metrics Meters

--

--