Codahale Metrics: using @Timed metrics annotation in plain Java

Rolf picture Rolf · Feb 13, 2015 · Viewed 49.1k times · Source

I am trying to add metrics to a plain Java application using codahale metrics. I'd like to use the @Timed annotation, but it is unclear to me which MetricRegistry it uses, or how to tell it which MetricRegistry to use. The application is a plain Java 8 application, built with Maven 3, no Spring, no Hibernate.

I can not find any documentation on how to implement @Timed in the dropwizard documentation: https://dropwizard.github.io/metrics/3.1.0/manual/

I've added these dependencies:

<dependency>
  <groupId>io.dropwizard.metrics</groupId>
  <artifactId>metrics-core</artifactId>
  <version>3.1.0</version>
</dependency>
<dependency>
  <groupId>com.codahale.metrics</groupId>
  <artifactId>metrics-annotation</artifactId>
  <version>3.0.2</version>
</dependency>

When I use a programatic call to Timer, I can get reports because I know which MetricsRegistry is used:

static final MetricRegistry metrics = new MetricRegistry();
private void update() throws SQLException {
  Timer.Context time = metrics.timer("domainobject.update").time();
  try {
    [...]
  } finally {
    time.stop();
  }
}

But when I use the much more elegant @Timed annotation, I have no idea which registry is used, and therefore I can not create a reporter, which means I can not get the metrics reported (I'm not even sure if this actually does anything):

@Timed(name = "domainobject.update")
private void update() throws SQLException {
    [...]
}

Please advise on how to make the @Timed and other Metrics annotations work in a regular Java application.

Additional info: The reason I am finding this strange is that I have added the Lombok framework and the @Slf4j annotations do work. I added Lombok as a dependency in the maven pom.xml:

<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <version>1.14.8</version>
</dependency>

And I can use the @Sl4fj class annotation to add a logger to the class without cluttering up the member variables:

@Slf4j
public class App {
  public void logsome(){
    log.info("Hello there");
  }
}

So if that's possible by just adding a dependency, I reckon I am just missing a dependency or configuration to get the codahale @Timed annotation work, as described above.

(by the way, check out Lombok, it will make your life easier: http://projectlombok.org/ )

Answer

Andrew Logvinov picture Andrew Logvinov · Feb 14, 2015

Long story short, you cannot use @Timed without some kind of AOP (be it Spring AOP or AspectJ).

A week or two ago, I also decided to add metrics to our project and chose AspectJ for this task (mostly because I used it in the past for similar purpose and because it allows for compile-time weaving while Spring allows only runtime via proxies).

You should be able to find all the necessary information and instructions here: https://github.com/astefanutti/metrics-aspectj.

As for Lombok, I guess they use built-in javac annotations processor:

Another point of contention is the implementation of both the code supporting IDE integration as well as the javac annotation processor. Both of these pieces of Project Lombok make use of non-public APIs to accomplish their sorcery. This means that there is a risk that Project Lombok will be broken with subsequent IDE or JDK releases.