17
votes

I'm using springbooot 2.4.0 and I added the following dependencies for enabling prometheus metrics:

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
        <groupId>io.micrometer</groupId>
        <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

then in my application.properties I have the following properties

management.endpoints.web.exposure.include=*
management.metrics.enable.all=true

I'm trying to run a simple integration test to see my custom metrics appearing at /actuator/prometheus endpoint. Below the code

package com.example.demo;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import static io.restassured.RestAssured.given;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class IntegrationTest {

  @LocalServerPort
  private int port;

  private String baseUrl;

  @BeforeEach
  public void setup() {
      baseUrl = "http://localhost:" + port;
  }

  @Test
  public void metricsEndpoint() throws Exception {

    given().when().get(baseUrl + "/demo/actuator/prometheus")
            .then()
            .statusCode(200);
    }
}

The error I get here is

java.lang.AssertionError: 1 expectation failed.
Expected status code <200> but was <404>.

while if I repeat the same request for any other endpoint provided by springboot actuator I correctly geth the response, for example I tried /actuator/health, /actuator/info, /actuator/metrics etc..

This happens only during integration tests with @Springboot annotation and this is strange because if I run my application and make a request with postman to the address localhost:8080/actuator/prometheus I correctly get a response.

It is like the prometheus registry is not loaded during tests.

Can anyone help?

Thanks in advance.

EDIT: the solution is the one suggested by Johannes Klug. Adding the annotation @AutoConfigureMetrics solved my problem

3
This referred answer solved my problem as well! It should be marked as the accepted answeraseychell

3 Answers

34
votes

I faced the same issue. After some tracing through spring-context ConditionEvaluator, I found that the newly introduced @ConditionalOnEnabledMetricsExport("prometheus") condition on PrometheusMetricsExportAutoConfiguration prevented the endpoint from loading.

This is intended behavior due to https://github.com/spring-projects/spring-boot/pull/21658 and impacts spring-boot 2.4.x

Fix: add @AutoConfigureMetrics to your test

@AutoConfigureMetrics
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class IntegrationTest {
0
votes

It's happening to me too, with Spring Boot 2.4.1

The only thing that I can think of, is that the endpoints that are included in @SpringBootTest are using the @Endpoint annotation.

For example:

@Endpoint(id = "metrics")
public class MetricsEndpoint {}

@Endpoint(id = "loggers")
public class LoggersEndpoint {}

And the prometheus endpoint is using the @WebEndpoint annotation

@WebEndpoint(id = "prometheus")
public class PrometheusScrapeEndpoint {}

I didn't find if this is how it should work, or is a probable bug

0
votes

I see in your test, you are appending "demo" before actual actuator path.

given().when().get(baseUrl + "/demo/actuator/prometheus")
        .then()
        .statusCode(200);

The correct url should be baseUrl+"/actuator/prometheus".