Skip to content

Commit 2dedae2

Browse files
submission
1 parent cdce99c commit 2dedae2

12 files changed

Lines changed: 969 additions & 2 deletions

File tree

app_python/app.py

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from fastapi import FastAPI, Request
2-
from fastapi.responses import JSONResponse
2+
from fastapi.responses import JSONResponse, Response
33
import os
44
import platform
55
import socket
@@ -9,6 +9,9 @@
99
import time
1010
import uuid
1111
from contextlib import asynccontextmanager
12+
from prometheus_client import Counter, Histogram, Gauge, generate_latest, CONTENT_TYPE_LATEST
13+
import asyncio
14+
1215

1316
HOST = os.getenv('HOST', '0.0.0.0')
1417
PORT = int(os.getenv('PORT', 5000))
@@ -39,6 +42,77 @@ def format(self, record):
3942
app = FastAPI()
4043
start_time = datetime.now()
4144

45+
http_requests_total = Counter(
46+
'http_requests_total',
47+
'Total HTTP requests',
48+
['method', 'endpoint', 'status']
49+
)
50+
51+
http_request_duration_seconds = Histogram(
52+
'http_request_duration_seconds',
53+
'HTTP request duration',
54+
['method', 'endpoint']
55+
)
56+
57+
http_requests_in_progress = Gauge(
58+
'http_requests_in_progress',
59+
'HTTP requests currently being processed'
60+
)
61+
62+
# Application-specific metrics
63+
64+
uptime_seconds = Gauge(
65+
'app_uptime_seconds',
66+
'Application uptime in seconds'
67+
)
68+
69+
endpoint_response_size_bytes = Histogram(
70+
'endpoint_response_size_bytes',
71+
'Response payload size in bytes',
72+
['endpoint']
73+
)
74+
75+
76+
@app.middleware("http")
77+
async def dispatch(request, call_next):
78+
if request.url.path == "/metrics":
79+
return await call_next(request)
80+
81+
http_requests_in_progress.inc()
82+
83+
start_time = time.time()
84+
status_code = 500
85+
response = None
86+
try:
87+
response = await call_next(request)
88+
status_code = response.status_code
89+
except Exception as e:
90+
status_code = 500
91+
http_requests_in_progress.dec()
92+
raise
93+
finally:
94+
duration = time.time() - start_time
95+
96+
http_requests_total.labels(
97+
method=request.method,
98+
endpoint=request.url.path,
99+
status=status_code
100+
).inc()
101+
102+
http_request_duration_seconds.labels(
103+
method=request.method,
104+
endpoint=request.url.path
105+
).observe(duration)
106+
107+
if response and hasattr(response, 'body'):
108+
response_size = len(response.body)
109+
endpoint_response_size_bytes.labels(
110+
endpoint=request.url.path).observe(response_size)
111+
112+
http_requests_in_progress.dec()
113+
114+
return response
115+
42116

43117
@app.middleware("http")
44118
async def log_requests(request: Request, call_next):
@@ -88,9 +162,25 @@ async def lifespan(app: FastAPI):
88162
logger.info("Application starting up", extra={
89163
"extra_info": {"config": startup_config}})
90164

165+
async def update_uptime():
166+
while True:
167+
uptime_seconds.set(get_uptime()['seconds'])
168+
await asyncio.sleep(5) # Update every 5 seconds
169+
170+
uptime_task = asyncio.create_task(update_uptime())
171+
91172
yield
92173

93174
logger.info("Application shutting down")
175+
uptime_task.cancel()
176+
177+
178+
@app.get('/metrics')
179+
def metrics():
180+
return Response(
181+
generate_latest(),
182+
media_type=CONTENT_TYPE_LATEST
183+
)
94184

95185

96186
@app.get("/")

app_python/requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,5 @@ jsonschema==4.23.0
4747
flake8==7.3.0
4848
mccabe==0.7.0
4949
pycodestyle==2.14.0
50-
pyflakes==3.4.0
50+
pyflakes==3.4.0
51+
prometheus-client==0.23.1

monitoring/docker-compose.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,32 @@ services:
6060
cpus: '0.5'
6161
memory: 256M
6262

63+
prometheus:
64+
image: prom/prometheus:v3.9.0
65+
container_name: prometheus
66+
command:
67+
- '--config.file=/etc/prometheus/prometheus.yml'
68+
- '--storage.tsdb.retention.time=15d'
69+
- '--storage.tsdb.retention.size=10GB'
70+
ports:
71+
- 9090:9090
72+
restart: unless-stopped
73+
volumes:
74+
- ./prometheus:/etc/prometheus
75+
- prometheus-data:/prometheus
76+
networks:
77+
- logging
78+
deploy:
79+
resources:
80+
limits:
81+
cpus: '1.0'
82+
memory: 1G
83+
healthcheck:
84+
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:9090/-/healthy || exit 1"]
85+
interval: 10s
86+
timeout: 5s
87+
retries: 5
88+
6389
grafana:
6490
image: grafana/grafana:12.3.1
6591
container_name: grafana
@@ -87,6 +113,7 @@ services:
87113
volumes:
88114
loki-data:
89115
grafana-data:
116+
prometheus-data:
90117

91118
networks:
92119
logging:

0 commit comments

Comments
 (0)