Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ java = "17"
spring-boot = "3.2.5"
spring-dependency-management = "1.1.4"
micrometer = "1.12.5"
micrometer-tracing = "1.2.5"
prometheus-simpleclient = "0.16.0"
junit-jupiter = "5.10.2"
rest-assured = "5.4.0"
flyway = "10.11.0"
Expand Down Expand Up @@ -33,6 +35,8 @@ spring-boot-configuration-processor = { module = "org.springframework.boot:sprin

micrometer-core = { module = "io.micrometer:micrometer-core", version.ref = "micrometer" }
micrometer-registry-prometheus = { module = "io.micrometer:micrometer-registry-prometheus", version.ref = "micrometer" }
micrometer-observation = { module = "io.micrometer:micrometer-observation", version.ref = "micrometer" }
micrometer-tracing-bridge-otel = { module = "io.micrometer:micrometer-tracing-bridge-otel", version.ref = "micrometer-tracing" }

junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit-jupiter" }
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit-jupiter" }
Expand Down Expand Up @@ -74,6 +78,7 @@ jackson = ["jackson-databind", "jackson-datatype-jsr310"]
testing = ["spring-boot-starter-test", "junit-jupiter-api", "junit-jupiter-engine", "mockito-junit-jupiter", "assertj-core"]
rest-assured-all = ["rest-assured", "rest-assured-json-path", "rest-assured-spring-mock-mvc"]
micrometer = ["micrometer-core", "micrometer-registry-prometheus"]
observability = ["micrometer-core", "micrometer-registry-prometheus", "micrometer-observation", "spring-boot-starter-actuator"]

[plugins]
spring-boot = { id = "org.springframework.boot", version.ref = "spring-boot" }
Expand Down
90 changes: 90 additions & 0 deletions infrastructure/monitoring/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# FTGO Monitoring Infrastructure

Prometheus and Grafana monitoring configuration for FTGO microservices.

## Directory Structure

```
infrastructure/monitoring/
prometheus/
prometheus.yml # Prometheus scrape configuration
grafana/
provisioning/
datasources.yml # Grafana datasource provisioning
dashboards.yml # Grafana dashboard provisioning
dashboards/
order-service-dashboard.json
consumer-service-dashboard.json
courier-service-dashboard.json
restaurant-service-dashboard.json
```

## Prometheus Configuration

The `prometheus.yml` file configures scrape targets for all FTGO services:

| Service | Target | Scrape Path | Interval |
|---------|--------|-------------|----------|
| order-service | order-service:8080 | /actuator/prometheus | 10s |
| consumer-service | consumer-service:8080 | /actuator/prometheus | 10s |
| courier-service | courier-service:8080 | /actuator/prometheus | 10s |
| restaurant-service | restaurant-service:8080 | /actuator/prometheus | 10s |

### Customizing Targets

For non-Docker environments, update the `targets` field with actual host:port values:

```yaml
static_configs:
- targets: ['localhost:8081']
```

## Grafana Dashboards

### Dashboard Overview

Each service dashboard contains three sections:

1. **Business Metrics**: Domain-specific counters, rates, and gauges
2. **HTTP Metrics**: Request rates and p95 response times by endpoint
3. **JVM Metrics**: Heap memory usage and thread counts

### Importing Dashboards

Dashboards are automatically provisioned when using the provisioning configuration. For manual import:

1. Open Grafana UI
2. Navigate to Dashboards > Import
3. Upload the JSON file or paste its contents
4. Select the Prometheus datasource

### Dashboard UIDs

| Dashboard | UID |
|-----------|-----|
| Order Service | ftgo-order-service |
| Consumer Service | ftgo-consumer-service |
| Courier Service | ftgo-courier-service |
| Restaurant Service | ftgo-restaurant-service |

## Quick Start with Docker Compose

```yaml
services:
prometheus:
image: prom/prometheus:v2.50.1
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"

grafana:
image: grafana/grafana:10.3.3
volumes:
- ./grafana/provisioning:/etc/grafana/provisioning
- ./grafana/dashboards:/var/lib/grafana/dashboards
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
{
"annotations": {
"list": []
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 1,
"links": [],
"panels": [
{
"collapsed": false,
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 },
"id": 1,
"title": "Business Metrics",
"type": "row"
},
{
"datasource": { "type": "prometheus", "uid": "${datasource}" },
"fieldConfig": {
"defaults": {
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] }
}
},
"gridPos": { "h": 6, "w": 8, "x": 0, "y": 1 },
"id": 2,
"options": { "colorMode": "value", "graphMode": "area", "reduceOptions": { "calcs": ["lastNotNull"] } },
"title": "Consumers Registered (Total)",
"type": "stat",
"targets": [
{
"expr": "ftgo_consumers_registered_total{application=\"consumer-service\"}",
"legendFormat": "Registered"
}
]
},
{
"datasource": { "type": "prometheus", "uid": "${datasource}" },
"fieldConfig": {
"defaults": {
"thresholds": { "mode": "absolute", "steps": [{ "color": "blue", "value": null }] }
}
},
"gridPos": { "h": 6, "w": 8, "x": 8, "y": 1 },
"id": 3,
"options": { "colorMode": "value", "graphMode": "area", "reduceOptions": { "calcs": ["lastNotNull"] } },
"title": "Active Consumers",
"type": "stat",
"targets": [
{
"expr": "ftgo_consumers_active{application=\"consumer-service\"}",
"legendFormat": "Active"
}
]
},
{
"datasource": { "type": "prometheus", "uid": "${datasource}" },
"fieldConfig": {
"defaults": {
"thresholds": { "mode": "absolute", "steps": [{ "color": "red", "value": null }] }
}
},
"gridPos": { "h": 6, "w": 8, "x": 16, "y": 1 },
"id": 4,
"options": { "colorMode": "value", "graphMode": "area", "reduceOptions": { "calcs": ["lastNotNull"] } },
"title": "Verification Failures (Total)",
"type": "stat",
"targets": [
{
"expr": "ftgo_consumers_verification_failures_total{application=\"consumer-service\"}",
"legendFormat": "Failures"
}
]
},
{
"datasource": { "type": "prometheus", "uid": "${datasource}" },
"fieldConfig": {
"defaults": {
"unit": "reqps"
}
},
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 7 },
"id": 5,
"title": "Consumer Registration Rate",
"type": "timeseries",
"targets": [
{
"expr": "rate(ftgo_consumers_registered_total{application=\"consumer-service\"}[5m])",
"legendFormat": "Registrations/sec"
}
]
},
{
"datasource": { "type": "prometheus", "uid": "${datasource}" },
"fieldConfig": {
"defaults": {
"unit": "reqps"
}
},
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 7 },
"id": 6,
"title": "Verification Rate",
"type": "timeseries",
"targets": [
{
"expr": "rate(ftgo_consumers_verifications_total{application=\"consumer-service\"}[5m])",
"legendFormat": "Verifications/sec"
},
{
"expr": "rate(ftgo_consumers_verification_failures_total{application=\"consumer-service\"}[5m])",
"legendFormat": "Failures/sec"
}
]
},
{
"collapsed": false,
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 15 },
"id": 7,
"title": "HTTP Metrics",
"type": "row"
},
{
"datasource": { "type": "prometheus", "uid": "${datasource}" },
"fieldConfig": {
"defaults": {
"unit": "reqps"
}
},
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 16 },
"id": 8,
"title": "HTTP Request Rate",
"type": "timeseries",
"targets": [
{
"expr": "sum(rate(http_server_requests_seconds_count{application=\"consumer-service\"}[5m])) by (uri, method)",
"legendFormat": "{{method}} {{uri}}"
}
]
},
{
"datasource": { "type": "prometheus", "uid": "${datasource}" },
"fieldConfig": {
"defaults": {
"unit": "s"
}
},
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 16 },
"id": 9,
"title": "HTTP Response Time (p95)",
"type": "timeseries",
"targets": [
{
"expr": "histogram_quantile(0.95, sum(rate(http_server_requests_seconds_bucket{application=\"consumer-service\"}[5m])) by (le, uri))",
"legendFormat": "{{uri}}"
}
]
},
{
"collapsed": false,
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 24 },
"id": 10,
"title": "JVM Metrics",
"type": "row"
},
{
"datasource": { "type": "prometheus", "uid": "${datasource}" },
"fieldConfig": {
"defaults": {
"unit": "bytes"
}
},
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 25 },
"id": 11,
"title": "JVM Heap Memory",
"type": "timeseries",
"targets": [
{
"expr": "jvm_memory_used_bytes{application=\"consumer-service\", area=\"heap\"}",
"legendFormat": "Used {{id}}"
},
{
"expr": "jvm_memory_max_bytes{application=\"consumer-service\", area=\"heap\"}",
"legendFormat": "Max {{id}}"
}
]
},
{
"datasource": { "type": "prometheus", "uid": "${datasource}" },
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 25 },
"id": 12,
"title": "JVM Threads",
"type": "timeseries",
"targets": [
{
"expr": "jvm_threads_live_threads{application=\"consumer-service\"}",
"legendFormat": "Live Threads"
},
{
"expr": "jvm_threads_daemon_threads{application=\"consumer-service\"}",
"legendFormat": "Daemon Threads"
}
]
}
],
"schemaVersion": 39,
"tags": ["ftgo", "consumer-service"],
"templating": {
"list": [
{
"current": { "selected": false, "text": "Prometheus", "value": "Prometheus" },
"hide": 0,
"includeAll": false,
"name": "datasource",
"options": [],
"query": "prometheus",
"type": "datasource"
}
]
},
"time": { "from": "now-1h", "to": "now" },
"title": "FTGO Consumer Service",
"uid": "ftgo-consumer-service"
}
Loading