Add request metrics database

This commit is contained in:
“Naeel”
2026-08-29 13:30:57 +03:00
parent eae62e76f8
commit 773b088bfa
4 changed files with 175 additions and 10 deletions
+78 -10
View File
@@ -4,12 +4,19 @@ import os
import requests
from flask import Flask, jsonify, request
try:
from recipe_service.metrics import initialize, record, request_context, usage_json
except ModuleNotFoundError:
from metrics import initialize, record, request_context, usage_json
app = Flask(__name__)
MAX_IMAGE_BYTES = 10 * 1024 * 1024
ALLOWED_TYPES = {"image/jpeg", "image/png", "image/webp"}
PROXY_URL = "http://127.0.0.1:8768/gemini"
initialize()
def settings() -> dict:
try:
@@ -35,17 +42,58 @@ def health():
@app.post("/recipe")
@app.post("/recipe/")
def recipe():
request_id, started_at, started_monotonic = request_context()
image_mime = None
image_bytes = None
prompt_chars = None
status_code = 500
response_bytes = None
usage = {}
error = None
if not authorized():
return jsonify(error="unauthorized"), 401
status_code = 401
error = "unauthorized"
response = jsonify(error=error)
record(request_id=request_id, started_at=started_at, client_ip=request.remote_addr,
user_agent=request.user_agent.string, method=request.method, path=request.path,
image_mime=image_mime, image_bytes=image_bytes, prompt_chars=prompt_chars,
status_code=status_code, duration_ms=int((__import__('time').monotonic() - started_monotonic) * 1000),
response_bytes=len(response.get_data()), usage_json=usage_json(usage), error=error)
return response, status_code
image = request.files.get("image")
prompt = request.form.get("prompt")
if image is None or not prompt:
return jsonify(error="image and prompt are required"), 400
status_code = 400
error = "image and prompt are required"
response = jsonify(error=error)
record(request_id=request_id, started_at=started_at, client_ip=request.remote_addr,
user_agent=request.user_agent.string, method=request.method, path=request.path,
status_code=status_code, duration_ms=0, response_bytes=len(response.get_data()),
usage_json=usage_json(usage), error=error)
return response, status_code
if image.mimetype not in ALLOWED_TYPES:
return jsonify(error="unsupported image type"), 415
status_code = 415
error = "unsupported image type"
response = jsonify(error=error)
record(request_id=request_id, started_at=started_at, client_ip=request.remote_addr,
user_agent=request.user_agent.string, method=request.method, path=request.path,
image_mime=image.mimetype, prompt_chars=len(prompt), status_code=status_code,
duration_ms=0, response_bytes=len(response.get_data()), usage_json=usage_json(usage), error=error)
return response, status_code
image_data = image.read(MAX_IMAGE_BYTES + 1)
if len(image_data) > MAX_IMAGE_BYTES:
return jsonify(error="image is too large"), 413
status_code = 413
error = "image is too large"
response = jsonify(error=error)
record(request_id=request_id, started_at=started_at, client_ip=request.remote_addr,
user_agent=request.user_agent.string, method=request.method, path=request.path,
image_mime=image.mimetype, image_bytes=len(image_data), prompt_chars=len(prompt),
status_code=status_code, duration_ms=0, response_bytes=len(response.get_data()),
usage_json=usage_json(usage), error=error)
return response, status_code
image_mime = image.mimetype
image_bytes = len(image_data)
prompt_chars = len(prompt)
try:
config = settings()
response = requests.post(
@@ -55,15 +103,35 @@ def recipe():
timeout=180,
)
except (requests.RequestException, RuntimeError) as exc:
return jsonify(error=str(exc) if isinstance(exc, RuntimeError) else "Gemini unavailable"), 503
error = str(exc) if isinstance(exc, RuntimeError) else "Gemini unavailable"
status_code = 503
response = jsonify(error=error)
record(request_id=request_id, started_at=started_at, client_ip=request.remote_addr,
user_agent=request.user_agent.string, method=request.method, path=request.path,
image_mime=image_mime, image_bytes=image_bytes, prompt_chars=prompt_chars,
status_code=status_code, duration_ms=0, response_bytes=len(response.get_data()),
usage_json=usage_json(usage), error=error)
return response, status_code
if response.status_code != 200:
try:
detail = response.json().get("error", {}).get("message", "Gemini request failed")
except ValueError:
detail = "Gemini request failed"
return jsonify(error=detail), 502
error = detail
status_code = 502
response = jsonify(error=error)
record(request_id=request_id, started_at=started_at, client_ip=request.remote_addr,
user_agent=request.user_agent.string, method=request.method, path=request.path,
image_mime=image_mime, image_bytes=image_bytes, prompt_chars=prompt_chars,
status_code=status_code, duration_ms=0, response_bytes=len(response.get_data()),
usage_json=usage_json(usage), error=error)
return response, status_code
data = response.json()
return jsonify(
text=data.get("text"),
usage=data.get("usage", {}),
)
usage = data.get("usage", {})
result = jsonify(text=data.get("text"), usage=usage)
record(request_id=request_id, started_at=started_at, client_ip=request.remote_addr,
user_agent=request.user_agent.string, method=request.method, path=request.path,
image_mime=image_mime, image_bytes=image_bytes, prompt_chars=prompt_chars,
status_code=200, duration_ms=0, response_bytes=len(result.get_data()),
usage_json=usage_json(usage), error=None)
return result