Spring Cloud Gateway中Spring Boot Actuator采集到的uri为UNKNOWN

在将spring cloud gateway接入Prometheus之后发现收集到的指标中有很多 uri=“UNKNOWN”,如下:

# HELP http_server_requests_seconds  
# TYPE http_server_requests_seconds histogram
http_server_requests_seconds{exception="None",method="GET",outcome="SUCCESS",status="200",uri="UNKNOWN",quantile="0.95",} 326.417514496
http_server_requests_seconds{exception="None",method="GET",outcome="SUCCESS",status="200",uri="UNKNOWN",quantile="0.99",} 326.417514496
http_server_requests_seconds{exception="None",method="GET",outcome="SUCCESS",status="200",uri="UNKNOWN",quantile="0.995",} 326.417514496
http_server_requests_seconds_bucket{exception="None",method="GET",outcome="SUCCESS",status="200",uri="UNKNOWN",le="0.01",} 0.0
http_server_requests_seconds_bucket{exception="None",method="GET",outcome="SUCCESS",status="200",uri="UNKNOWN",le="0.02",} 0.0
http_server_requests_seconds_bucket{exception="None",method="GET",outcome="SUCCESS",status="200",uri="UNKNOWN",le="0.05",} 0.0
http_server_requests_seconds_bucket{exception="None",method="GET",outcome="SUCCESS",status="200",uri="UNKNOWN",le="0.1",} 0.0
http_server_requests_seconds_bucket{exception="None",method="GET",outcome="SUCCESS",status="200",uri="UNKNOWN",le="0.3",} 0.0
http_server_requests_seconds_bucket{exception="None",method="GET",outcome="SUCCESS",status="200",uri="UNKNOWN",le="+Inf",} 1.0
http_server_requests_seconds_count{exception="None",method="GET",outcome="SUCCESS",status="200",uri="UNKNOWN",} 1.0
http_server_requests_seconds_sum{exception="None",method="GET",outcome="SUCCESS",status="200",uri="UNKNOWN",} 328.888017765
# HELP http_server_requests_seconds_max  
# TYPE http_server_requests_seconds_max gauge
http_server_requests_seconds_max{exception="None",method="GET",outcome="SUCCESS",status="200",uri="UNKNOWN",} 328.888017765

这些UNKNOWN的指标都是网关上下转发的请求,因此找一下为UNKNOWN的原因。
首先了解到这些指标是Spring Boot Actuator负责收集的,在源码中找到Tag转换的类:
在spring-boot-actuator-2.1.4.RELEASE.jar中org.springframework.boot.actuate.metrics.web.reactive.server.WebFluxTags这个类的public static Tag uri(ServerWebExchange exchange)方法:

/**
	 * Creates a {@code uri} tag based on the URI of the given {@code exchange}. Uses the
	 * {@link HandlerMapping#BEST_MATCHING_PATTERN_ATTRIBUTE} best matching pattern if
	 * available. Falling back to {@code REDIRECTION} for 3xx responses, {@code NOT_FOUND}
	 * for 404 responses, {@code root} for requests with no path info, and {@code UNKNOWN}
	 * for all other requests.
	 * @param exchange the exchange
	 * @return the uri tag derived from the exchange
	 */
	public static Tag uri(ServerWebExchange exchange) {
		PathPattern pathPattern = exchange
				.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
		if (pathPattern != null) {
			return Tag.of("uri", pathPattern.getPatternString());
		}
		HttpStatus status = exchange.getResponse().getStatusCode();
		if (status != null) {
			if (status.is3xxRedirection()) {
				return URI_REDIRECTION;
			}
			if (status == HttpStatus.NOT_FOUND) {
				return URI_NOT_FOUND;
			}
		}
		String path = getPathInfo(exchange);
		if (path.isEmpty()) {
			return URI_ROOT;
		}
		return URI_UNKNOWN;
	}

可以看到String path = getPathInfo(exchange);其实已经拿到了路径,但是却return URI_UNKNOWN;
于是去github上看一下是否有人存在相同的疑问,为什么不返回path?
https://github.com/spring-projects/spring-boot/issues/16208

跟着问题中的回复看到了这个PR(https://github.com/spring-projects/spring-boot/pull/15609),将uri方法修改到了现在的样子,最初实际上返回的就是path:

/**
	 * Creates a {@code uri} tag based on the URI of the given {@code exchange}. Uses the
	 * {@link HandlerMapping#BEST_MATCHING_PATTERN_ATTRIBUTE} best matching pattern.
	 * @param exchange the exchange
	 * @return the uri tag derived from the exchange
	 */
	public static Tag uri(ServerWebExchange exchange) {
		PathPattern pathPattern = exchange
				.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
		if (pathPattern != null) {
			return Tag.of("uri", pathPattern.getPatternString());
		}
		HttpStatus status = exchange.getResponse().getStatusCode();
		if (status != null) {
			if (status.is3xxRedirection()) {
				return URI_REDIRECTION;
			}
			if (status == HttpStatus.NOT_FOUND) {
				return URI_NOT_FOUND;
			}
		}
		String path = exchange.getRequest().getPath().value();
		if (path.isEmpty()) {
			return URI_ROOT;
		}
		return Tag.of("uri", path);
	}

这个PR中解释了为什么要返回URI_UNKNOWN,大概的意思就是应该关系本身的指标,同时为了防止指标太多。

你可能感兴趣的:(Java)