-
Notifications
You must be signed in to change notification settings - Fork 6
Tutorial: Instrumentation and Monitoring
Instrumentation allows us to add extra instructions on top of our code, without modifying the code itself. We might want to do this for several reasons, such as logging, monitoring, calculating code coverage, etc.
In pankti and rick, we use instrumentation to serialize objects when a method is invoked during the execution of an application. For this tutorial, we use instrumentation to simply count the number of times a specific method gets invoked during the execution of an application.
First, build pankti
cd pankti/
mvn clean install
For this tutorial, we work with an open-source Java project called BroadLeafCommerce. Let's start by cloning it.
git clone git@github.com:BroadleafCommerce/BroadleafCommerce.git --branch broadleaf-6.2.0-GA
The developers of BroadLeafCommerce also provide a demo application called DemoSite. Let's clone that as well. We will use DemoSite for our experiments.
git clone git@github.com:BroadleafCommerce/DemoSite.git
You can build and run it, following the steps in its README. Play around with the website (localhost:8443) to get familiar with it.
Glowroot is an open-source APM agent. We use it for instrumentation and monitoring. Follow the instructions on the website to download it. Also, create a directory called plugins
within glowroot/
.
You can try to attach glowroot as a javaagent
to DemoSite, by updating its POM and then running DemoSite.
...
<properties>
<debug.args>-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=${debug.port}</debug.args>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<boot.jvm.memory>-Xmx1536M</boot.jvm.memory>
- <boot.jvm.args>${boot.jvm.memory} ${debug.args}</boot.jvm.args>
+ <glowroot.plugin.jar>-javaagent:/path/to/glowroot/glowroot.jar</glowroot.plugin.jar>
+ <boot.jvm.args>${boot.jvm.memory} ${debug.args} ${glowroot.plugin.jar}</boot.jvm.args>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.uri>${project.baseUri}</project.uri>
</properties>
...
Let's instrument the method getPriceForQuantity(long)
defined within the class org.broadleafcommerce.core.catalog.service.dynamic.DynamicSkuPrices
, and count the number of times it gets invoked as DemoSite executes.
First,
cd pankti-instrument/
Find the class se.kth.castor.pankti.instrument.plugins.CounterAspect
. The nested TargetMethodAdvice
within CounterAspect
has the @Pointcut
annotation. This is where we specify the className
, the methodName
, the methodParameterTypes
, and a descriptive timerName
for the method we want to instrument. Let's replace the placeholder values with the details of getPriceForQuantity(long)
.
public class CounterAspect {
private static int INVOCATION_COUNT;
- @Pointcut(className = "fully.qualified.path.to.class",
- methodName = "methodToInstrument",
- methodParameterTypes = {"param1", "param2"},
- timerName = "Timer - name")
+ @Pointcut(className = "org.broadleafcommerce.core.catalog.service.dynamic.DynamicSkuPrices",
+ methodName = "getPriceForQuantity",
+ methodParameterTypes = {"long"},
+ timerName = "Timer - DynamicSkuPrices.getPriceForQuantity")
public static class TargetMethodAdvice implements AdviceTemplate {
...
@OnBefore
...
@OnReturn
...
}
}
The methods annotated with @OnBefore
and @OnReturn
within TargetMethodAdvice
tell Glowroot to increment a counter whenever getPriceForQuantity(long)
gets invoked, and update a file with this value.
Next, let's modify ./src/main/resources/META-INF/glowroot.plugin.json
to add our aspect class:
{
"name": "pankti/rick plugin to serialize objects",
"id": "pankti-rick-plugin",
"properties": [
{
"name": "stackTraceThresholdMillis",
"type": "double",
"default": 0.0,
"label": "Stack trace threshold (millis)",
"checkboxLabel": "",
"description": "Any query that exceeds this threshold will have a stack trace captured and attached to it. An empty value will not collect any stack traces, a zero value will collect a stack trace for every query."
}
],
"aspects": [
+ "se.kth.castor.pankti.instrument.plugins.CounterAspect"
]
}
That's it! We can now package this into a plugin with
mvn clean install
This produces pankti-instrument/target/pankti-instrument-<version>-jar-with-dependencies.jar
. Copy this jar and paste it in the glowroot/plugins/
directory we created in Step 1.
Now that we've added the plugin with the instructions to monitor the invocations of getPriceForQuantity
, run DemoSite (make sure you've modified the DemoSite POM as presented in Step 1). Click around the website and interact with the products, add them to the cart, etc. You'll find that /tmp/pankti-object-data/
now has two files.
The first one, org.broadleafcommerce.core.catalog.service.dynamic.DynamicSkuPrices.getPriceForQuantity_long-count.txt
has the invocation counter that gets updated with each invocation of getPriceForQuantity
. The second file is called invoked-methods.csv
, which in our case would have org.broadleafcommerce.core.catalog.service.dynamic.DynamicSkuPrices.getPriceForQuantity_long
. You can stop the DemoSite server when you're done interacting with the site.
With this tutorial, we learned how to instrument a method with Glowroot, and how to see this instrumentation in action. You can now head over to the pankti and rick tutorials, to see how we use instrumentation to serialize objects, and use them to generate tests.