Skip to content

Commit 3ac25c7

Browse files
committed
feat: add Prometheus metrics, Grafana dashboard, monitoring config
1 parent f68cea5 commit 3ac25c7

5 files changed

Lines changed: 375 additions & 5 deletions

File tree

app/main.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
from contextlib import asynccontextmanager
2-
from fastapi import FastAPI
2+
from fastapi import FastAPI, Response
33
from sqlalchemy import text
44
from app.database import engine
55
from app.routers import vehicles, drivers
6+
from prometheus_fastapi_instrumentator import Instrumentator
7+
8+
instrumentator = Instrumentator()
69

710

811
@asynccontextmanager
912
async def lifespan(app: FastAPI):
10-
# async with engine.begin() as conn:
11-
# await conn.run_sync(Base.metadata.create_all)
13+
instrumentator.expose(app)
1214
yield
1315

1416

1517
app = FastAPI(title="FleetOps API", lifespan=lifespan)
1618

19+
instrumentator.instrument(app)
20+
1721
app.include_router(vehicles.router)
1822
app.include_router(drivers.router)
1923

@@ -30,6 +34,4 @@ async def ready():
3034
await conn.execute(text("SELECT 1"))
3135
return {"status": "ready", "db": "ok"}
3236
except Exception as e:
33-
from fastapi import Response
34-
3537
return Response(status_code=503, content=str(e))

docker-compose.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,26 @@ services:
2727
db:
2828
condition: service_healthy
2929

30+
prometheus:
31+
image: prom/prometheus:v2.51.0
32+
ports:
33+
- "9090:9090"
34+
volumes:
35+
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
36+
depends_on:
37+
- app
38+
39+
grafana:
40+
image: grafana/grafana:10.4.0
41+
ports:
42+
- "3000:3000"
43+
environment:
44+
GF_SECURITY_ADMIN_PASSWORD: admin
45+
volumes:
46+
- grafana_data:/var/lib/grafana
47+
depends_on:
48+
- prometheus
49+
3050
volumes:
3151
postgres_data:
52+
grafana_data:
Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
{
2+
"annotations": {
3+
"list": [
4+
{
5+
"builtIn": 1,
6+
"datasource": {
7+
"type": "grafana",
8+
"uid": "-- Grafana --"
9+
},
10+
"enable": true,
11+
"hide": true,
12+
"iconColor": "rgba(0, 211, 255, 1)",
13+
"name": "Annotations & Alerts",
14+
"type": "dashboard"
15+
}
16+
]
17+
},
18+
"editable": true,
19+
"fiscalYearStartMonth": 0,
20+
"graphTooltip": 0,
21+
"id": 1,
22+
"links": [],
23+
"panels": [
24+
{
25+
"datasource": {
26+
"type": "prometheus",
27+
"uid": "efsvwlvjd8wlcf"
28+
},
29+
"fieldConfig": {
30+
"defaults": {
31+
"color": {
32+
"mode": "palette-classic"
33+
},
34+
"custom": {
35+
"axisBorderShow": false,
36+
"axisCenteredZero": false,
37+
"axisColorMode": "text",
38+
"axisLabel": "",
39+
"axisPlacement": "auto",
40+
"barAlignment": 0,
41+
"drawStyle": "line",
42+
"fillOpacity": 0,
43+
"gradientMode": "none",
44+
"hideFrom": {
45+
"legend": false,
46+
"tooltip": false,
47+
"viz": false
48+
},
49+
"insertNulls": false,
50+
"lineInterpolation": "linear",
51+
"lineWidth": 1,
52+
"pointSize": 5,
53+
"scaleDistribution": {
54+
"type": "linear"
55+
},
56+
"showPoints": "auto",
57+
"spanNulls": false,
58+
"stacking": {
59+
"group": "A",
60+
"mode": "none"
61+
},
62+
"thresholdsStyle": {
63+
"mode": "off"
64+
}
65+
},
66+
"mappings": [],
67+
"thresholds": {
68+
"mode": "absolute",
69+
"steps": [
70+
{
71+
"color": "green",
72+
"value": null
73+
},
74+
{
75+
"color": "red",
76+
"value": 80
77+
}
78+
]
79+
}
80+
},
81+
"overrides": []
82+
},
83+
"gridPos": {
84+
"h": 8,
85+
"w": 12,
86+
"x": 0,
87+
"y": 0
88+
},
89+
"id": 3,
90+
"options": {
91+
"legend": {
92+
"calcs": [],
93+
"displayMode": "list",
94+
"placement": "bottom",
95+
"showLegend": true
96+
},
97+
"tooltip": {
98+
"mode": "single",
99+
"sort": "none"
100+
}
101+
},
102+
"targets": [
103+
{
104+
"datasource": {
105+
"type": "prometheus",
106+
"uid": "efsvwlvjd8wlcf"
107+
},
108+
"editorMode": "code",
109+
"expr": "rate(http_requests_total{status=~\"5..\"}[5m]) / rate(http_requests_total[5m])",
110+
"instant": false,
111+
"legendFormat": "__auto",
112+
"range": true,
113+
"refId": "A"
114+
}
115+
],
116+
"title": "Taux d'erreurs 5xx",
117+
"type": "timeseries"
118+
},
119+
{
120+
"datasource": {
121+
"type": "prometheus",
122+
"uid": "efsvwlvjd8wlcf"
123+
},
124+
"fieldConfig": {
125+
"defaults": {
126+
"color": {
127+
"mode": "palette-classic"
128+
},
129+
"custom": {
130+
"axisBorderShow": false,
131+
"axisCenteredZero": false,
132+
"axisColorMode": "text",
133+
"axisLabel": "",
134+
"axisPlacement": "auto",
135+
"barAlignment": 0,
136+
"drawStyle": "line",
137+
"fillOpacity": 0,
138+
"gradientMode": "none",
139+
"hideFrom": {
140+
"legend": false,
141+
"tooltip": false,
142+
"viz": false
143+
},
144+
"insertNulls": false,
145+
"lineInterpolation": "linear",
146+
"lineWidth": 1,
147+
"pointSize": 5,
148+
"scaleDistribution": {
149+
"type": "linear"
150+
},
151+
"showPoints": "auto",
152+
"spanNulls": false,
153+
"stacking": {
154+
"group": "A",
155+
"mode": "none"
156+
},
157+
"thresholdsStyle": {
158+
"mode": "off"
159+
}
160+
},
161+
"mappings": [],
162+
"thresholds": {
163+
"mode": "absolute",
164+
"steps": [
165+
{
166+
"color": "green",
167+
"value": null
168+
},
169+
{
170+
"color": "red",
171+
"value": 80
172+
}
173+
]
174+
}
175+
},
176+
"overrides": []
177+
},
178+
"gridPos": {
179+
"h": 8,
180+
"w": 12,
181+
"x": 0,
182+
"y": 8
183+
},
184+
"id": 2,
185+
"options": {
186+
"legend": {
187+
"calcs": [],
188+
"displayMode": "list",
189+
"placement": "bottom",
190+
"showLegend": true
191+
},
192+
"tooltip": {
193+
"mode": "single",
194+
"sort": "none"
195+
}
196+
},
197+
"targets": [
198+
{
199+
"datasource": {
200+
"type": "prometheus",
201+
"uid": "efsvwlvjd8wlcf"
202+
},
203+
"editorMode": "code",
204+
"expr": "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))",
205+
"hide": false,
206+
"instant": false,
207+
"legendFormat": "__auto",
208+
"range": true,
209+
"refId": "B"
210+
}
211+
],
212+
"title": "Latence p95 par endpoint",
213+
"type": "timeseries"
214+
},
215+
{
216+
"datasource": {
217+
"type": "prometheus",
218+
"uid": "efsvwlvjd8wlcf"
219+
},
220+
"fieldConfig": {
221+
"defaults": {
222+
"color": {
223+
"mode": "palette-classic"
224+
},
225+
"custom": {
226+
"axisBorderShow": false,
227+
"axisCenteredZero": false,
228+
"axisColorMode": "text",
229+
"axisLabel": "",
230+
"axisPlacement": "auto",
231+
"barAlignment": 0,
232+
"drawStyle": "line",
233+
"fillOpacity": 0,
234+
"gradientMode": "none",
235+
"hideFrom": {
236+
"legend": false,
237+
"tooltip": false,
238+
"viz": false
239+
},
240+
"insertNulls": false,
241+
"lineInterpolation": "linear",
242+
"lineWidth": 1,
243+
"pointSize": 5,
244+
"scaleDistribution": {
245+
"type": "linear"
246+
},
247+
"showPoints": "auto",
248+
"spanNulls": false,
249+
"stacking": {
250+
"group": "A",
251+
"mode": "none"
252+
},
253+
"thresholdsStyle": {
254+
"mode": "off"
255+
}
256+
},
257+
"mappings": [],
258+
"thresholds": {
259+
"mode": "absolute",
260+
"steps": [
261+
{
262+
"color": "green"
263+
},
264+
{
265+
"color": "red",
266+
"value": 80
267+
}
268+
]
269+
}
270+
},
271+
"overrides": []
272+
},
273+
"gridPos": {
274+
"h": 8,
275+
"w": 12,
276+
"x": 0,
277+
"y": 16
278+
},
279+
"id": 1,
280+
"options": {
281+
"legend": {
282+
"calcs": [],
283+
"displayMode": "list",
284+
"placement": "bottom",
285+
"showLegend": true
286+
},
287+
"tooltip": {
288+
"mode": "single",
289+
"sort": "none"
290+
}
291+
},
292+
"targets": [
293+
{
294+
"datasource": {
295+
"type": "prometheus",
296+
"uid": "efsvwlvjd8wlcf"
297+
},
298+
"editorMode": "code",
299+
"expr": "rate(http_requests_total[5m])",
300+
"hide": false,
301+
"instant": false,
302+
"legendFormat": "__auto",
303+
"range": true,
304+
"refId": "A"
305+
},
306+
{
307+
"datasource": {
308+
"type": "prometheus",
309+
"uid": "efsvwlvjd8wlcf"
310+
},
311+
"expr": "",
312+
"hide": false,
313+
"instant": false,
314+
"range": true,
315+
"refId": "B"
316+
}
317+
],
318+
"title": "Requests per second",
319+
"type": "timeseries"
320+
}
321+
],
322+
"schemaVersion": 39,
323+
"tags": [],
324+
"templating": {
325+
"list": []
326+
},
327+
"time": {
328+
"from": "now-5m",
329+
"to": "now"
330+
},
331+
"timepicker": {},
332+
"timezone": "browser",
333+
"title": "FleetOps- Métier",
334+
"uid": "efsywqz3heupsf",
335+
"version": 7,
336+
"weekStart": ""
337+
}

0 commit comments

Comments
 (0)