如何使用 dropwizard 指标和 spring-mvc 实现统计
How to implement statistics using dropwizard metrics and spring-mvc
我有大约 20 API 秒,我想为每个 API 实现执行时间、响应计数等统计信息。在做了一些研究之后,我开始知道 dropwizard 指标是实现此类功能的最佳方法。我正在使用 Spring MVC 框架(不可启动)。有人可以建议我如何将 Metrics 集成到 Spring MVC 框架吗?
如果可能,请提供任何代码作为参考。
您可以将 Metrics for Spring. Here's a github link, which explains how to integrate it with Spring MVC. The metrics-spring module integrates Dropwizard Metrics library 与 Spring 一起使用,并提供 XML 和 Java 配置。
Maven
Current version is 3.1.2, which is compatible with Metrics 3.1.2
<dependency>
<groupId>com.ryantenney.metrics</groupId>
<artifactId>metrics-spring</artifactId>
<version>3.1.2</version>
</dependency>
基本用法
As of version 3, metrics-spring may be configured using XML or Java,
depending on your personal preference.
XML配置:
<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 配置:
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);
}
}
阅读有关 Metrics Spring
的更多信息
正如已经建议的那样,指标 Spring 提供了与 Spring 的一些有趣的集成。如果您想从 JSON API 访问这些指标,您仍然需要添加 servlet,如 http://metrics.dropwizard.io/3.1.0/manual/servlets/.
中所述
为了使用这些 servlet,您需要添加依赖项:
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-servlets</artifactId>
<version>${metrics.version}</version>
</dependency>
然后在web.xml中添加servlet:
<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>
你也可以使用JavaConfig来配置。
注册 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/*");
}
}
并提供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);
}
}
我对上面的回答有几点补充。
您需要在WebInitializer中将MetricsConfiguration注册为RootConfigClasses,否则无法加载。
我发现我的 Spring 版本 (4.2.5) 与 metrics-spring 的 AOP 版本不匹配,这会导致 ClassNotFoundException。只需将 spring-aop 作为 metrics-spring 的依赖项排除在您的 pom 中。
最后,您可以像这样轻松实现自己的 Metrics Controller:
@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.");
}
}
}
我有大约 20 API 秒,我想为每个 API 实现执行时间、响应计数等统计信息。在做了一些研究之后,我开始知道 dropwizard 指标是实现此类功能的最佳方法。我正在使用 Spring MVC 框架(不可启动)。有人可以建议我如何将 Metrics 集成到 Spring MVC 框架吗?
如果可能,请提供任何代码作为参考。
您可以将 Metrics for Spring. Here's a github link, which explains how to integrate it with Spring MVC. The metrics-spring module integrates Dropwizard Metrics library 与 Spring 一起使用,并提供 XML 和 Java 配置。
Maven
Current version is 3.1.2, which is compatible with Metrics 3.1.2
<dependency>
<groupId>com.ryantenney.metrics</groupId>
<artifactId>metrics-spring</artifactId>
<version>3.1.2</version>
</dependency>
基本用法
As of version 3, metrics-spring may be configured using XML or Java, depending on your personal preference.
XML配置:
<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 配置:
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);
}
}
阅读有关 Metrics Spring
的更多信息正如已经建议的那样,指标 Spring 提供了与 Spring 的一些有趣的集成。如果您想从 JSON API 访问这些指标,您仍然需要添加 servlet,如 http://metrics.dropwizard.io/3.1.0/manual/servlets/.
中所述为了使用这些 servlet,您需要添加依赖项:
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-servlets</artifactId>
<version>${metrics.version}</version>
</dependency>
然后在web.xml中添加servlet:
<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>
你也可以使用JavaConfig来配置。
注册 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/*");
}
}
并提供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);
}
}
我对上面的回答有几点补充。
您需要在WebInitializer中将MetricsConfiguration注册为RootConfigClasses,否则无法加载。
我发现我的 Spring 版本 (4.2.5) 与 metrics-spring 的 AOP 版本不匹配,这会导致 ClassNotFoundException。只需将 spring-aop 作为 metrics-spring 的依赖项排除在您的 pom 中。
最后,您可以像这样轻松实现自己的 Metrics Controller:
@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.");
}
}
}