Spring Boot Actuator metrics端点缺失http.server.requests指标排查
问题:Spring Boot Actuator metrics端点缺失http.server.requests指标
问题背景
使用Java 11开发Spring Boot 2.6.6项目,引入Spring Boot Actuator后,已完成pom.xml和application.properties配置,自定义REST API可正常响应,但访问http://localhost:8080/metrics时,响应中无http.server.requests指标(该指标用于分析API响应时间与状态码)。
pom.xml配置
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.6</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.abc</groupId> <artifactId>xyz</artifactId> <version>0.0.1-SNAPSHOT</version> <name>Project ABC</name> <description>Project for ...</description> <properties> <java.version>11</java.version> <apache.commons.lang3.version>3.12.0</apache.commons.lang3.version> <common.io.version>2.11.0</common.io.version> <springdoc-openapi-ui.version>1.2.32</springdoc-openapi-ui.version> <git.commit.id.plugin.version>4.9.10</git.commit.id.plugin.version> <problem.version>0.26.0</problem.version> <google.bean-matcher.version>0.11</google.bean-matcher.version> <arch.junit5.version>0.13.1</arch.junit5.version> <api-authenticator.version>1.1.0</api-authenticator.version> <org.json.version>20220320</org.json.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>${apache.commons.lang3.version}</version> </dependency> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-ui</artifactId> <version>${springdoc-openapi-ui.version}</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> <dependency> <groupId>org.zalando</groupId> <artifactId>problem-spring-web</artifactId> <version>${problem.version}</version> </dependency> <dependency> <groupId>org.zalando</groupId> <artifactId>jackson-datatype-problem</artifactId> <version>${problem.version}</version> </dependency> <dependency> <groupId>com.google.code.bean-matchers</groupId> <artifactId>bean-matchers</artifactId> <version>${google.bean-matcher.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>com.tngtech.archunit</groupId> <artifactId>archunit-junit5-api</artifactId> <version>${arch.junit5.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>com.tngtech.archunit</groupId> <artifactId>archunit-junit5-engine</artifactId> <version>${arch.junit5.version}</version> <scope>test</scope> </dependency> <dependency> <artifactId>android-json</artifactId> <groupId>com.vaadin.external.google</groupId> <scope>compile</scope> <version>0.0.20131108.vaadin1</version> </dependency> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>${org.json.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>build-info</goal> </goals> </execution> </executions> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> </project>
application.properties配置
# Timeout Configurations connection.timeout=6000000 # Logging Configurations logging.level.root=INFO logging.level.com.rwg.*=DEBUG # Validation Configurations email.validation=^[\\w!#$%&'*+/=?`{|}~^-]+(?:\\.[\\w!#$%&'*+/=?`{|}~^-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6} name.validation=^[a-zA-Z0-9_\\s]+$ # API's for User search. user = create.user= deactivate.user= update.api= # Spring Boot Actuator Configurations management.endpoint.health.show-details=ALWAYS management.endpoints.web.base-path= management.endpoint.metrics.enabled = true management.endpoints.web.exposure.include = * management.endpoints.web.path-mapping.health=/healthcheck spring.main.allow-circular-references = true spring.mvc.pathmatch.matching-strategy=ant_path_matcher
排查过程
移除所有自定义类和服务,仅保留一个返回示例消息的REST控制器时,http.server.requests指标正常出现在metrics响应中。进一步定位发现问题源于自定义认证Filter,但初始不清楚具体原因。
Filter配置类
@Configuration public class FilterConfiguration { @Autowired private AuthenticationFilter authenticationFilter; @Autowired private FilterRegistrationBean registration; /** * Filter configuration bean to apply filter for given url patterns. */ @Bean public FilterRegistrationBean filterConfigurationForAuthentication() { registration.setFilter(authenticationFilter); registration.addUrlPatterns("/workers/endpoint-1"); registration.addUrlPatterns("/workers/endpoint-2"); registration.addUrlPatterns("/workers/endpoint-3"); return registration; } }
Filter类
@Component @Slf4j public class AuthenticationFilter extends OncePerRequestFilter { @Value("${azure.jwt-key-validation-url}") private String azureJwtValidationUrl; @Value("${header-name.authorization}") private String authorizationHeader; @Value("${header-name.api-key}") private String apiKeyHeader; @Value("${basic-auth-username}") private String basicAuthUsername; @Value("${basic-auth-password}") private String basicAuthPassword; @Value("${invalid.jwt.message}") private String invalidJWT; @Value("${missing.jwt.message}") private String missingJWT; @Value("${invalid.api-key.message}") private String invalidApiKey; @Value("${missing.api-key.message}") private String missingApiKey; @Value("${api.key}") private String applicationApiKey; @Value("${invalid.username.message}") private String invalidUsername; @Value("${invalid.password.message}") private String invalidPassword; private final AuthenticationService authenticationService; public AuthenticationFilter(AuthenticationService authenticationService) { this.authenticationService = authenticationService; } /** * Filter to process request and manage authentication for APIs. If valid JWT is provided request * will be processed If JWT is invalid request will be terminated with required message * * @param request incoming request * @param response response for incoming request * @param chain filter chain * @throws IOException if unable to process request * @throws ServletException if unable to process request */ @SneakyThrows @Override public void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { String authorizationHeaderValue = request.getHeader(authorizationHeader); String apiKeyFromRequest = request.getHeader(apiKeyHeader); log.debug("api-key: {}, authorization: {}", apiKeyFromRequest, authorizationHeaderValue); ... chain.doFilter(request, response); } /** * Method to send forbidden response message * * @param response response for current request * @param message message for client or API user * @throws IOException if unable to send response */ private void sendErrorMessage(HttpServletResponse response, String message) throws IOException, JSONException { JSONObject responseValue = new JSONObject(); responseValue.put("message", message); response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setStatus(HttpServletResponse.SC_FORBIDDEN); response.getWriter().write(responseValue.toString()); } }
问题原因与解决方案
问题根源
Filter配置类中错误地Autowired了全局的FilterRegistrationBean实例,并修改了它的Filter和URL匹配规则。这会覆盖Spring Boot自动注册的Micrometer MetricsFilter的配置,导致MetricsFilter仅作用于/workers/endpoint-*路径,而metrics端点(/metrics)的请求不会经过MetricsFilter,因此无法生成http.server.requests指标。
修复方案
在Filter配置类中,不要Autowired现有FilterRegistrationBean,而是创建新的FilterRegistrationBean实例来注册自定义认证Filter:
@Configuration public class FilterConfiguration { @Autowired private AuthenticationFilter authenticationFilter; /** * Filter configuration bean to apply filter for given url patterns. */ @Bean public FilterRegistrationBean filterConfigurationForAuthentication() { // 创建新的FilterRegistrationBean实例,而非修改全局实例 FilterRegistrationBean<AuthenticationFilter> registration = new FilterRegistrationBean<>(); registration.setFilter(authenticationFilter); registration.addUrlPatterns("/workers/endpoint-1"); registration.addUrlPatterns("/workers/endpoint-2"); registration.addUrlPatterns("/workers/endpoint-3"); return registration; } }
额外验证
修复后,重启项目:
- 访问自定义REST API
- 再访问
http://localhost:8080/metrics,即可看到http.server.requests指标,包含API的响应时间、状态码等数据。
内容的提问来源于stack exchange,提问作者anonymous
相关产品推荐
相关产品推荐

