Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat : grafana LGTM sample #1189

Merged
merged 5 commits into from
Apr 12, 2024
Merged

feat : grafana LGTM sample #1189

merged 5 commits into from
Apr 12, 2024

Conversation

rajadilipkolli
Copy link
Owner

@rajadilipkolli rajadilipkolli commented Apr 12, 2024

Summary by CodeRabbit

  • New Features

    • Introduced LGTM tool stack with Loki, Grafana, Tempo, and Mimir for comprehensive log, metric, and trace visualization.
    • Added a REST controller for greeting messages at /greetings endpoint.
    • Configured Prometheus for monitoring with specific scraping intervals and targets.
    • Deployed Grafana and Prometheus services via Docker, including custom configurations and health checks.
  • Documentation

    • Updated ReadMe with details on the LGTM tool stack and its components.
  • Configuration

    • Established Maven project settings for a Spring Boot application with necessary dependencies for monitoring and testing.
    • Set application properties for Spring Boot management endpoints and application name.
  • Tests

    • Added tests for application functionality and configuration using Spring's testing framework and TestContainers.

Copy link
Contributor

coderabbitai bot commented Apr 12, 2024

Warning

Rate Limit Exceeded

@rajadilipkolli has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 7 minutes and 26 seconds before requesting another review.

How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.
Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.
Please see our FAQ for further information.

Commits Files that changed from the base of the PR and between f3a4d9c and d3ede9d.

Walkthrough

The boot-grafana-lgtm project transformation integrates Loki, Grafana, Tempo, and Mimir into LGTM, a comprehensive toolset for logs, metrics, and traces. Major improvements include Maven configurations, Docker setups for Prometheus and Grafana, and Spring Boot upgrades enhancing observability and testing capabilities.

Changes

File Path Change Summary
.gitignore Rules added to exclude files from version control.
.mvn/wrapper/maven-wrapper.properties Specifies Maven 3.9.6 distribution and wrapper URLs.
ReadMe.md Introduces LGTM tool stack for logging, metrics, and traces.
config/prometheus/prometheus.yml Configures scraping intervals and targets.
docker/docker-compose.yml Introduces Grafana and Prometheus services in Docker containers.
mvnw, mvnw.cmd Scripts for Maven Wrapper startup handling project execution.
pom.xml Adds dependencies and configurations for Spring Boot project.
src/main/.../GrafanaLGTMApplication.java Sets up Spring Boot application with logging and timezone settings.
src/main/.../GreetingsController.java Defines a REST controller with metrics monitoring.
src/main/resources/application.properties Introduces configuration settings for the application.
src/test/.../GrafanaLGTMApplicationTest.java Implements tests for Prometheus method in GrafanaLGTMApplication.
src/test/.../TestGrafanaLGTMApplication.java Defines a test configuration for Grafana LGTM using TestContainers.
.github/workflows/boot-choas-monkey.yml Updates JDK version in the workflow from 17 to 21.
.github/workflows/boot-grafana-lgtm.yml Sets up GitHub Actions workflow for unit and integration tests on boot-grafana-lgtm.

🐇✨
In the burrow of code, under the moon's glow,
A rabbit hopped with files in tow.
With a flick and a hop, setups align,
LGTM's magic, oh so fine!
Cheers to logs and metrics, all in line! 🌟
🐇💻


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@rajadilipkolli rajadilipkolli self-assigned this Apr 12, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Comment on lines 9 to 20
@SpringBootTest(classes = {TestGrafanaLGTMApplication.class})
@AutoConfigureMockMvc
class GrafanaLGTMApplicationTest {

@Autowired
private MockMvc mockMvc;

@Test
void prometheus(){

}
}
Copy link
Contributor

@coderabbitai coderabbitai bot Apr 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test configuration is set up correctly. However, the prometheus test method is empty and needs to be implemented.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderabbitai , help me to write integration test which calls below curl using spring boots mockmvc

curl --user "admin:admin" \
	--data-urlencode 'query=http_server_request_duration_seconds_count' \
	http://localhost:3000/api/datasources/proxy/uid/prometheus/api/v1/query

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rajadilipkolli, here's how you can write the integration test using Spring Boot's MockMvc to simulate the curl command you provided. This test will perform a GET request to the specified Grafana endpoint, including basic authentication and the required query parameter:

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.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

@SpringBootTest(classes = {TestGrafanaLGTMApplication.class})
@AutoConfigureMockMvc
class GrafanaLGTMApplicationTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    void prometheus() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/api/datasources/proxy/uid/prometheus/api/v1/query")
                .with(httpBasic("admin", "admin"))
                .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                .param("query", "http_server_request_duration_seconds_count"))
            .andExpect(MockMvcResultMatchers.status().isOk())
            .andExpect(MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
            .andExpect(MockMvcResultMatchers.jsonPath("$.data.result").exists());
    }
}

This test checks that the endpoint is reachable, returns a 200 OK status, and the response is JSON containing a data.result field. Adjust the assertions as needed based on the actual expected response structure.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderabbitai, expand above example to clearly have imports or method of httpBasic

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rajadilipkolli, I've expanded the example to include the necessary imports and a brief explanation of the httpBasic method used for authentication in the test. Here's the updated test code:

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.http.MediaType;
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

@SpringBootTest(classes = {TestGrafanaLGTMApplication.class})
@AutoConfigureMockMvc
class GrafanaLGTMApplicationTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    void prometheus() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/api/datasources/proxy/uid/prometheus/api/v1/query")
                .with(SecurityMockMvcRequestPostProcessors.httpBasic("admin", "admin"))
                .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                .param("query", "http_server_request_duration_seconds_count"))
            .andExpect(MockMvcResultMatchers.status().isOk())
            .andExpect(MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
            .andExpect(MockMvcResultMatchers.jsonPath("$.data.result").exists());
    }
}

The httpBasic method is part of the SecurityMockMvcRequestPostProcessors class, which is used here to add basic authentication to the request. This method takes two parameters: the username and the password. In this test, it's used to authenticate as "admin" with the password "admin". This setup is necessary to test secured endpoints.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rajadilipkolli, here's how you can rewrite the test using RestAssured and the necessary dependencies to add in your POM.xml.

Updated Test Code with RestAssured

package com.learning.grafanalgtm;

import io.restassured.RestAssured;
import io.restassured.authentication.PreemptiveBasicAuthScheme;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;

class GrafanaLGTMApplicationTest {

    @BeforeAll
    static void setup() {
        RestAssured.baseURI = "http://localhost:3000";
        PreemptiveBasicAuthScheme authScheme = new PreemptiveBasicAuthScheme();
        authScheme.setUserName("admin");
        authScheme.setPassword("admin");
        RestAssured.authentication = authScheme;
    }

    @Test
    void prometheus() {
        given()
            .contentType("application/x-www-form-urlencoded")
            .body("query=http_server_request_duration_seconds_count")
        .when()
            .post("/api/datasources/proxy/uid/prometheus/api/v1/query")
        .then()
            .statusCode(200)
            .contentType("application/json")
            .body("data.result", not(empty()));
    }
}

Required Dependencies for POM.xml

Add the following dependencies to your pom.xml to use RestAssured in your project:

<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <version>5.1.1</version>
    <scope>test</scope>
</dependency>

This setup configures RestAssured with basic authentication and performs a POST request similar to your curl command. The test checks for a 200 status code, correct content type, and non-empty result data. Adjust the base URI and other parameters as necessary for your environment.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderabbitai, it has worked, thank you. Can you please change to below POST CURL

curl --user "admin:admin"
--data-urlencode 'q={span.http.response.status_code="200"}'
http://localhost:3000/api/datasources/proxy/uid/tempo/api/search

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rajadilipkolli, I've updated the RestAssured test to match the new POST curl command you provided. Here's the revised test code:

package com.learning.grafanalgtm;

import io.restassured.RestAssured;
import io.restassured.authentication.PreemptiveBasicAuthScheme;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;

class GrafanaLGTMApplicationTest {

    @BeforeAll
    static void setup() {
        RestAssured.baseURI = "http://localhost:3000";
        PreemptiveBasicAuthScheme authScheme = new PreemptiveBasicAuthScheme();
        authScheme.setUserName("admin");
        authScheme.setPassword("admin");
        RestAssured.authentication = authScheme;
    }

    @Test
    void tempoQuery() {
        given()
            .contentType("application/x-www-form-urlencoded")
            .body("q={span.http.response.status_code=\"200\"}")
        .when()
            .post("/api/datasources/proxy/uid/tempo/api/search")
        .then()
            .statusCode(200)
            .contentType("application/json")
            .body("data.result", not(empty()));
    }
}

This test now targets the /api/datasources/proxy/uid/tempo/api/search endpoint and sends a POST request with the query q={span.http.response.status_code="200"}. It checks for a 200 status code, correct content type, and non-empty result data in the response. Adjust the base URI and other parameters as necessary for your environment.

If you need further adjustments or have any more requests, feel free to let me know!


If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderabbitai, I have improve readablity by tweaking above code as

.statusCode(HttpStatus.SC_OK)
                .contentType(ContentType.JSON)

where imports are from

import io.restassured.http.ContentType;
import org.apache.http.HttpStatus;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rajadilipkolli, the improvements you've made to the test code enhance its readability and maintainability significantly. Using HttpStatus.SC_OK and ContentType.JSON not only makes the code cleaner but also less prone to errors associated with raw values. Great choice!

If there's anything more you need help with or any other adjustments you'd like to discuss, feel free to let me know!

🐰

(\__/) 
(•ㅅ•) CodeRabbit is happy to see your code becoming cleaner and more robust!
/   づ

New Learnings Added
User: rajadilipkolli"
URL: https://github.com/rajadilipkolli/my-spring-boot-experiments/pull/1189

Timestamp: 2024-04-13T07:17:05.492Z
Learning: User prefers using constants like `HttpStatus.SC_OK` and `ContentType.JSON` for status codes and content types in tests to improve readability and maintainability.

Note: Learnings are effective only in the context of specific code segments. To apply general coding guidelines, please configure review instructions.

boot-grafana-lgtm/ReadMe.md Outdated Show resolved Hide resolved

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

boot-grafana-lgtm/ReadMe.md Show resolved Hide resolved
boot-grafana-lgtm/ReadMe.md Show resolved Hide resolved
boot-grafana-lgtm/ReadMe.md Show resolved Hide resolved
boot-grafana-lgtm/ReadMe.md Show resolved Hide resolved
boot-grafana-lgtm/ReadMe.md Outdated Show resolved Hide resolved
boot-grafana-lgtm/ReadMe.md Outdated Show resolved Hide resolved
rajadilipkolli and others added 2 commits April 12, 2024 11:49

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@rajadilipkolli rajadilipkolli merged commit 191b6e3 into main Apr 12, 2024
6 checks passed
@rajadilipkolli rajadilipkolli deleted the grafana-lgtm branch April 12, 2024 11:52
Copy link

Quality Gate Passed Quality Gate passed

Issues
0 New issues
0 Accepted issues

Measures
0 Security Hotspots
No data about Coverage
0.0% Duplication on New Code

See analysis details on SonarCloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant