micrometer和Spring Boot 2.x是无缝集成的。
但是在有的情况下,我们需要在很老的框架下,也使用它,比如Spring 3.X。我略作了调整,改成了JDK 1.8。
为了简单期间,我从mykong上找了3.X的脚手架工程,可以参考这里。
1 添加pom依赖
<!-- for micrometer -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-jmx</artifactId>
<version>1.8.7</version>
</dependency>
<!-- for micrometer -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-jmx</artifactId>
<version>1.8.7</version>
</dependency>
<!-- for micrometer --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> </dependency> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-jmx</artifactId> <version>1.8.7</version> </dependency>
注意这里用的是servlet3.0,如果是2.5的话,后面没法拿response.status。
2 添加拦截器
这里的关键是需要手工造一个Registry,我这里直接用的JmxMeterRegistry,Prometheus也一样的原理。
package com.mkyong.web.interceptor;
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.DistributionSummary;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.jmx.JmxConfig;
import io.micrometer.jmx.JmxMeterRegistry;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Optional;
public class MeterInterceptor implements HandlerInterceptor {
private MeterRegistry meterRegistry = new JmxMeterRegistry(new JmxConfig() {
@Override
public String get(String s) {
return null;
}
}, Clock.SYSTEM);
private ThreadLocal<Long> tlTimer = new ThreadLocal<Long>();
private static Optional<String> getMethod(HttpServletRequest request, Object handler) {
if (handler instanceof HandlerMethod) {
return Optional.of(String.format("%s_%s_%s", ((HandlerMethod) handler).getBeanType().getSimpleName(),
((HandlerMethod) handler).getMethod().getName(), request.getMethod()));
} else {
return Optional.empty();
}
}
private void recordTimeDistribution(HttpServletRequest request, Object handler, long ms) {
Optional<String> methodOp = getMethod(request, handler);
if (methodOp.isPresent()) {
DistributionSummary.builder("app_requests_time_ms")
.tag("method", methodOp.get())
.publishPercentiles(0.5, 0.95)
.publishPercentileHistogram()
.register(meterRegistry)
.record(ms);
}
}
public Optional<Counter> getCounterOfTotalCounts(HttpServletRequest request, Object handler) {
Optional<String> methodOp = getMethod(request, handler);
if (methodOp.isPresent()) {
return Optional.of(meterRegistry.counter("app_requests_total_counts", "method",
methodOp.get()));
} else {
return Optional.empty();
}
}
public Optional<Counter> getCounterOfExceptionCounts(HttpServletRequest request, Object handler) {
Optional<String> methodOp = getMethod(request, handler);
if (methodOp.isPresent()) {
return Optional.of(meterRegistry.counter("app_requests_exption_counts", "method",
methodOp.get()));
} else {
return Optional.empty();
}
}
public Optional<Counter> getCounterOfRespCodeCounts(HttpServletRequest request, HttpServletResponse response,
Object handler) {
Optional<String> methodOp = getMethod(request, handler);
if (methodOp.isPresent()) {
return Optional.of(meterRegistry.counter(String.format("app_requests_resp%d_counts", response.getStatus()),
"method", methodOp.get()));
} else {
return Optional.empty();
}
}
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
tlTimer.set(System.currentTimeMillis());
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// record time
recordTimeDistribution(request, handler, System.currentTimeMillis() - tlTimer.get());
tlTimer.remove();
// total counts
getCounterOfTotalCounts(request, handler).ifPresent(counter -> counter.increment());
// different response code count
getCounterOfRespCodeCounts(request, response, handler).ifPresent(counter -> counter.increment());
if (ex != null) {
// exception counts
getCounterOfExceptionCounts(request, handler).ifPresent(counter -> counter.increment());
}
}
}
package com.mkyong.web.interceptor;
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.DistributionSummary;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.jmx.JmxConfig;
import io.micrometer.jmx.JmxMeterRegistry;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Optional;
public class MeterInterceptor implements HandlerInterceptor {
private MeterRegistry meterRegistry = new JmxMeterRegistry(new JmxConfig() {
@Override
public String get(String s) {
return null;
}
}, Clock.SYSTEM);
private ThreadLocal<Long> tlTimer = new ThreadLocal<Long>();
private static Optional<String> getMethod(HttpServletRequest request, Object handler) {
if (handler instanceof HandlerMethod) {
return Optional.of(String.format("%s_%s_%s", ((HandlerMethod) handler).getBeanType().getSimpleName(),
((HandlerMethod) handler).getMethod().getName(), request.getMethod()));
} else {
return Optional.empty();
}
}
private void recordTimeDistribution(HttpServletRequest request, Object handler, long ms) {
Optional<String> methodOp = getMethod(request, handler);
if (methodOp.isPresent()) {
DistributionSummary.builder("app_requests_time_ms")
.tag("method", methodOp.get())
.publishPercentiles(0.5, 0.95)
.publishPercentileHistogram()
.register(meterRegistry)
.record(ms);
}
}
public Optional<Counter> getCounterOfTotalCounts(HttpServletRequest request, Object handler) {
Optional<String> methodOp = getMethod(request, handler);
if (methodOp.isPresent()) {
return Optional.of(meterRegistry.counter("app_requests_total_counts", "method",
methodOp.get()));
} else {
return Optional.empty();
}
}
public Optional<Counter> getCounterOfExceptionCounts(HttpServletRequest request, Object handler) {
Optional<String> methodOp = getMethod(request, handler);
if (methodOp.isPresent()) {
return Optional.of(meterRegistry.counter("app_requests_exption_counts", "method",
methodOp.get()));
} else {
return Optional.empty();
}
}
public Optional<Counter> getCounterOfRespCodeCounts(HttpServletRequest request, HttpServletResponse response,
Object handler) {
Optional<String> methodOp = getMethod(request, handler);
if (methodOp.isPresent()) {
return Optional.of(meterRegistry.counter(String.format("app_requests_resp%d_counts", response.getStatus()),
"method", methodOp.get()));
} else {
return Optional.empty();
}
}
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
tlTimer.set(System.currentTimeMillis());
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// record time
recordTimeDistribution(request, handler, System.currentTimeMillis() - tlTimer.get());
tlTimer.remove();
// total counts
getCounterOfTotalCounts(request, handler).ifPresent(counter -> counter.increment());
// different response code count
getCounterOfRespCodeCounts(request, response, handler).ifPresent(counter -> counter.increment());
if (ex != null) {
// exception counts
getCounterOfExceptionCounts(request, handler).ifPresent(counter -> counter.increment());
}
}
}
package com.mkyong.web.interceptor; import io.micrometer.core.instrument.Clock; import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.DistributionSummary; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.jmx.JmxConfig; import io.micrometer.jmx.JmxMeterRegistry; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Optional; public class MeterInterceptor implements HandlerInterceptor { private MeterRegistry meterRegistry = new JmxMeterRegistry(new JmxConfig() { @Override public String get(String s) { return null; } }, Clock.SYSTEM); private ThreadLocal<Long> tlTimer = new ThreadLocal<Long>(); private static Optional<String> getMethod(HttpServletRequest request, Object handler) { if (handler instanceof HandlerMethod) { return Optional.of(String.format("%s_%s_%s", ((HandlerMethod) handler).getBeanType().getSimpleName(), ((HandlerMethod) handler).getMethod().getName(), request.getMethod())); } else { return Optional.empty(); } } private void recordTimeDistribution(HttpServletRequest request, Object handler, long ms) { Optional<String> methodOp = getMethod(request, handler); if (methodOp.isPresent()) { DistributionSummary.builder("app_requests_time_ms") .tag("method", methodOp.get()) .publishPercentiles(0.5, 0.95) .publishPercentileHistogram() .register(meterRegistry) .record(ms); } } public Optional<Counter> getCounterOfTotalCounts(HttpServletRequest request, Object handler) { Optional<String> methodOp = getMethod(request, handler); if (methodOp.isPresent()) { return Optional.of(meterRegistry.counter("app_requests_total_counts", "method", methodOp.get())); } else { return Optional.empty(); } } public Optional<Counter> getCounterOfExceptionCounts(HttpServletRequest request, Object handler) { Optional<String> methodOp = getMethod(request, handler); if (methodOp.isPresent()) { return Optional.of(meterRegistry.counter("app_requests_exption_counts", "method", methodOp.get())); } else { return Optional.empty(); } } public Optional<Counter> getCounterOfRespCodeCounts(HttpServletRequest request, HttpServletResponse response, Object handler) { Optional<String> methodOp = getMethod(request, handler); if (methodOp.isPresent()) { return Optional.of(meterRegistry.counter(String.format("app_requests_resp%d_counts", response.getStatus()), "method", methodOp.get())); } else { return Optional.empty(); } } @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { tlTimer.set(System.currentTimeMillis()); return true; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // record time recordTimeDistribution(request, handler, System.currentTimeMillis() - tlTimer.get()); tlTimer.remove(); // total counts getCounterOfTotalCounts(request, handler).ifPresent(counter -> counter.increment()); // different response code count getCounterOfRespCodeCounts(request, response, handler).ifPresent(counter -> counter.increment()); if (ex != null) { // exception counts getCounterOfExceptionCounts(request, handler).ifPresent(counter -> counter.increment()); } } }
3 在xml中声明
<mvc:interceptors>
<bean class="com.mkyong.web.interceptor.MeterInterceptor" />
</mvc:interceptors>
<mvc:interceptors>
<bean class="com.mkyong.web.interceptor.MeterInterceptor" />
</mvc:interceptors>
<mvc:interceptors> <bean class="com.mkyong.web.interceptor.MeterInterceptor" /> </mvc:interceptors>
4 启动,测试
mvn jetty:run
mvn jetty:run
mvn jetty:run
访问http://127.0.0.1/spring3,成功后,多访问几次
然后打开jconsole,就能看到统计的jmx了。