How to implement statistics using dropwizard and spring -mvc metrics

I have about 20 APIs, and I want to implement statistics such as runtime, number of responses for each API. After some research, I found out that dropwizard metrics are the best approach to implement such functions. I am using Spring MVC framework (non-downloadable). Can someone suggest me how to integrate Metrics into Spring MVC framework?

If possible, provide any code as a reference.

+5
source share
3 answers

You can use Metrics for Spring . Here's a github link that explains how to integrate it with Spring MVC. The metrics-spring module integrates the Dropwizard metrics library with Spring and provides XML and Java configuration.

Maven

Current version 3.1.2 compatible with Metrics 3.1.2

<dependency> <groupId>com.ryantenney.metrics</groupId> <artifactId>metrics-spring</artifactId> <version>3.1.2</version> </dependency> 

Main use

Starting with version 3, metrics-spring can be configured using XML or Java, depending on your personal preferences.

XML configuration:

 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:metrics="http://www.ryantenney.com/schema/metrics" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.ryantenney.com/schema/metrics http://www.ryantenney.com/schema/metrics/metrics.xsd"> <!-- Creates a MetricRegistry bean --> <metrics:metric-registry id="metricRegistry" /> <!-- Creates a HealthCheckRegistry bean (Optional) --> <metrics:health-check-registry id="health" /> <!-- Registers BeanPostProcessors with Spring which proxy beans and capture metrics --> <!-- Include this once per context (once in the parent context and in any subcontexts) --> <metrics:annotation-driven metric-registry="metricRegistry" /> <!-- Example reporter definiton. Supported reporters include jmx, slf4j, graphite, and others. --> <!-- Reporters should be defined only once, preferably in the parent context --> <metrics:reporter type="console" metric-registry="metricRegistry" period="1m" /> <!-- Register metric beans (Optional) --> <!-- The metrics in this example require metrics-jvm --> <metrics:register metric-registry="metricRegistry"> <bean metrics:name="jvm.gc" class="com.codahale.metrics.jvm.GarbageCollectorMetricSet" /> <bean metrics:name="jvm.memory" class="com.codahale.metrics.jvm.MemoryUsageGaugeSet" /> <bean metrics:name="jvm.thread-states" class="com.codahale.metrics.jvm.ThreadStatesGaugeSet" /> <bean metrics:name="jvm.fd.usage" class="com.codahale.metrics.jvm.FileDescriptorRatioGauge" /> </metrics:register> <!-- Beans and other Spring config --> </beans> 

Java configuration:

 import java.util.concurrent.TimeUnit; import org.springframework.context.annotation.Configuration; import com.codahale.metrics.ConsoleReporter; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.SharedMetricRegistries; import com.ryantenney.metrics.spring.config.annotation.EnableMetrics; import com.ryantenney.metrics.spring.config.annotation.MetricsConfigurerAdapter; @Configuration @EnableMetrics public class SpringConfiguringClass extends MetricsConfigurerAdapter { @Override public void configureReporters(MetricRegistry metricRegistry) { // registerReporter allows the MetricsConfigurerAdapter to // shut down the reporter when the Spring context is closed registerReporter(ConsoleReporter .forRegistry(metricRegistry) .build()) .start(1, TimeUnit.MINUTES); } } 

Read more about Spring Metrics

+4
source

As already mentioned, Metrics Spring offers an interesting integration with Spring. If you want to access these metrics from the JSON API, you still need to add a servlet, as described in http://metrics.dropwizard.io/3.1.0/manual/servlets/ .

To use these servlets, you need to add a dependency:

 <dependency> <groupId>io.dropwizard.metrics</groupId> <artifactId>metrics-servlets</artifactId> <version>${metrics.version}</version> </dependency> 

Then you add the servlet to web.xml:

 <servlet> <servlet-name>metrics-admin</servlet-name> <servlet-class>com.codahale.metrics.servlets.AdminServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>metrics-admin</servlet-name> <url-pattern>/metrics/admin/*</url-pattern> </servlet-mapping> 

You can also use JavaConfig to configure it.

Register the servlet:

 import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; import com.codahale.metrics.servlets.AdminServlet; public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class<?>[]{RootConfig.class}; } @Override protected Class<?>[] getServletConfigClasses() { return null; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } @Override public void onStartup(ServletContext servletContext) throws ServletException { super.onStartup(servletContext); ServletRegistration.Dynamic metricsServlet = servletContext.addServlet("metrics", new AdminServlet()); metricsServlet.addMapping("/metrics/admin/*"); } } 

And specify the attributes required by the servlet:

 import java.util.concurrent.TimeUnit; import javax.servlet.ServletContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import com.codahale.metrics.ConsoleReporter; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.health.HealthCheckRegistry; import com.codahale.metrics.servlets.HealthCheckServlet; import com.codahale.metrics.servlets.MetricsServlet; import com.ryantenney.metrics.spring.config.annotation.EnableMetrics; import com.ryantenney.metrics.spring.config.annotation.MetricsConfigurerAdapter; @Configuration @EnableMetrics public class MetricsConfiguration extends MetricsConfigurerAdapter { @Autowired ServletContext servletContext; @Autowired private HealthCheckRegistry healthCheckRegistry; @Override public void configureReporters(MetricRegistry metricRegistry) { registerReporter(ConsoleReporter .forRegistry(metricRegistry) .build()) .start(1, TimeUnit.MINUTES); servletContext.setAttribute(MetricsServlet.METRICS_REGISTRY, metricRegistry); servletContext.setAttribute(HealthCheckServlet.HEALTH_CHECK_REGISTRY, healthCheckRegistry); } } 
+1
source

I have a few additions to the above answer.

You need to register the MetricsConfiguration as RootConfigClasses inside the WebInitializer, otherwise it will not load.

I found with my version of Spring (4.2.5) a mismatch of the AOP version with the metric - spring, which throws a ClassNotFoundException. Just exclude spring-aop as a dependency on spring metrics inside your pom.

Finally, you can easily implement your own Metrics Controller as follows:

 @Controller public class MetricsContoller { @Autowired private ServletContext servletContext; @RequestMapping(value="/metrics", method=RequestMethod.GET) public @ResponseBody MetricRegistry saveTestStep() throws ServletException { final Object registryAttr = servletContext.getAttribute(MetricsServlet.METRICS_REGISTRY); if (registryAttr instanceof MetricRegistry) { return (MetricRegistry) registryAttr; } else { throw new ServletException("Couldn't find a MetricRegistry instance."); } } } 
0
source

Source: https://habr.com/ru/post/1238918/


All Articles