Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Codahale Metrics: using @Timed metrics annotation in plain Java

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/ )

like image 223
Rolf Avatar asked Feb 13 '15 12:02

Rolf


People also ask

What is @timed annotation in Java?

An annotation for marking a method, constructor, or class as timed. The metric will be registered in the application MetricRegistry. Given a method annotated with @Timed like this: @Timed(name = "fancyName") public String fancyName(String name) { return "Sir Captain " + name; }

What is the use of @timed annotation?

Add @Timed to: A controller class to enable timings on every request handler in the controller. A method to enable for an individual endpoint. This is not necessary if you have it on the class.


2 Answers

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.

like image 173
Andrew Logvinov Avatar answered Oct 04 '22 11:10

Andrew Logvinov


Using @Timed doesn't actually require the use of AOP, as was previously claimed in the top-rated answer, if you're inside a container and using one of Dropwizard's instrumentation libraries. See the Jersey 2.x module for example, which you can see uses reflection (as do the others I looked at), if you read the source.

You can read up on all of these modules in the Dropwizard docs under the corresponding "Instrumenting ____" bullets.

I understand the OP was explicitly NOT working within such a container, but I wanted to offer this info, since many of us looking for this answer may be working on a modern web service that can register such resources in its runtime environment.

like image 27
Michael Zalimeni Avatar answered Oct 04 '22 12:10

Michael Zalimeni