Add request metrics database
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
import json
|
||||
import os
|
||||
import sqlite3
|
||||
import time
|
||||
import uuid
|
||||
|
||||
|
||||
DEFAULT_DB_PATH = "/var/lib/recipe/metrics.sqlite3"
|
||||
|
||||
|
||||
def db_path() -> str:
|
||||
return os.environ.get("RECIPE_METRICS_DB", DEFAULT_DB_PATH)
|
||||
|
||||
|
||||
def initialize() -> None:
|
||||
path = db_path()
|
||||
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||
with sqlite3.connect(path) as connection:
|
||||
connection.execute("PRAGMA journal_mode=WAL")
|
||||
connection.execute("""
|
||||
CREATE TABLE IF NOT EXISTS requests (
|
||||
request_id TEXT PRIMARY KEY,
|
||||
started_at TEXT NOT NULL,
|
||||
client_ip TEXT,
|
||||
user_agent TEXT,
|
||||
method TEXT NOT NULL,
|
||||
path TEXT NOT NULL,
|
||||
image_mime TEXT,
|
||||
image_bytes INTEGER,
|
||||
prompt_chars INTEGER,
|
||||
status_code INTEGER NOT NULL,
|
||||
duration_ms INTEGER NOT NULL,
|
||||
response_bytes INTEGER,
|
||||
usage_json TEXT,
|
||||
error TEXT
|
||||
)
|
||||
""")
|
||||
connection.execute("CREATE INDEX IF NOT EXISTS idx_requests_started_at ON requests(started_at)")
|
||||
connection.execute("CREATE INDEX IF NOT EXISTS idx_requests_status_code ON requests(status_code)")
|
||||
|
||||
|
||||
def record(**values) -> None:
|
||||
initialize()
|
||||
columns = [
|
||||
"request_id", "started_at", "client_ip", "user_agent", "method",
|
||||
"path", "image_mime", "image_bytes", "prompt_chars", "status_code",
|
||||
"duration_ms", "response_bytes", "usage_json", "error",
|
||||
]
|
||||
payload = [values.get(column) for column in columns]
|
||||
with sqlite3.connect(db_path()) as connection:
|
||||
connection.execute(
|
||||
f"INSERT INTO requests ({','.join(columns)}) VALUES ({','.join('?' for _ in columns)})",
|
||||
payload,
|
||||
)
|
||||
|
||||
|
||||
def request_context() -> tuple[str, str, float]:
|
||||
return str(uuid.uuid4()), time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), time.monotonic()
|
||||
|
||||
|
||||
def usage_json(usage: dict) -> str:
|
||||
return json.dumps(usage, ensure_ascii=True, separators=(",", ":"))
|
||||
Reference in New Issue
Block a user