Search code examples
springspring-bootmetrics

spring boot repository metrics


I am trying to make an object repositoryMetrics in SpringBoot and later I obtained information with this repository. But I create a repository and this always is null.

How I generate a repository and this save the metrics? I have this code:

public static void stateSist() throws Exception {

    InMemoryMetricRepository metricRepository = null;
    metricRepository.findAll();
    System.out.println(metricRepository.count());

}

EDIT 1:

I do this change in my version and I obtained this error:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'actuatorMetricsPrinter' defined in file [ActuatorMetricsPrinter.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [java.util.Collection]: : No qualifying bean of type [org.springframework.boot.actuate.endpoint.PublicMetrics] found for dependency [collection of org.springframework.boot.actuate.endpoint.PublicMetrics]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.boot.actuate.endpoint.PublicMetrics] found for dependency [collection of org.springframework.boot.actuate.endpoint.PublicMetrics]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:747)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1115)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:706)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:762)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:952)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:941)
at hello.Application.main(Application.java:14)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.boot.actuate.endpoint.PublicMetrics] found for dependency [collection of org.springframework.boot.actuate.endpoint.PublicMetrics]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1118)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:919)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:862)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:811)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:739)
... 18 common frames omitted

Thank you!


Solution

  • In order to access all Public Metrics printed by the Spring Boot actuator framework you need to inject a 'Collection' into your component and then access it to read all the metrics. Here is an example:

        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.boot.actuate.endpoint.PublicMetrics;
        import org.springframework.boot.actuate.metrics.Metric;
        import org.springframework.stereotype.Component;
    
        import java.util.Collection;
    
        @Component
        public class ActuatorMetricsPrinter {
            private static final String TEMPLATE = "Metric: %s [%s]";
    
            private final Collection<PublicMetrics> publicMetrics;
    
            @Autowired
            public ActuatorMetricsPrinter(Collection<PublicMetrics> publicMetrics) {
                this.publicMetrics = publicMetrics;
            }
    
            public String printAllMetrics() {
    
                StringBuilder sb = new StringBuilder();
    
                for (PublicMetrics pm : publicMetrics) {
                    sb.append("Public Metric: " + pm.getClass().getName());
                    sb.append("\n\n");
    
                    for (Metric<?> m : pm.metrics()) {
                        sb.append(String.format(TEMPLATE, m.getName(), m.getValue().toString()));
                        sb.append("\n");
                    }
                }
    
                return sb.toString();
            }
        }
    

    If you want to reproduce this simple scenario, then:

    1. Go to http://start.spring.io/ and create new project with Actuator and Web checked,
    2. Create a demo project with Build tool of your choice (Gradle, Maven),
    3. Download it and open in your IDE,
    4. Create a new component just like one in my example,
    5. Create a new RestController, like this:
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class DummyController {
    
        private final ActuatorMetricsPrinter metricsPrinter;
    
        @Autowired
        public DummyController(ActuatorMetricsPrinter metricsPrinter) {
            this.metricsPrinter = metricsPrinter;
        }
    
        @RequestMapping(value = "/customMetrics", method = RequestMethod.GET)
        public String printMetrics() {
            return metricsPrinter.printAllMetrics();
        }
    }
    
    1. Then start the application and type in your browser: http://localhost:8080/customMetrics
    2. You should see all the metrics printed by your class in the most messy way possible