https://github.com/lchristmann/mysql-laravel-grafana-demo
A demo of a Laravel API processing data from 2 MySQL databases and serving it as JSON to a Grafana Dashboard.
https://github.com/lchristmann/mysql-laravel-grafana-demo
databases docker docker-compose grafana grafana-dashboard grafana-infinity-datasource json-api laravel laravel-12 mysql pest pestphp
Last synced: 4 months ago
JSON representation
A demo of a Laravel API processing data from 2 MySQL databases and serving it as JSON to a Grafana Dashboard.
- Host: GitHub
- URL: https://github.com/lchristmann/mysql-laravel-grafana-demo
- Owner: lchristmann
- License: mit
- Created: 2025-07-18T17:18:41.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2025-08-07T15:07:19.000Z (5 months ago)
- Last Synced: 2025-08-07T16:32:21.139Z (5 months ago)
- Topics: databases, docker, docker-compose, grafana, grafana-dashboard, grafana-infinity-datasource, json-api, laravel, laravel-12, mysql, pest, pestphp
- Language: PHP
- Homepage:
- Size: 519 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# MySQL Laravel Grafana Demo




This project shall demonstrate a setup with
- 2 MySQL databases holding business data
- a Laravel API querying that data and serving it via a JSON API
- and a Grafana dashboard consuming the API
Content-wise, the example is geared towards a fictional business, that has users (that can have sub-users),
protocols that are created and partially signed with QES ([Qualified Electronic Signature](https://en.wikipedia.org/wiki/Qualified_electronic_signature)), and valuations (of products) being done.
## Table of Contents
- [Tech Stack](#tech-stack)
- [Architecture](#architecture)
- [Database](#database)
- [API](#api)
- [Grafana](#grafana)
- [Start and Stop](#start-and-stop)
- [Renew the data](#renew-the-data)
- [One-time Setup](#one-time-setup)
- [Testing](#testing)
## Tech Stack
- 2 [MySQL](https://www.mysql.com/) databases
- 1 [Laravel 12](https://laravel.com/docs/12.x) API
- exposing a JSON API for querying the two MySQL databases
- 1 [Grafana](https://grafana.com/docs/grafana/latest/setup-grafana/installation/docker/) Dashboard
- using the [Grafana Infinity data source plugin](https://grafana.com/docs/plugins/yesoreyeram-infinity-datasource/latest/)
With the [Docker Compose](https://docs.docker.com/compose/) setup being based on my [lchristmann/selfhosted-tracker-backend](https://github.com/lchristmann/selfhosted-tracker-backend) project, which already implements a JSON API, and is itself based on the official [Docker Compose Laravel setup](https://docs.docker.com/guides/frameworks/laravel/) example.
> Note: for a live system a third MySQL database could expand what's possible to visualize by enabling historic data that goes beyond what the business data already offers.
> One would therefor [schedule a recurring task in Laravel](https://laravel.com/docs/12.x/scheduling), that runs queries on the two MySQL DBs
> and stores the result in the third MySQL DB along with a date or timestamp.
## Architecture
### Database
This is the database schema as entity relationship diagram (ERD).

Please refer to the [Data(base) Guide](docs/DATA-GUIDE.md) for information about the seeded data, running migrations, PhpMyAdmin and running SQL queries.
### API
Please refer to the [API Documentation](docs/API-DOCUMENTATION.md).
### Grafana
Please refer to the [Grafana Documentation](docs/GRAFANA-DOCUMENTATION.md).
## Start and Stop
If this is a fresh project, do the [One-time Setup](#one-time-setup) first.
```shell
docker compose up -d
```
```shell
docker compose down
```
### Renew the data
This should be done at least every 3 weeks, so `last_login` is renewed for the users (or else `active` users created during seeding, aren't considered `active` anymore).
```bash
docker compose exec workspace bash
php artisan migrate:refresh --seed
```
## One-time Setup
1. Copy the `.env.dev.example` file to `.env`:
```bash
cp .env.example .env
```
2. Start the Docker Compose Services:
```bash
docker compose up -d
```
3. Install Laravel Dependencies:
```bash
docker compose exec workspace bash
composer install
```
4. Run Migrations and Seeding:
```bash
docker compose exec workspace bash
php artisan db:drop-users-table # not relevant on first ever migration
php artisan migrate:fresh --seed
```
5. Generate Application Key
```shell
docker compose exec workspace php artisan key:generate
```
6. Access the API (e.g. [http://localhost/api/metrics/qes/total-unlocked-users](http://localhost/api/metrics/qes/total-unlocked-users))
Just make sure that it works (i.e. it returns some JSON response) - you can use your browser here.
If it doesn't work yet, ensure that
- you have `http` not `https` in the URL scheme
- all 6 Docker Compose services are up and running (`docker compose ps`)
- in case some are missing, re-run `docker compose up -d`
Also see the [API Documentation](docs/API-DOCUMENTATION.md).
7. Visit the [Grafana Dashboard](http://localhost:3000/d/fb6c8c15-7315-43e0-af17-d5fc0995955d/mysql-laravel-grafana-demo)
Also see the [Grafana Documentation](docs/GRAFANA-DOCUMENTATION.md).
## Testing
I've written the API's tests using the [Pest](https://pestphp.com/) framework, which is built on PHPUnit.
> The tests are based on the seeding, but robust enough to avoid flakiness.
> If some, like the `qes/active-users` fail, make sure you've re-run the seeding sometime in the last 21 days.
Execute the tests:
```shell
docker compose exec workspace bash
php artisan test
```
Execute the tests and generate tests results and coverage reports into the `build` folder:
```shell
docker compose exec workspace bash
php artisan test --log-junit build/junit-report.xml --coverage-clover=build/coverage-clover.xml
```
> Pest supports reporting via various [test results](https://pestphp.com/docs/cli-api-reference#content-logging) and [code coverage](https://pestphp.com/docs/cli-api-reference#content-code-coverage) formats.
As shown in the Laravel docs on [Running tests](https://laravel.com/docs/12.x/testing#running-tests), you have further
options like running tests [in parallel](https://laravel.com/docs/12.x/testing#running-tests-in-parallel) with `--parallel` or [listing the ten slowest](https://laravel.com/docs/12.x/testing#profiling-tests) with `--profile`.