You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
  }

}

额外验证

修复后,重启项目:

  1. 访问自定义REST API
  2. 再访问http://localhost:8080/metrics,即可看到http.server.requests指标,包含API的响应时间、状态码等数据。

内容的提问来源于stack exchange,提问作者anonymous

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 10:05:32