linked metrics-endpoint #132

Merged
hsh-michaelhoennig merged 5 commits from feature/linked-metrics-endpoint into master 2024-12-06 10:08:32 +01:00
4 changed files with 87 additions and 2 deletions
Showing only changes of commit 73016ae2fd - Show all commits

View File

@ -0,0 +1,42 @@
package net.hostsharing.hsadminng.config;
import lombok.Getter;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import java.util.List;
@Component
@Endpoint(id="custom")
public class CustomActuatorEndpoint {
private final RestTemplate restTemplate = new RestTemplate();
@ReadOperation
public String getMetricsLinks() {
final String baseUrl = ServletUriComponentsBuilder.fromCurrentContextPath().build().toUriString();
final var metricsEndpoint = baseUrl + "/actuator/metrics";
final var response = restTemplate.getForObject(metricsEndpoint, ActuatorMetricsEndpointResource.class);
if (response == null || response.getNames() == null) {
throw new IllegalStateException("no metrics available");
}
return generateJsonLinksToMetricEndpoints(response, metricsEndpoint);
}
private static String generateJsonLinksToMetricEndpoints(final ActuatorMetricsEndpointResource response, final String metricsEndpoint) {
final var links = response.getNames().stream()
.map(name -> "\"" + name + "\": \"" + metricsEndpoint + "/" + name + "\"")
.toList();
return "{\n" + String.join(",\n", links) + "\n}";
}
@Getter
private static class ActuatorMetricsEndpointResource {
private List<String> names;
}
}

View File

@ -8,7 +8,7 @@ management:
endpoints: endpoints:
web: web:
exposure: exposure:
include: info, health, metrics include: info, health, metrics, custom
observations: observations:
annotations: annotations:
enabled: true enabled: true

View File

@ -0,0 +1,43 @@
package net.hostsharing.hsadminng.config;
import io.restassured.RestAssured;
import net.hostsharing.hsadminng.HsadminNgApplication;
import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
import net.hostsharing.hsadminng.test.DisableSecurityConfig;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalManagementPort;
import org.springframework.test.context.ActiveProfiles;
import static net.hostsharing.hsadminng.rbac.test.JsonMatcher.lenientlyEquals;
@SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = { HsadminNgApplication.class, DisableSecurityConfig.class, JpaAttempt.class }
)
@ActiveProfiles("test")
class CustomActuatorEndpointAcceptanceTest {
@LocalManagementPort
private Integer managementPort;
@Test
void shouldListMetricLinks() {
RestAssured // @formatter:off
.given()
.port(managementPort)
.when()
.get("http://localhost/actuator/custom")
.then().log().all().assertThat()
.statusCode(200)
.contentType("application/vnd.spring-boot.actuator.v3+json")
.body("", lenientlyEquals("""
{
"application.ready.time": "http://localhost:%{managementPort}/actuator/metrics/application.ready.time",
"application.started.time": "http://localhost:%{managementPort}/actuator/metrics/application.started.time"
}
""".replace("%{managementPort}", managementPort.toString())));
// @formatter:on
}
}

View File

@ -6,7 +6,7 @@ management:
endpoints: endpoints:
web: web:
exposure: exposure:
include: info, health, metrics include: info, health, metrics, custom
spring: spring:
sql: sql: