Spring Boot Sping Boot Actuator未在指标端点中显示http.server.requests

yhuiod9q  于 2022-11-05  发布在  Spring
关注(0)|答案(1)|浏览(172)

我确实有一个使用Java 11开发的Sping Boot 项目,我在其中添加了Spring Boot Actuator,以使用指标端点来分析API响应时间和代码。我在pom.xml和www.example.com文件中添加了以下内容application.properties。首先,我确实点击了我开发的REST API,它们返回所需的响应,当我使用http://localhost:8080/metrics检查指标时,我找不到http。服务器。请求。

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>

应用程序.属性


# 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

更新

我已经删除了所有其他类和服务,只保留了剩下的控制器和一个返回示例消息的API,现在我可以看到响应中的http.server.requests。因此,我尝试进一步invistage问题与我的原始项目,并发现这是由于过滤器,我正在使用的身份验证目的。我不知道为什么这个过滤器是打破指标端点

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

}

筛选器

@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());
  }
}
4zcjmb1e

4zcjmb1e1#

更新

添加后:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>

AFilter这样:

package com.stackoverflow.soq74301852;

import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

@Component
@Slf4j
public class AFilter extends OncePerRequestFilter {

  @Value("${foo:foo}")
  private String foo;

  @Value("${bar:bar}")
  private String bar;

  @SneakyThrows
  @Override
  public void doFilterInternal(
      HttpServletRequest request, HttpServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    String fooVal = request.getHeader(foo);
    String barVal = request.getHeader(bar);
    log.debug("api-key: {}, authorization: {}", barVal, fooVal);
    chain.doFilter(request, response);
  }
}

除错:

logging.level.com.stackoverflow=debug

无需额外配置,我们将获得:

  • (“业务”和“致动器”的默认Spring启动安全保护)

一旦通过身份验证(!),:

  • 我们撞到过滤器了!
  • 我们仍然可以达到http://localhost:8080/actuator/metrics/http.server.requests

因此,它(您的问题)必须位于:

  • 附加配置!(/workers/endpoint-x听起来很“l(load)B(alancing)like”;)
  • 或/和...(隐藏代码)中。
  • 或/和您的安全详细信息/config #

原文回答:

对不起,无法复制!

仅使用(pom.xml):

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.6</version> <!-- neither with 2.7.5 (latest "Release" version) -->
    <relativePath/> <!-- lookup parent from repository -->
  </parent>
  ...
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--
     + lombok
     + devtools
    -->
  </dependencies>

和(应用程序.属性):

management.endpoint.metrics.enabled = true
management.endpoints.web.exposure.include = metrics

GET http://localhost:8080/actuator/metrics/会产生(v2.7.5):

{
  "names": [
    "application.ready.time",
    "application.started.time",
    "disk.free",
    "disk.total",
    "executor.active",
    "executor.completed",
    "executor.pool.core",
    "executor.pool.max",
    "executor.pool.size",
    "executor.queue.remaining",
    "executor.queued",
    "http.server.requests",
    "jvm.buffer.count",
    "jvm.buffer.memory.used",
    "jvm.buffer.total.capacity",
    "jvm.classes.loaded",
    "jvm.classes.unloaded",
    "jvm.gc.live.data.size",
    "jvm.gc.max.data.size",
    "jvm.gc.memory.allocated",
    "jvm.gc.memory.promoted",
    "jvm.gc.overhead",
    "jvm.gc.pause",
    "jvm.memory.committed",
    "jvm.memory.max",
    "jvm.memory.usage.after.gc",
    "jvm.memory.used",
    "jvm.threads.daemon",
    "jvm.threads.live",
    "jvm.threads.peak",
    "jvm.threads.states",
    "logback.events",
    "process.cpu.usage",
    "process.start.time",
    "process.uptime",
    "system.cpu.count",
    "system.cpu.usage",
    "tomcat.sessions.active.current",
    "tomcat.sessions.active.max",
    "tomcat.sessions.alive.max",
    "tomcat.sessions.created",
    "tomcat.sessions.expired",
    "tomcat.sessions.rejected"
  ]
}

而GET http://localhost:8080/actuator/metrics/http.server.requests则响应如下:

{
  "name": "http.server.requests",
  "description": "Duration of HTTP server request handling",
  "baseUnit": "seconds",
  "measurements": [{
      "statistic": "COUNT",
      "value": 9.0
    }, {
      "statistic": "TOTAL_TIME",
      "value": 0.11513509999999999
    }, {
      "statistic": "MAX",
      "value": 0.0149434
    }],
  "availableTags": [{
      "tag": "exception",
      "values": ["None"]
    }, {
      "tag": "method",
      "values": ["GET"]
    }, {
      "tag": "uri",
      "values": ["/actuator/metrics/{requiredMetricName}", "/actuator", "/actuator/metrics", "root"]
    }, {
      "tag": "outcome",
      "values": ["SUCCESS"]
    }, {
      "tag": "status",
      "values": ["200"]
    }]
}

可能的原因

  • 缺少依赖项(springboot-starter-web)
  • /不正确的(自动)配置
  • 任何其他...

链接

  • https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#actuator.metrics.supported.spring-mvc
  • https://docs.spring.io/spring-boot/docs/current/actuator-api/htmlsingle/#metrics
  • Metrics Collection for Spring Boot REST APIs

相关问题