13

I'm trying to automatically publish metrics to my MetricRegistry using annotations like @Timed (http://metrics.dropwizard.io/3.1.0/apidocs/com/codahale/metrics/annotation/package-summary.html).

This doesn't work out of the box. On searching for questions, I found Codahale Metrics: using @Timed metrics annotation in plain Java where it was mentioned that the only way for this to work would be by using aspectj. I added this to my project, but still do not see my metrics in my MetricRegistry.

This is my pom file. I added a librato library, which loads in com.codahale.metrics:metrics-annotation.

<dependency>
  <groupId>io.astefanutti.metrics.aspectj</groupId>
  <artifactId>metrics-aspectj</artifactId>
  <version>${metrics-aspectj.version}</version>
</dependency>
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjrt</artifactId>
  <version>1.8.10</version>
</dependency>

  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.7</version>
    <configuration>
      <showWeaveInfo>true</showWeaveInfo>
      <source>1.8</source>
      <target>1.8</target>
      <complianceLevel>1.8</complianceLevel>
      <encoding>UTF-8</encoding>
      <verbose>true</verbose>
      <aspectLibraries>
        <aspectLibrary>
          <groupId>io.astefanutti.metrics.aspectj</groupId>
          <artifactId>metrics-aspectj</artifactId>
        </aspectLibrary>
      </aspectLibraries>
    </configuration>
    <executions>
      <execution>
        <phase>process-sources</phase>
        <goals>
          <goal>compile</goal>
          <goal>test-compile</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

<dependency>
  <groupId>com.librato.metrics</groupId>
  <artifactId>metrics-librato</artifactId>
  <version>${metrics-librato.version}</version>
</dependency>

This is how I'm trying to use the metrics

@Metrics(registry = "default") // this.metricRegistry is default
public class Foo {
    @Inject
    private MetricRegistry metricRegistry;
    ...

    @Metered(name = "meterName")
    public void bar() {
        Meter meter = metricRegistry.meter("manual");
        meter.mark();
        // this.metricRegistry does not contain "meterName" after the ConsoleReporter prints the metrics for "default"
        // this.metricRegistry contains "manual" after the ConsoleReporter prints the metrics for "default"
    }

I'm seeing this in my logs when I compile:

[INFO] Extending interface set for type 'Foo' (Foo.java) to include 'io.astefanutti.metrics.aspectj.Profiled' (MetricAspect.aj)
[INFO] Type 'Foo' (Foo.java) has intertyped field from 'io.astefanutti.metrics.aspectj.MetricAspect' (MetricAspect.aj:'java.util.Map<java.lang.String,io.astefanutti.metrics.aspectj.AnnotatedMetric<com.codahale.metrics.Gauge>> io.astefanutti.metrics.aspectj.Profiled.gauges')
[INFO] Type 'Foo' (Foo.java) has intertyped field from 'io.astefanutti.metrics.aspectj.MetricAspect' (MetricAspect.aj:'java.util.Map<java.lang.String,io.astefanutti.metrics.aspectj.AnnotatedMetric<com.codahale.metrics.Meter>> io.astefanutti.metrics.aspectj.Profiled.meters')
[INFO] Type 'Foo' (Foo.java) has intertyped field from 'io.astefanutti.metrics.aspectj.MetricAspect' (MetricAspect.aj:'java.util.Map<java.lang.String,io.astefanutti.metrics.aspectj.AnnotatedMetric<com.codahale.metrics.Timer>> io.astefanutti.metrics.aspectj.Profiled.timers')
[INFO] Join point 'staticinitialization(void Foo.<clinit>())' in Type 'Foo' (Foo.java:46) advised by after advice from 'io.astefanutti.metrics.aspectj.MetricStaticAspect' (metrics-aspectj-1.2.0.jar!MetricStaticAspect.class:41(from MetricStaticAspect.aj))
[INFO] Join point 'method-execution(void Foo.bar())' in Type 'Foo' (Foo.java:74) advised by around advice from 'io.astefanutti.metrics.aspectj.TimedAspect' (metrics-aspectj-1.2.0.jar!TimedAspect.class:26(from TimedAspect.aj))
[INFO] Join point 'method-execution(void Foo.bar())' in Type 'Foo' (Foo.java:74) advised by before advice from 'io.astefanutti.metrics.aspectj.MeteredAspect' (metrics-aspectj-1.2.0.jar!MeteredAspect.class:26(from MeteredAspect.aj))

It seems to indicate the annotated metrics I setup are working properly. However, I also see this in my logs too

[WARNING] advice defined in io.astefanutti.metrics.aspectj.TimedStaticAspect has not been applied [Xlint:adviceDidNotMatch]
    /Users/x/.m2/repository/io/astefanutti/metrics/aspectj/metrics-aspectj/1.2.0/metrics-aspectj-1.2.0.jar!io/astefanutti/metrics/aspectj/TimedStaticAspect.class:26

[WARNING] advice defined in io.astefanutti.metrics.aspectj.ExceptionMeteredAspect has not been applied [Xlint:adviceDidNotMatch]
    /Users/x/.m2/repository/io/astefanutti/metrics/aspectj/metrics-aspectj/1.2.0/metrics-aspectj-1.2.0.jar!io/astefanutti/metrics/aspectj/ExceptionMeteredAspect.class:26

[WARNING] advice defined in io.astefanutti.metrics.aspectj.ExceptionMeteredStaticAspect has not been applied [Xlint:adviceDidNotMatch]
    /Users/x/.m2/repository/io/astefanutti/metrics/aspectj/metrics-aspectj/1.2.0/metrics-aspectj-1.2.0.jar!io/astefanutti/metrics/aspectj/ExceptionMeteredStaticAspect.class:26

[WARNING] advice defined in io.astefanutti.metrics.aspectj.MeteredStaticAspect has not been applied [Xlint:adviceDidNotMatch]
    /Users/x/.m2/repository/io/astefanutti/metrics/aspectj/metrics-aspectj/1.2.0/metrics-aspectj-1.2.0.jar!io/astefanutti/metrics/aspectj/MeteredStaticAspect.class:26

[WARNING] advice defined in io.astefanutti.metrics.aspectj.TimedAspect has not been applied [Xlint:adviceDidNotMatch]
    /Users/x/.m2/repository/io/astefanutti/metrics/aspectj/metrics-aspectj/1.2.0/metrics-aspectj-1.2.0.jar!io/astefanutti/metrics/aspectj/TimedAspect.class:26

[WARNING] advice defined in io.astefanutti.metrics.aspectj.TimedStaticAspect has not been applied [Xlint:adviceDidNotMatch]
    /Users/x/.m2/repository/io/astefanutti/metrics/aspectj/metrics-aspectj/1.2.0/metrics-aspectj-1.2.0.jar!io/astefanutti/metrics/aspectj/TimedStaticAspect.class:26

[WARNING] advice defined in io.astefanutti.metrics.aspectj.MetricAspect has not been applied [Xlint:adviceDidNotMatch]
    /Users/x/.m2/repository/io/astefanutti/metrics/aspectj/metrics-aspectj/1.2.0/metrics-aspectj-1.2.0.jar!io/astefanutti/metrics/aspectj/MetricAspect.class:45

[WARNING] advice defined in io.astefanutti.metrics.aspectj.ExceptionMeteredAspect has not been applied [Xlint:adviceDidNotMatch]
    /Users/x/.m2/repository/io/astefanutti/metrics/aspectj/metrics-aspectj/1.2.0/metrics-aspectj-1.2.0.jar!io/astefanutti/metrics/aspectj/ExceptionMeteredAspect.class:26

[WARNING] advice defined in io.astefanutti.metrics.aspectj.MeteredAspect has not been applied [Xlint:adviceDidNotMatch]
    /Users/x/.m2/repository/io/astefanutti/metrics/aspectj/metrics-aspectj/1.2.0/metrics-aspectj-1.2.0.jar!io/astefanutti/metrics/aspectj/MeteredAspect.class:26

[WARNING] advice defined in io.astefanutti.metrics.aspectj.ExceptionMeteredStaticAspect has not been applied [Xlint:adviceDidNotMatch]
    /Users/x/.m2/repository/io/astefanutti/metrics/aspectj/metrics-aspectj/1.2.0/metrics-aspectj-1.2.0.jar!io/astefanutti/metrics/aspectj/ExceptionMeteredStaticAspect.class:26

[WARNING] advice defined in io.astefanutti.metrics.aspectj.MetricStaticAspect has not been applied [Xlint:adviceDidNotMatch]
    /Users/x/.m2/repository/io/astefanutti/metrics/aspectj/metrics-aspectj/1.2.0/metrics-aspectj-1.2.0.jar!io/astefanutti/metrics/aspectj/MetricStaticAspect.class:41

[WARNING] advice defined in io.astefanutti.metrics.aspectj.MeteredStaticAspect has not been applied [Xlint:adviceDidNotMatch]
    /Users/x/.m2/repository/io/astefanutti/metrics/aspectj/metrics-aspectj/1.2.0/metrics-aspectj-1.2.0.jar!io/astefanutti/metrics/aspectj/MeteredStaticAspect.class:26

Here is my app setup

@Override
public void run(AppConfiguration configuration, Environment environment) {

    ConsoleReporter reporter = ConsoleReporter.forRegistry(environment.metrics())
            .convertRatesTo(TimeUnit.SECONDS)
            .convertDurationsTo(TimeUnit.MILLISECONDS)
            .build();
    reporter.start(2, TimeUnit.MINUTES);
}
user2158382
  • 4,430
  • 12
  • 55
  • 97
  • Did you add the metrics config in your yaml file? – Dhruvil Vaghela Dec 28 '17 at 15:21
  • @DhruvilsinhVaghela what config in yaml? I don't see anything in aspectj docs (https://github.com/astefanutti/metrics-aspectj) nor dropwizard metrics docs (http://metrics.dropwizard.io/3.1.0/getting-started/) – user2158382 Dec 29 '17 at 16:58
  • What is the question? Does it work with the AspectJ integration for Dropwizard? Did you even read the read-me at https://github.com/astefanutti/metrics-aspectj (just scroll down and keep reading)? There is a lot of explanation about metrics registry resolution and how to influence it. – kriegaex Dec 30 '17 at 00:50
  • @kriegaex please see my edit – user2158382 Jan 03 '18 at 01:53
  • what if you declare your `metricRegistry` field like this: `private MetricRegistry metricRegistry = SharedMetricRegistries.getOrCreate("default");` ? Maybe the injected value is a different registry than the static registry named 'default' that the aspect will work with. – Nándor Előd Fekete Jan 04 '18 at 00:40
  • @NándorElődFekete I made that change, but the `manual` metric still appears. This tells me that the injected value is the same registry as the static registry named `default` – user2158382 Jan 04 '18 at 00:51
  • Then maybe I don't understand what you're trying to achieve. There is metering done by the aspects for the annotated methods and there is metering done by your code programmatically. You want them to end up in the same registry? Could you please clarify your question? – Nándor Előd Fekete Jan 04 '18 at 01:16
  • @NándorElődFekete I am realy trying to get the annotated methods working. The manual meter metric is just to indicate that manually setting metrics on the `default` registry works, but using the annotations do not work. And yes, in this example, both of the metrics (annotated & manual) should end up in the same registry – user2158382 Jan 04 '18 at 18:11
  • 1
    So, you tried to change the field default value as I recommended in an earlier comment to `private MetricRegistry metricRegistry = SharedMetricRegistries.getOrCreate("default");`, and in your `bar()` method you print it out with `System.out.println(metricRegistry.getMetrics());`, what do you get? I get this: `{Foo.meterName=com.codahale.metrics.Meter@4b9af9a9, manual=com.codahale.metrics.Meter@5387f9e0}`, meaning that both the manual metering and the aspect one end up in the same registry. It's only that the aspect one is prefixed with `Foo.`, so you need to look for it that way. – Nándor Előd Fekete Jan 04 '18 at 18:36
  • If you still don't have the aspect one ending up properly in the same registry as I've shown it happens for me, then you have a different problem and it's probably related to the aspect not getting weaved in. Actually, you could just try debugging it with a breakpoint in the method `com.codahale.metrics.Meter.mark()`. It will be pretty obvious from the stack trace if it stops there called from the advice or not. It will me much easier to get to the root of this problem. – Nándor Előd Fekete Jan 04 '18 at 18:40

2 Answers2

6

I just tried this out and it works well. Here is my entire setup:

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mycompany.app</groupId>
    <artifactId>my-app</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>my-app</name>
    <url>http://maven.apache.org</url>


    <dependencies>

        <dependency>
            <groupId>io.astefanutti.metrics.aspectj</groupId>
            <artifactId>metrics-aspectj</artifactId>
            <version>1.2.0</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <configuration>
                    <aspectLibraries>
                        <aspectLibrary>
                            <groupId>io.astefanutti.metrics.aspectj</groupId>
                            <artifactId>metrics-aspectj</artifactId>
                        </aspectLibrary>
                    </aspectLibraries>
                    <complianceLevel>1.8</complianceLevel>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.4.1</version>
                <configuration>
                    <!-- get all project dependencies -->
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <!-- MainClass in mainfest make a executable jar -->
                    <archive>
                        <manifest>
                            <mainClass>com.mkyong.core.utils.App</mainClass>
                        </manifest>
                    </archive>

                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <!-- bind to the packaging phase -->
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

Note that I need to add the aspectj-maven-plugin. I am also adding an assembly plugin for testing later. This is not really necessary, I just didn't want to go hunting for dependencies on my local box.

My timed class:

package com.mycompany.app;

import java.util.concurrent.ThreadLocalRandom;

import com.codahale.metrics.annotation.Timed;

import io.astefanutti.metrics.aspectj.Metrics;
@Metrics(registry = "someMetrics")
public class TimedClass {

    @Timed(name = "test")
    public void doSomething() {
        try {
            Thread.sleep(200L);
        } catch (InterruptedException e) {
        }
        System.out.println("Done");
    }

    @Timed(name = "test-random")
    public void doSomething2() {
        try {
            Thread.sleep(ThreadLocalRandom.current().nextLong(100L));
        } catch (InterruptedException e) {
        }
        System.out.println("Done");
    }
}

And the app:

package com.mycompany.app;

import java.util.concurrent.TimeUnit;

import com.codahale.metrics.ConsoleReporter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.SharedMetricRegistries;
public class App {

    public static void main(String[] args) throws InterruptedException {
        MetricRegistry metrics =
                SharedMetricRegistries.getOrCreate("someMetrics");

        ConsoleReporter.forRegistry(metrics)
        .convertRatesTo(TimeUnit.SECONDS)
        .convertDurationsTo(TimeUnit.MILLISECONDS)
        .build()
        .start(1, TimeUnit.SECONDS);

        TimedClass c = new TimedClass();
        for(int i = 0; i < 10; i++) {
            c.doSomething();
            c.doSomething2();
        }
        c.doSomething();
        Thread.sleep(1010L);
    }
}

What happens here is that while compiling the maven plugin for aspect will find the annotations you use and apply the aspects.

In your case (and mine) for example this one from the metrics-aspect source:

final aspect TimedAspect {

    pointcut timed(Profiled object) : execution(@Timed !static * (@Metrics Profiled+).*(..)) && this(object);

    Object around(Profiled object) : timed(object) {
        String methodSignature = ((MethodSignature) thisJoinPointStaticPart.getSignature()).getMethod().toString();
        Timer timer = object.timers.get(methodSignature).getMetric();
        Timer.Context context = timer.time();
        try {
            return proceed(object);
        } finally {
            context.stop();
        }
    }
}

All the above does is to say:

Any method that is non static and has a @Timed annotation should be executed within the "around" method.

Now, you may compile and package that by doing:

mvn clean install package

This will print a bunch of warning for non-applied aspects, but that is perfectly fine (we are not actually using them).

Further, you now have a fat-jar containing your application and you can execute it to see if what we did worked:

java -cp target/my-app-1.0-SNAPSHOT-jar-with-dependencies.jar com.mycompany.app.App

Which will print:

artur@pdb-ct ~/dev/repo/my-app $ java -cp target/my-app-1.0-SNAPSHOT-jar-with-dependencies.jar com.mycompany.app.App
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Done
Done
Done
Done
Done
Done
Done
Done
04/01/18 15:10:42 ==============================================================

-- Timers ----------------------------------------------------------------------
com.mycompany.app.TimedClass.test
             count = 4
         mean rate = 4.11 calls/second
     1-minute rate = 0.00 calls/second
     5-minute rate = 0.00 calls/second
    15-minute rate = 0.00 calls/second
               min = 200.21 milliseconds
               max = 200.37 milliseconds
              mean = 200.29 milliseconds
            stddev = 0.06 milliseconds
            median = 200.25 milliseconds
              75% <= 200.32 milliseconds
              95% <= 200.37 milliseconds
              98% <= 200.37 milliseconds
              99% <= 200.37 milliseconds
            99.9% <= 200.37 milliseconds
com.mycompany.app.TimedClass.test-random
             count = 4
         mean rate = 4.10 calls/second
     1-minute rate = 0.00 calls/second
     5-minute rate = 0.00 calls/second
    15-minute rate = 0.00 calls/second
               min = 20.41 milliseconds
               max = 32.28 milliseconds
              mean = 26.07 milliseconds
            stddev = 4.56 milliseconds
            median = 28.26 milliseconds
              75% <= 32.28 milliseconds
              95% <= 32.28 milliseconds
              98% <= 32.28 milliseconds
              99% <= 32.28 milliseconds
            99.9% <= 32.28 milliseconds


Done
Done
Done
Done
Done
Done
Done
04/01/18 15:10:43 ==============================================================

-- Timers ----------------------------------------------------------------------
com.mycompany.app.TimedClass.test
             count = 8
         mean rate = 4.06 calls/second
     1-minute rate = 0.00 calls/second
     5-minute rate = 0.00 calls/second
    15-minute rate = 0.00 calls/second
               min = 200.16 milliseconds
               max = 200.37 milliseconds
              mean = 200.25 milliseconds
            stddev = 0.06 milliseconds
            median = 200.25 milliseconds
              75% <= 200.26 milliseconds
              95% <= 200.37 milliseconds
              98% <= 200.37 milliseconds
              99% <= 200.37 milliseconds
            99.9% <= 200.37 milliseconds
com.mycompany.app.TimedClass.test-random
             count = 7
         mean rate = 3.55 calls/second
     1-minute rate = 0.00 calls/second
     5-minute rate = 0.00 calls/second
    15-minute rate = 0.00 calls/second
               min = 20.41 milliseconds
               max = 97.20 milliseconds
              mean = 43.68 milliseconds
            stddev = 28.17 milliseconds
            median = 28.26 milliseconds
              75% <= 76.30 milliseconds
              95% <= 97.20 milliseconds
              98% <= 97.20 milliseconds
              99% <= 97.20 milliseconds
            99.9% <= 97.20 milliseconds


Done
Done
Done
Done
Done
Done
04/01/18 15:10:44 ==============================================================

-- Timers ----------------------------------------------------------------------
com.mycompany.app.TimedClass.test
             count = 11
         mean rate = 3.70 calls/second
     1-minute rate = 0.00 calls/second
     5-minute rate = 0.00 calls/second
    15-minute rate = 0.00 calls/second
               min = 200.13 milliseconds
               max = 200.37 milliseconds
              mean = 200.23 milliseconds
            stddev = 0.07 milliseconds
            median = 200.21 milliseconds
              75% <= 200.26 milliseconds
              95% <= 200.37 milliseconds
              98% <= 200.37 milliseconds
              99% <= 200.37 milliseconds
            99.9% <= 200.37 milliseconds
com.mycompany.app.TimedClass.test-random
             count = 10
         mean rate = 3.37 calls/second
     1-minute rate = 0.00 calls/second
     5-minute rate = 0.00 calls/second
    15-minute rate = 0.00 calls/second
               min = 15.19 milliseconds
               max = 97.20 milliseconds
              mean = 48.90 milliseconds
            stddev = 30.99 milliseconds
            median = 32.28 milliseconds
              75% <= 76.30 milliseconds
              95% <= 97.20 milliseconds
              98% <= 97.20 milliseconds
              99% <= 97.20 milliseconds
            99.9% <= 97.20 milliseconds

Few points:

This does not work within Eclipse. You will have to install an extension to get that to work (I have not tried that), see here:

https://github.com/astefanutti/metrics-aspectj/blob/master/README.md

And for instructions on how to use AJDT:

https://www.ibm.com/developerworks/library/j-ajdt/

The reason is (vague because I have not spend too much time on this) that the aspects are applied at compile time, not at runtime. Eclipse uses its own compiler when run within the IDE, so it just executes your code. The maven plugin inside your pom file however is what applies the aspects when compiling your code.

I hope that helps,

P.S. forgive my naming/packaging - i used the default maven generator

-- Artur

Follow up:

To add your dropwizard metrics you can just add it to the shared one if you want to use the above solution. For example:

        MetricRegistry myCustomRegistry = new MetricRegistry();
        SharedMetricRegistries.add("my-metric-registry", myCustomRegistry);

In your case, this would come from environment().metrics() or similar.

pandaadb
  • 6,306
  • 2
  • 22
  • 41
  • This works for me as well. It seems like the issue is that I can't use the default dropwizard metric registry with this. Please see my edit for how I originally had the Console reporter setup – user2158382 Jan 04 '18 at 20:58
  • Do you know how to make this work with the "default" metric registry provided by dropwizard (`environment.metrics()`)? Ideally, this is the one where I would like my annotated metrics published to. – user2158382 Jan 04 '18 at 21:07
  • 1
    _user2158382_, have you even read Nándor's advice? You did not provide any feedback there. _pandaadb_, I can see nothing in this answer that would be substantially new or different from what he suggested. _user2158382_ again, how do you get the idea that there is such a thing as a "default" registry you have not created or configured yourself? The environment is a parameter in your `run` method. What does the method override and how is the environment provided? What kind of CDI container do you use for the `@Inject` annotation you initially wanted to use? Please provide a full GitHub project. – kriegaex Jan 05 '18 at 01:17
  • @user2158382 you can call `SharedMetricRegistries.add` to add DW's registry. Alternatively you can reverse it, and overwrite DW's metrics creation to just delegate it to the `SharedMetricRegistries`. – pandaadb Jan 05 '18 at 11:01
  • @kriegaex I know there is a "default" registry, because I pull that default registry using `SharedMetricRegistries.getOrCreate("default")` & use that value when injecting. I know this is the same one as the `environment.metrics()` because I register `environment.metrics()` in my console logger and the metrics from a manual meter to the metric registry injected (`SharedMetricRegistries.getOrCreate("default")`) show up there. – user2158382 Jan 08 '18 at 19:26
3

The problem you're facing is that the MetricRegistry instance used by the AspectJ advice is different from the instance you are using for your manual metering test and your ConsoleReporter.

Since your question doesn't specify where the @Inject-ed MetricRegistry instance comes from, I can only speculate that it's the same instance you are using with the ConsoleReporter, but that is most probably a different instance from the "default" registry used by the AspectJ advice. The one used by the AspectJ advice is obtained with

SharedMetricRegistries.getOrCreate("default");

In order to solve your issue, you should either:

  • make sure that the @Inject-ed MetricRegistry instance and the one returned by environment.metrics() is the same as SharedMetricRegistries.getOrCreate("default"), by using your preferred dependency injection framework's way of using factory methods (@Bean for Spring, @Produces for CDI).

  • use an EL expression in the Foo class @Metrics annotation's registry value like this:

    @Metrics(registry = "${this.metricRegistry}")
    

    provide a getter for the referenced metricRegistry property above:

    public MetricRegistry getMetricRegistry() {
        return this.metricRegistry;
    }
    

    and make sure you have the required EL library in you project:

    <dependency>
        <groupId>org.glassfish</groupId>
        <artifactId>javax.el</artifactId>
        <version>3.0.1-b09</version>
    </dependency>
    
Nándor Előd Fekete
  • 6,988
  • 1
  • 22
  • 47
  • Yes this is definitely the issue I'm facing, but I don't know exactly why. The metric registry in the console logged IS the `SharedMetricRegistries.getOrCreate("default")`. I can prove this in 2 ways. First, I can set the ConsoleLogger metric to be `SharedMetricRegistries.getOrCreate("default")`, when doing this, still only the `manual` metric shows up. Second, I can set the `manual` metric registry to be `SharedMetricRegistries.getOrCreate("default")`, leave the `ConsoleLogger` to be `environment.metrics()`, & again only the `manual` metric shows up. The only way this works is if...continued – user2158382 Jan 06 '18 at 21:38
  • if I set the `ConsoleLogger` to be something other than `default` (`metricRegistry` for example), then set the `@Metrics(registry = "metricRegistry")`. Do you know why this won't work for default? With the default one, Dropwizard does a lot of the metric setting for me (e.g: auto metrics about the jvm, etc), and I just want to add to this – user2158382 Jan 06 '18 at 21:40
  • 1
    Your quoted `pom.xml` doesn't show the versions of the libraries you are using. I tried with `1.2.0` and `5.1.0`. Maybe there's a version difference that affects the behavior? Did you try the EL version I suggested? That would work around the issue as it would get the `MetricRegistry` directly from the advised class. Or you can still figure it out with a debugger, just place breakpoints on known locations, like `Meter.mark()`, and inspect parent stack frames and local variables when it stops. – Nándor Előd Fekete Jan 06 '18 at 22:14
  • I am using those same exact versions. Also, I tried EL as well, and no luck – user2158382 Jan 08 '18 at 19:22
  • If it doesn't work with EL either, it could mean something is wrong with your configuration. Try debugging it by placing a breakpoint inside `io.astefanutti.metrics.aspectj.JavaxElMetricStrategy.resolveMetricRegistry(String)`. That should stop your code right at the point where the EL based resolving of the `MetricRegistry` is happening. Or placing a breakpoint on your own `Foo.getMetricRegistry()` method, where you return the instance. If it doesn't stop in either, your configuration is wrong, and it's unlikely any of us could solve it. Debugging through StackOverflow is not efficient. – Nándor Előd Fekete Jan 08 '18 at 20:01
  • I actually found a workaround for this issue. In my `Application.initialize(Bootstrap bootstrap)`, I set this `MetricRegistry metrics = SharedMetricRegistries.getOrCreate("someMetrics"); bootstrap.setMetricRegistry(metrics);`. This has everything working correctly. This issue only seems to happen when I use the `default` metricRegistry. Odd – user2158382 Jan 08 '18 at 20:43
  • What version of aspectjrt are you using? – user2158382 Jan 09 '18 at 23:56
  • I was using 1.8.10. – Nándor Előd Fekete Jan 09 '18 at 23:58