微服务、Java Metrics、Docker、业务系统接口监控概览

1.记录类AccessMetricsFilter.java
@Log4j2
@Component
@ConditionalOnClass(MetricRegistry.class)
public class AccessMetricsFilter extends OncePerRequestFilter {
private final String METRIC_SUFFIX_TIME = ".url_exec";
@Value("${spring.application.name}")
private String applicationName;
private String[] excludeUrls = {};
@Override
public void afterPropertiesSet() throws ServletException {
excludeUrls = new String[]{applicationName + "/tools/", applicationName + "/admin/tools"};
}
@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
//排除url
String sourceUrl = request.getRequestURI();
for (String excludeUrl : excludeUrls) {
if (sourceUrl.indexOf(excludeUrl) != -1) {
return true;
}
}
return false;
}
@Autowired
private MetricRegistry metricRegistry;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String uri = request.getRequestURI().replaceAll("[/\\.]", "_");
long startTime = System.nanoTime();
long duration = 0L;
try {
filterChain.doFilter(request, response);
duration = System.nanoTime() - startTime;
} finally {
//优先取本次记录的错误码
Integer statusCode = (Integer) request.getAttribute(Constants.SERVER_ERROR_CODE);
if (statusCode == null) {
statusCode = response.getStatus();
}
//记录分析数据
Timer timer = metricRegistry.timer(uri + "." + statusCode + METRIC_SUFFIX_TIME);
timer.update(duration, TimeUnit.NANOSECONDS);
if (log.isInfoEnabled()) {
log.info("req: url={}, time={}ms, status={}", uri, TimeUnit.MILLISECONDS.convert(duration, TimeUnit.NANOSECONDS), statusCode);
}
}
}
}
2.指标上报配置类MetricsConfiguration.java
@Configuration
@ConditionalOnClass(MetricRegistry.class)
@EnableMetrics
@AutoConfigureAfter(MetricsConfig.class)
@Log4j2
public class MetricsConfiguration extends MetricsConfigurerAdapter {
@Value("${spring.application.name}")
private String applicationName;
@Autowired
private MetricsConfig metricsConfig;
@Override
public void configureReporters(MetricRegistry metricRegistry) {
// 采集jvm指标
metricRegistry.register("-.-.jvm.gc", new com.codahale.metrics.jvm.GarbageCollectorMetricSet());
metricRegistry.register("-.-.jvm.memory", new com.codahale.metrics.jvm.MemoryUsageGaugeSet());
metricRegistry.register("-.-.jvm.thread-states", new com.codahale.metrics.jvm.ThreadStatesGaugeSet());
metricRegistry.register("-.-.jvm.fd.usage", new com.codahale.metrics.jvm.FileDescriptorRatioGauge());
// 配置Influxdb
HttpInfluxdbProtocol influxdbProtocol = new HttpInfluxdbProtocol("http", metricsConfig.getHost(), metricsConfig.getPort(), metricsConfig.getUsername(), metricsConfig.getPassword(), metricsConfig.getDb());
InfluxdbReporter.Builder builder = InfluxdbReporter.forRegistry(metricRegistry).protocol(influxdbProtocol);
builder.convertRatesTo(TimeUnit.SECONDS).convertDurationsTo(TimeUnit.MILLISECONDS);
builder.filter(MetricFilter.ALL).skipIdleMetrics(true);
builder.tag("server", applicationName).tag("ip", HttpUtil.getDockerHostIp()).tag("cid", HttpUtil.getLocalHostName());
builder.transformer(new CategoriesMetricMeasurementTransformer("url", "code"));
// 启动上报
ScheduledReporter reporter = builder.build();
reporter.start(metricsConfig.getPeriod(), TimeUnit.SECONDS);
log.debug("grafana上报初始化完成:host={}, port={}, db={}", metricsConfig.getHost(), metricsConfig.getPort(), metricsConfig.getDb());
}
}