metrics 日志
默认netty没有开启自身metrics统计, 开启方式如下(并打开url聚合)
@Component public class NettyWebServerFactoryPortCustomizer implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory> { private Set<RequestMappingInfo> setMappings = null; public Set<RequestMappingInfo> getSetMappings() { if (setMappings == null) { RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) applicationContext.getBean( "requestMappingHandlerMapping"); setMappings = requestMappingHandlerMapping.getHandlerMethods().keySet().stream().filter( v -> v.getPatternsCondition() .getPatterns() .stream() .filter(t -> t.getPatternString().contains("{")) .filter(u -> u.getPatternString().contains("}")) .findAny() .isPresent() ).collect(Collectors.toSet()); } return setMappings; } @Override public void customize(NettyReactiveWebServerFactory serverFactory) { serverFactory.addServerCustomizers(httpServer -> httpServer.metrics(false, new Function<String, String>() { @Override public String apply(final String s) { Iterator<RequestMappingInfo> iterator = getSetMappings().iterator(); TreeSet<PathPattern> result = new TreeSet<>(); PathContainer p = RequestPath.parse(s, "/"); String strUrlReal = s; while (iterator.hasNext()) { RequestMappingInfo mappingInfo = iterator.next(); Set<PathPattern> patternSet = mappingInfo.getPatternsCondition() .getPatterns(); for (PathPattern pattern : patternSet) { if (pattern.matches(p)) { result = (result != null ? result : new TreeSet<>()); result.add(pattern); } } } if (result.size() > 0) { strUrlReal = result.first().getPatternString(); } log.info("===> " + s); return strUrlReal; } }) ); } }
默认 actuator已开启了对metric统计,并且支持 按照url聚合(最佳url匹配存储在request.attribute中,不用手动再查找), 如果不想对添加url到tag中,可以做如下配置:
//remove actuator metrics for each url @Bean public SgFluxRequestProvider webFluxRequestProvider() { return new SgFluxRequestProvider(); } static class SgFluxRequestProvider implements WebFluxTagsProvider { @Override public Iterable<Tag> httpRequestTags(ServerWebExchange exchange, Throwable ex) { return new ArrayList<>(); } }
相当于替换掉 默认 DefaultWebFluxTagsProvider,默认如下
@AutoConfigureAfter({ MetricsAutoConfiguration.class, CompositeMeterRegistryAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class }) @ConditionalOnBean(MeterRegistry.class) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) public class WebFluxMetricsAutoConfiguration { private final MetricsProperties properties; public WebFluxMetricsAutoConfiguration(MetricsProperties properties) { this.properties = properties; } @Bean @ConditionalOnMissingBean(WebFluxTagsProvider.class) public DefaultWebFluxTagsProvider webFluxTagsProvider(ObjectProvider<WebFluxTagsContributor> contributors) { return new DefaultWebFluxTagsProvider(this.properties.getWeb().getServer().getRequest().isIgnoreTrailingSlash(), contributors.orderedStream().collect(Collectors.toList())); } @Bean public MetricsWebFilter webfluxMetrics(MeterRegistry registry, WebFluxTagsProvider tagConfigurer) { ServerRequest request = this.properties.getWeb().getServer().getRequest(); return new MetricsWebFilter(registry, tagConfigurer, request.getMetricName(), request.getAutotime()); } @Bean @Order(0) public MeterFilter metricsHttpServerUriTagFilter() { String metricName = this.properties.getWeb().getServer().getRequest().getMetricName(); MeterFilter filter = new OnlyOnceLoggingDenyMeterFilter( () -> String.format("Reached the maximum number of URI tags for '%s'.", metricName)); return MeterFilter.maximumAllowableTags(metricName, "uri", this.properties.getWeb().getServer().getMaxUriTags(), filter); } }
private static final String DIRECT_BUFFER_MBEAN = "java.nio:type=BufferPool,name=direct"; private static final String MAPPED_BUFFER_MBEAN = "java.nio:type=BufferPool,name=mapped"; Gauge.builder(DIRECT_BUFFER, beanServer, s -> { long directBufferSize = 0; try { ObjectName directPool = new ObjectName(DIRECT_BUFFER_MBEAN); directBufferSize = (Long) beanServer.getAttribute(directPool, "MemoryUsed"); } catch (Exception e) { e.printStackTrace(); } return directBufferSize; } ).register(registry); Gauge.builder(MAPPED_BUFFER, beanServer, s -> { long mappedBufferSize = 0; try { ObjectName bufferPool = new ObjectName(MAPPED_BUFFER_MBEAN); mappedBufferSize = (Long) beanServer.getAttribute(bufferPool, "MemoryUsed"); } catch (Exception e) { e.printStackTrace(); } return mappedBufferSize; } ).register(registry);