Micrometer: How to use micrometer out of springboot

Created on 4 Apr 2018  路  12Comments  路  Source: micrometer-metrics/micrometer

I want to use this library in a Spring framework based project (no spring-bot) that is using Dropwizard at the moment.

What could be the best approach for this?
Is there any docs on how to use this out of spring-boot?

question

All 12 comments

If you don't have dependency injection, then you can use the static Metrics.counter... and similar helpers to record metrics.

Then you'll need to wire in the appropriate backing registry to the global one via Metrics.addRegistry(registry);

Lastly you would need to configure your reporting registry and could mimic the code found here (based on the backend you want to leverage): https://github.com/micrometer-metrics/micrometer/tree/master/micrometer-spring-legacy/src/main/java/io/micrometer/spring/autoconfigure/export

@checketts I have Spring Framework dependency injection ... just I don't have spring-boot

@blacar The "Configuring" section of each registry guide doesn't assume a Spring environment. For example, this. With Spring Framework injection in play, I'd of course recommend configuring your registry of choice as a Spring bean so it can be injected elsewhere in your components, but that is a choice.

@checketts
@jkschneider
Thanks for your help

I have done this

    @Bean
    public Clock micrometerClock() {
        return Clock.SYSTEM;
    }

    @Bean
    public PrometheusConfig prometheusConfig() {
        return new PrometheusPropertiesConfigAdapter(new DefaultPrometheusProperties());
    }

    @Bean
    public PrometheusMeterRegistry prometheusMeterRegistry(PrometheusConfig config, CollectorRegistry collectorRegistry,
                                                           Clock clock) {
        return new PrometheusMeterRegistry(config, collectorRegistry, clock);
    }

    @Bean
    public CollectorRegistry collectorRegistry() {
        return new CollectorRegistry(true);
    }

and also this:

@Controller
@RequestMapping(value = "api/prometheus")
public final class MetricController {

    private static final Logger LOGGER = LoggerFactory.getLogger(StudentController.class);

    @Autowired
    private PrometheusMeterRegistry registry;

    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    public String getStudents() {
        LOGGER.info("/prometheus [GET]");
        return registry.scrape();
    }
}

No complains ... seems working ... but the CollectorRegistry is empty
I tried to use:

@Timed(value = "get.counter.requests", histogram = true, percentiles = { 0.95, 0.99 }, extraTags = { "version", "v1" })

but seems this is not registering the Timer in the registry.

Shall I inject registry in my controller and add the Timer in a more imperative way?

Thanks!!

Yes. Verify it imperatively. To make the @Timer work you'll need to add a request interceptor I believe. Not certain on the syntax for that.

Also I recommend injecting the registry as a MeterRegistry just to minimize exposing any Prometheus specifics.

Or you could use io.micrometer.core.aop.TimedAspect if you can do AOP stuff. Probably better would be to just use Timer#record(Callable) and avoid the annotation stuff?

@checketts ohh ... but "scrape" method is PrometheusMeterRegistry specific. I can inject registry as MeterRegistry but it will require casting to PrometheusMeterRegistry before calling scrap.

I will definitely want @Timer work ... but I can do that as my next step. Thanks.

@blacar Suggest injecting PrometheusMeterRegistry in your controller (like you've done) that exposes the scrape endpoint, but everywhere else just inject MeterRegistry for future portability if you ever choose to use more than one system or just move away from Prometheus.

Cool ... this is working now:

@Controller
@RequestMapping(value = "api/students")
public class StudentController {

    private static final Logger LOGGER = LoggerFactory.getLogger(StudentController.class);

    private final DistributionSummary counter;

    @Autowired
    public StudentController(final MeterRegistry registry) {
        this.counter = DistributionSummary.builder("get.counter.requests")
            .tags("version", "v1")
            .publishPercentileHistogram()
            .register(registry);
    }

    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    public List<String> getStudents() {
        LOGGER.info("/students [GET]");
        counter.record(10.0); // <-- We shall record latency here
        return Collections.emptyList();
    }
 }

Thanks!

@jkschneider May you give me some hints about how to make the @Timer work?

@blacar Follow this guide on Spring's support for load-time weaving of AspectJ's aspects without requiring the regular AspectJ agent. The aspect that you are weaving is called TimedAspect and is in micrometer-core.

@jkschneider May you give me some hints about how to make the @Timer work?

@blacar any news making the @Timer work out of Spring Boot?

With Spring Boot 2 the annotation is named "@Timed" (not @Timer).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

filpano picture filpano  路  4Comments

jonatan-ivanov picture jonatan-ivanov  路  3Comments

wilkinsona picture wilkinsona  路  3Comments

pjfanning picture pjfanning  路  3Comments

wilkinsona picture wilkinsona  路  3Comments