first commit
All checks were successful
Build Docker Image / build-and-deploy-image (push) Successful in 38s

This commit is contained in:
2024-10-13 09:26:56 +03:00
commit cd1d9b4be0
8 changed files with 422 additions and 0 deletions

90
app.py Normal file
View File

@@ -0,0 +1,90 @@
import asyncio
import contextlib
import os
import aiofiles
import orjson
from environs import Env
env = Env()
env.read_env()
unit_log_file: str = env.str("UNIT_LOG_FILE")
async def process_log_entry(log_entry):
with contextlib.suppress(Exception):
log_data = orjson.loads(log_entry)
request_time = float(log_data["request_time"])
url = log_data["url"]
http_method = log_data["http_method"]
key = (url, http_method)
return key, {"count": 1, "sum": request_time}
return None
async def read_and_process_logs():
metrics_data = {}
if os.path.exists(unit_log_file):
async with aiofiles.open(unit_log_file, mode="r+") as f:
lines = await f.readlines()
await f.truncate(0)
tasks = [process_log_entry(line) for line in lines]
results = await asyncio.gather(*tasks)
for result in results:
if not result:
continue
key, data = result
if key in metrics_data:
metrics_data[key]["count"] += data["count"]
metrics_data[key]["sum"] += data["sum"]
else:
metrics_data[key] = data
return metrics_data
async def generate_metrics_text():
lines = [
"# HELP request_duration_seconds_total Request duration in seconds",
"# TYPE request_duration_seconds_total counter",
"# HELP request_duration_seconds_count Number of requests",
"# TYPE request_duration_seconds_count counter",
]
metrics_data = await read_and_process_logs()
for key, data in metrics_data.items():
url, http_method = key
count = data["count"]
sum_values = data["sum"]
labels = f'url="{url}",http_method="{http_method}"'
lines.append(f"request_duration_seconds_count{{{labels}}} {count}")
lines.append(f"request_duration_seconds_total{{{labels}}} {sum_values}")
return "\n".join(lines) + "\n"
async def app(scope, receive, send):
if scope["type"] == "http":
if scope["path"] == "/metrics":
headers = [(b"content-type", b"text/plain; charset=utf-8")]
metrics_text = await generate_metrics_text()
body = metrics_text.encode("utf-8")
await send({"type": "http.response.start", "status": 200, "headers": headers})
await send({"type": "http.response.body", "body": body})
else:
await send(
{
"type": "http.response.start",
"status": 404,
"headers": [(b"content-type", b"text/plain; charset=utf-8")],
}
)
await send({"type": "http.response.body", "body": b"Not Found"})