How to capture custom metrics without app code changes using the Java Agent Plugin


The Elastic APM Java Agent automatically tracks many metrics, including those that are generated through Micrometer or the OpenTelemetry Metrics API. So if your application (or the libraries it includes) already exposes metrics from one of those APIs, installing the Elastic APM Java Agent is the only step required to capture them. You'll be able to visualize and configure thresholds, alerts, and anomaly detection — and anything else you want to use them for!

The next simplest option is to generate custom metrics directly from your code (e.g., by adding code using the OpenTelemetry Metrics API directly into the application). The major downside of that approach is that it requires modifying the application, so if you can't or don't want to do that, you can easily produce the desired custom metrics by adding instrumentation to the Elastic APM Java Agent via a plugin.

This article deals with the situation where the application you are monitoring doesn't emit the custom metrics you'd like it to, and you can't directly change the code or config to make it do so. Instead, you can use a plugin to automatically instrument the application via the Elastic APM Java Agent, which will then make the application emit the custom metrics you desire.

Elastic Kibana Lens
Using Elastic Kibana Lens to analyze APM telemetry on various measures

Plugin basics

The basics of the Elastic APM Java Agent, and how to easily plugin instrumentation, are detailed in the article "Create your own instrumentation with the Java Agent Plugin." Generating metrics from a plugin is just another type of instrumentation, and the referenced article provides detailed step-by-step instructions with a worked example of how to create a plugin with custom instrumentation. 

For this article, I assume you understand how to create a plugin with custom instrumentation based on that previous article, as well as the example application (a simple webserver ExampleBasicHttpServer) from our plugin example repo.

The custom metric

For our example application, which is an HTTP server (ExampleBasicHttpServer) we'd like to add a custom metric 'page_views' which increments each time the ExampleBasicHttpServer application handles any request. That means the instrumentation we'll add will be triggered by the same ExampleBasicHttpServer.handleRequest() method used in "Create your own instrumentation with the Java Agent Plugin."

15-minute line visualization
A 15-minute line visualization of the page_views metric using Elastic APM

Using the Plugin/OpenTelemetry API

Essentially the only difference to that article is that for metrics, we'll use the OpenTelemetry metrics API instead of the OpenTelemetry tracing API.

In particular for the metrics, the advice method for the handleRequest() method is the following code:

if (pageViewCounter == null) {
    pageViewCounter = GlobalOpenTelemetry
        .setDescription("Page view count")

That is, lazily create the meter when it's first needed, and then on each invocation of the ExampleBasicHttpServer.handleRequest() method, increment the page view counter.

Everything else — setting up instrumentation, finding the method to instrument, building the plugin — is the same as in the article "

Create your own instrumentation with the Java Agent Plugin." The full metrics example is implemented in the plugin example repo, and the actual full metrics instrumentation implementation is ExampleMetricsInstrumentation.

15-minute bar chart visualization
A 15-minute bar chart visualization of the page_views metric using Elastic APM

Try it out!

That's it! To run the agent with the plugin, just build and include the jar as described in  "Create your own instrumentation with the Java Agent Plugin," in the directory specified by the plugins_dir configuration option. The plugin example repo provides a full tested implementation — just clone it and mvn install to see it working.

The best place to get started with Elastic APM is in the cloud. Begin your free trial of Elastic Cloud today!

The release and timing of any features or functionality described in this post remain at Elastic's sole discretion. Any features or functionality not currently available may not be delivered on time or at all.