From 224d8f564dc97e77fa07faf2c4fddf69f9622bfe Mon Sep 17 00:00:00 2001 From: Raja Kolli Date: Sat, 13 Apr 2024 13:18:07 +0530 Subject: [PATCH] feat : adds prometheus and tempo test cases (#1192) * feat : grafana LGTM sample * adds workflow * Update boot-grafana-lgtm/ReadMe.md Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * feat : fetch grafana port * feat : adds prometheus and tempo tests * adds grafana-lgtm label * Update SUMMARY.md * fix : broken link --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .github/labeler.yml | 3 + SUMMARY.md | 1 + boot-grafana-lgtm/pom.xml | 29 +++++ .../grafanalgtm/GrafanaLGTMApplication.java | 60 +++++----- .../controller/GreetingsController.java | 37 +++--- .../src/main/resources/application.properties | 4 + .../GrafanaLGTMApplicationTest.java | 107 ++++++++++++++---- .../TestGrafanaLGTMApplication.java | 61 +++++----- 8 files changed, 200 insertions(+), 102 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index bb5d9a870..d353f5e7a 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -7,6 +7,9 @@ "component : choas-monkey": - changed-files: - any-glob-to-any-file: 'boot-choas-monkey/**/*' +"component : grafana-lgtm": + - changed-files: + - any-glob-to-any-file: 'boot-grafana-lgtm/**/*' "component: mongodb-elasticsearch": - changed-files: - any-glob-to-any-file: 'boot-mongodb-elasticsearch/**/*' diff --git a/SUMMARY.md b/SUMMARY.md index 1e59577ac..f64b0c1b0 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -4,6 +4,7 @@ * [Spring Batch implementation](batch-boot-jpa-sample/README.md) * [API Example for Archunit](boot-api-archunit-sample/README.md) * [spring-boot-choas-monkey](boot-choas-monkey/README.md) +* [Grafana LGTM Implementation](boot-grafana-lgtm/ReadMe.md) * [MongoDb for insertion and search using elastic search](boot-mongodb-elasticsearch/README.md) * [OpenSearch Implementation](boot-opensearch-sample/README.md) * [spring-boot-rabbitmq-thymeleaf](boot-rabbitmq-thymeleaf/README.md) diff --git a/boot-grafana-lgtm/pom.xml b/boot-grafana-lgtm/pom.xml index 05f91414a..7e0b1bb15 100644 --- a/boot-grafana-lgtm/pom.xml +++ b/boot-grafana-lgtm/pom.xml @@ -16,6 +16,7 @@ 21 + 2.43.0 @@ -60,6 +61,11 @@ junit-jupiter test + + io.rest-assured + rest-assured + test + @@ -68,6 +74,29 @@ org.springframework.boot spring-boot-maven-plugin + + com.diffplug.spotless + spotless-maven-plugin + ${spotless.version} + + + + 2.43.0 + + + + + + + + + compile + + check + + + + diff --git a/boot-grafana-lgtm/src/main/java/com/learning/grafanalgtm/GrafanaLGTMApplication.java b/boot-grafana-lgtm/src/main/java/com/learning/grafanalgtm/GrafanaLGTMApplication.java index 7ec3e1f71..0f4008e04 100644 --- a/boot-grafana-lgtm/src/main/java/com/learning/grafanalgtm/GrafanaLGTMApplication.java +++ b/boot-grafana-lgtm/src/main/java/com/learning/grafanalgtm/GrafanaLGTMApplication.java @@ -1,31 +1,29 @@ -package com.learning.grafanalgtm; - -import jakarta.annotation.PostConstruct; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -import java.util.TimeZone; - - -@SpringBootApplication -public class GrafanaLGTMApplication { - - private static final Logger log = LoggerFactory.getLogger(GrafanaLGTMApplication.class); - - public static void main(String[] args) { - final Runtime r = Runtime.getRuntime(); - - log.info("[APP] Active processors: {}", r.availableProcessors()); - log.info("[APP] Total memory: {}", r.totalMemory()); - log.info("[APP] Free memory: {}", r.freeMemory()); - log.info("[APP] Max memory: {}", r.maxMemory()); - SpringApplication.run(GrafanaLGTMApplication.class, args); - } - - @PostConstruct - void started() { - TimeZone.setDefault(TimeZone.getTimeZone("GMT")); - } -} +package com.learning.grafanalgtm; + +import jakarta.annotation.PostConstruct; +import java.util.TimeZone; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class GrafanaLGTMApplication { + + private static final Logger log = LoggerFactory.getLogger(GrafanaLGTMApplication.class); + + public static void main(String[] args) { + final Runtime r = Runtime.getRuntime(); + + log.info("[APP] Active processors: {}", r.availableProcessors()); + log.info("[APP] Total memory: {}", r.totalMemory()); + log.info("[APP] Free memory: {}", r.freeMemory()); + log.info("[APP] Max memory: {}", r.maxMemory()); + SpringApplication.run(GrafanaLGTMApplication.class, args); + } + + @PostConstruct + void started() { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + } +} diff --git a/boot-grafana-lgtm/src/main/java/com/learning/grafanalgtm/controller/GreetingsController.java b/boot-grafana-lgtm/src/main/java/com/learning/grafanalgtm/controller/GreetingsController.java index 0189dc413..91a945138 100644 --- a/boot-grafana-lgtm/src/main/java/com/learning/grafanalgtm/controller/GreetingsController.java +++ b/boot-grafana-lgtm/src/main/java/com/learning/grafanalgtm/controller/GreetingsController.java @@ -1,17 +1,20 @@ -package com.learning.grafanalgtm.controller; - -import io.micrometer.core.annotation.Counted; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class GreetingsController { - - @Counted - @GetMapping("/greetings") - public String greetings() { - return "Hello, World!"; - } - -} \ No newline at end of file +package com.learning.grafanalgtm.controller; + +import io.micrometer.core.annotation.Counted; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class GreetingsController { + + private static final Logger LOGGER = LoggerFactory.getLogger(GreetingsController.class); + + @Counted + @GetMapping("/greetings") + public String greetings() { + LOGGER.info("Inside Greetings method"); + return "Hello, World!"; + } +} diff --git a/boot-grafana-lgtm/src/main/resources/application.properties b/boot-grafana-lgtm/src/main/resources/application.properties index 99b27c80f..91bb860de 100644 --- a/boot-grafana-lgtm/src/main/resources/application.properties +++ b/boot-grafana-lgtm/src/main/resources/application.properties @@ -1,3 +1,7 @@ spring.application.name=boot-grafana-lgtm management.endpoints.web.exposure.include=env,health,info,logfile,loggers,metrics,prometheus +management.tracing.sampling.probability=1.0 +management.prometheus.metrics.export.step=1s +management.metrics.distribution.percentiles-histogram.all=true +management.metrics.distribution.percentiles-histogram.http.server.requests=true \ No newline at end of file diff --git a/boot-grafana-lgtm/src/test/java/com/learning/grafanalgtm/GrafanaLGTMApplicationTest.java b/boot-grafana-lgtm/src/test/java/com/learning/grafanalgtm/GrafanaLGTMApplicationTest.java index 65237e923..ad36c264a 100644 --- a/boot-grafana-lgtm/src/test/java/com/learning/grafanalgtm/GrafanaLGTMApplicationTest.java +++ b/boot-grafana-lgtm/src/test/java/com/learning/grafanalgtm/GrafanaLGTMApplicationTest.java @@ -1,24 +1,83 @@ -package com.learning.grafanalgtm; - -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.web.servlet.MockMvc; -import org.testcontainers.containers.GenericContainer; - -@SpringBootTest(classes = {TestGrafanaLGTMApplication.class}) -@AutoConfigureMockMvc -class GrafanaLGTMApplicationTest { - - @Autowired - private MockMvc mockMvc; - - @Autowired - private GenericContainer lgtmContainer; - - @Test - void prometheus(){ - System.out.println("Configured grafana port "+ lgtmContainer.getMappedPort(3000)); - } -} \ No newline at end of file +package com.learning.grafanalgtm; + +import static io.restassured.RestAssured.given; +import static io.restassured.RestAssured.when; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.is; + +import io.restassured.RestAssured; +import io.restassured.authentication.PreemptiveBasicAuthScheme; +import io.restassured.http.ContentType; +import org.apache.http.HttpStatus; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.server.LocalServerPort; +import org.testcontainers.containers.GenericContainer; + +@SpringBootTest( + classes = {TestGrafanaLGTMApplication.class}, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class GrafanaLGTMApplicationTest { + + @Autowired + private GenericContainer lgtmContainer; + + @LocalServerPort + private int localServerPort; + + @BeforeAll + void setUp() { + PreemptiveBasicAuthScheme authScheme = new PreemptiveBasicAuthScheme(); + authScheme.setUserName("admin"); + authScheme.setPassword("admin"); + RestAssured.authentication = authScheme; + } + + @BeforeEach + void setPort() { + RestAssured.port = localServerPort; + } + + @Test + void prometheus() { + // calling endpoint to load metrics + when().get("/greetings").then().statusCode(HttpStatus.SC_OK); + + RestAssured.port = lgtmContainer.getMappedPort(3000); + given().contentType(ContentType.URLENC) + .body("query=http_server_requests_seconds_count") + .when() + .post("/api/datasources/proxy/uid/prometheus/api/v1/query") + .then() + .statusCode(HttpStatus.SC_OK) + .contentType(ContentType.JSON) + .body("status", is("success")) + .body("data.resultType", is("vector")) + .body("data.result", empty()); + } + + @Test + void tempoQuery() { + // calling endpoint to load metrics + when().get("/greetings").then().statusCode(HttpStatus.SC_OK); + + RestAssured.port = lgtmContainer.getMappedPort(3000); + + given().contentType(ContentType.URLENC) + .body("q={span.http.response.status_code=\"200\"}") + .when() + .post("/api/datasources/proxy/uid/tempo/api/search") + .then() + .statusCode(HttpStatus.SC_OK) + .contentType(ContentType.JSON) + .body("metrics.completedJobs", is(1)) + .body("metrics.totalJobs", is(1)) + .log() + .all(); + } +} diff --git a/boot-grafana-lgtm/src/test/java/com/learning/grafanalgtm/TestGrafanaLGTMApplication.java b/boot-grafana-lgtm/src/test/java/com/learning/grafanalgtm/TestGrafanaLGTMApplication.java index 95e576cd6..32866f3ae 100644 --- a/boot-grafana-lgtm/src/test/java/com/learning/grafanalgtm/TestGrafanaLGTMApplication.java +++ b/boot-grafana-lgtm/src/test/java/com/learning/grafanalgtm/TestGrafanaLGTMApplication.java @@ -1,30 +1,31 @@ -package com.learning.grafanalgtm; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.testcontainers.service.connection.ServiceConnection; -import org.springframework.context.annotation.Bean; -import org.testcontainers.containers.GenericContainer; -import org.testcontainers.containers.wait.strategy.Wait; - -import java.time.Duration; - -@TestConfiguration(proxyBeanMethods = false) -public class TestGrafanaLGTMApplication { - - public static void main(String[] args) { - SpringApplication.from(GrafanaLGTMApplication::main).with(TestGrafanaLGTMApplication.class).run(args); - } - - @Bean - @ServiceConnection("otel/opentelemetry-collector-contrib") - GenericContainer lgtmContainer() { - return new GenericContainer<>("grafana/otel-lgtm:0.5.0") - // grafana, otel grpc, otel http - .withExposedPorts(3000, 4317, 4318) - .withEnv("OTEL_METRIC_EXPORT_INTERVAL", "500") - .waitingFor(Wait.forLogMessage(".*The OpenTelemetry collector and the Grafana LGTM stack are up and running.*\\s", 1)) - .withStartupTimeout(Duration.ofMinutes(2)); - } - -} \ No newline at end of file +package com.learning.grafanalgtm; + +import java.time.Duration; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.context.annotation.Bean; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; + +@TestConfiguration(proxyBeanMethods = false) +public class TestGrafanaLGTMApplication { + + public static void main(String[] args) { + SpringApplication.from(GrafanaLGTMApplication::main) + .with(TestGrafanaLGTMApplication.class) + .run(args); + } + + @Bean + @ServiceConnection("otel/opentelemetry-collector-contrib") + GenericContainer lgtmContainer() { + return new GenericContainer<>("grafana/otel-lgtm:0.5.0") + // grafana, otel grpc, otel http + .withExposedPorts(3000, 4317, 4318) + .withEnv("OTEL_METRIC_EXPORT_INTERVAL", "500") + .waitingFor(Wait.forLogMessage( + ".*The OpenTelemetry collector and the Grafana LGTM stack are up and running.*\\s", 1)) + .withStartupTimeout(Duration.ofMinutes(2)); + } +}