Skip to content

A collection of practical experiments and insights into Spring Boot performance tuning, JPA optimization, query strategies, and observability setup with Grafana, Promtail, Loki, and Prometheus.

License

Notifications You must be signed in to change notification settings

MMrFalcon/movies

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

68 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“˜ About Movis

Movis is a research-driven project focused on exploring practical solutions to common backend development challenges using Spring Boot. Topics include optimizing database queries, comparing EntityManager vs JpaRepository, leveraging JpaSpecificationExecutor, and configuring effective monitoring with Grafana, Prometheus, Loki, and Promtail.

Grafana Setup

The Docker Compose file grafana.yml is designed for Windows systems.
If you're using a different setup, comment out or update the volume mapping:

# E:/logs:/var/log  # Update this path to match your local setup

πŸš€ Start Grafana, Loki, Prometheus and Promtail

Run the following command to start the services:

docker compose -f .\grafana.yml up -d

πŸ› οΈ Enable Spring Boot Logging to Loki

To enable Spring Boot logging with Loki, activate the Maven profile named grafana:

mvn spring-boot:run -Dspring-boot.run.profiles=grafana

πŸ“Œ Access Grafana

Open Grafana in your browser:
πŸ‘‰ http://localhost:3000

Default login credentials:

  • Username: admin
  • Password: admin

πŸ“‘ Add Loki as a Data Source

  1. Go to βš™οΈ Settings β†’ Data Sources
  2. Click "Add data source"
  3. Select Loki
  4. Set the URL to:
    http://loki:3100
    
  5. Click "Save & Test"

πŸ“Š Create a Dashboard

  1. Navigate to:
    • Home β†’ Dashboards β†’ New Dashboard
  2. Select Loki as the data source
  3. Scroll down to Label Filters, then:
    • Select app β†’ movies-app
    • Use the following LogQL query:
      {app="movies-app"} |= ""
      
  4. Click "Visualization Suggestion" and select "Logs"
  5. Use the right panel to customize the view
  6. Don't forget to save your dashboard! πŸ’Ύ

Prometheus Setup

This guide will help you set up Grafana, configure Prometheus as a data source, and create a dashboard.


πŸ“Œ Access Prometheus

Once running, Prometheus can be accessed at: πŸ‘‰ http://localhost:9090

You can use this UI to run PromQL queries and inspect collected metrics.


πŸ“‘ Add Prometheus as a Data Source

  1. Go to βš™οΈ Settings β†’ Data Sources
  2. Click "Add data source"
  3. Select Prometheus
  4. Set the URL to:
    http://prometheus:9090
    
  5. Click "Save & Test"

If Prometheus is running outside of Docker, use:

http://localhost:9090

πŸ“Š Create a Dashboard for Metrics

  1. Navigate to:
    • Home β†’ Dashboards β†’ New Dashboard
  2. Click "Add a new panel"
  3. Select Prometheus as the data source
  4. In the query editor, enter a PromQL query (example):
    http_server_requests_seconds_count{uri="/actuator/prometheus"}
    
  5. Click "Run Query" to see the results
  6. Select a visualization type (e.g., Time Series)
  7. Click "Save Dashboard" and give it a name

πŸ“Œ Verify Metrics Collection

Check the Prometheus UI at http://localhost:9090 and run queries like:

up
http_server_requests_seconds_count

If no data appears, check that your Spring Boot app is running and exposing metrics at: πŸ‘‰ http://localhost:8080/actuator/prometheus


πŸ“Œ Import Prebuilt Dashboards

Grafana has built-in dashboards for JVM, Spring Boot, and Prometheus. You can import one by:

  1. Go to Dashboards β†’ Import
  2. Use the following Dashboard IDs:
  • Spring Boot Metrics: 6756
    If it shows N/A, type host.docker.internal:8080 in the "instance" field.
  • JVM Dashboard: 4701
  • Prometheus Stats: 3662

Useful Links

1️⃣ Check If Spring Boot Exposes Metrics
πŸ‘‰ http://localhost:8080/actuator/prometheus

2️⃣ Verify That Prometheus is Scraping Spring Boot
πŸ‘‰ http://localhost:9090

http_server_requests_seconds_count

βœ… Next Steps

  • Customize queries for your application
  • Add alerts for critical metrics
  • Explore Grafana dashboards for better visualization

Run MySQL Database with Docker

Run the following commands to start the MySQL database:

cd movies/src/main/docker
sudo docker-compose -f mysql.yml up -d

πŸ”— Connect the Application to the Database

Edit the configuration file:
πŸ“„ movies/src/main/java/resources/application.properties

Replace custom.db.address with your Docker machine's IP address.


API Endpoints

πŸ“₯ GET Requests

Retrieve all movies:

http://localhost:8080/api/movies

Use query parameters to filter results:

http://localhost:8080/api/movies?authorNameLike=falcon
http://localhost:8080/api/movies?movieTypeIn=COMEDY,HORROR
http://localhost:8080/api/movies?movieTypeIn=COMEDY,HORROR&authorNameLike=falcon

Retrieve all authors:

http://localhost:8080/api/authors

πŸ” Performance Testing: Effect of Joins

1️⃣ Seed Test Data

Run the following commands to add random test data (this may take time):

POST: /api/authors/seed-by-random-data/1000
POST: /api/movies/seed-by-random-data/10000

2️⃣ Compare Performance with and without Joins

GET: /api/authors/reports/movies-count?page=0&size=10
GET: /api/authors/reports/movies-count-with-join?page=0&size=10

The implementation can be found in:
πŸ“„ AuthorQueryService

Performance tests were conducted in:
πŸ“„ BigDataTestIT


βœ… CRUD Operations in Tests

πŸ—„οΈ Repository Methods:

πŸ” EntityManager Usage:

  • Static methods like findByTitle() and countMovies() can be used anywhere by providing an entityManager and transaction.
  • Implemented in:
    πŸ“„ AuthorControllerTestIT

πŸ› οΈ Using the Specification Pattern with JpaSpecificationExecutor

The Specification pattern is used for filtering data using JpaSpecificationExecutor.
It handles Enums with "IN" clause, numbers with "equals", and Strings with "LIKE".
Implemented in:
πŸ“„ MovieQueryService β†’ findByCriteria()


🎲 Capturing Variables & Functional Interfaces

In πŸ“„ RandomMoviePicker, the following topics are demonstrated:

  1. Capturing Variables: captureMovies() method captures variables within a lambda.
  2. Using Runnable Functional Interface: ifEmpty() executes a block of code.
  3. Using Consumer Functional Interface: ifNonEmptyCapture() processes a list of movies.
  4. Static Factory Method Pattern: from() creates instances of RandomMoviePicker.

These concepts are applied in:
πŸ“„ MovieToWatchServiceImpl β†’ pickMoviesToWatch()

To test the implementation, call:

GET http://localhost:8080/api/movies-to-watch

About

A collection of practical experiments and insights into Spring Boot performance tuning, JPA optimization, query strategies, and observability setup with Grafana, Promtail, Loki, and Prometheus.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages