Spaces:
Build error
Build error
Upload folder using huggingface_hub
Browse files- app/core/usage_tracker.py +4 -4
- tests/test_usage_tracker.py +29 -0
app/core/usage_tracker.py
CHANGED
|
@@ -607,8 +607,8 @@ class UsageTracker:
|
|
| 607 |
processing_ms, idempotency_key)
|
| 608 |
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
| 609 |
(record.api_key, record.tier.value, record.timestamp, record.endpoint,
|
| 610 |
-
json.dumps(record.request_body) if record.request_body else None,
|
| 611 |
-
json.dumps(record.response) if record.response else None,
|
| 612 |
record.error, record.processing_ms, idempotency_key)
|
| 613 |
)
|
| 614 |
conn.commit()
|
|
@@ -644,8 +644,8 @@ class UsageTracker:
|
|
| 644 |
processing_ms, idempotency_key)
|
| 645 |
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
| 646 |
(record.api_key, tier_value, record.timestamp, record.endpoint,
|
| 647 |
-
json.dumps(record.request_body) if record.request_body else None,
|
| 648 |
-
json.dumps(record.response) if record.response else None,
|
| 649 |
record.error, record.processing_ms, None)
|
| 650 |
)
|
| 651 |
conn.commit()
|
|
|
|
| 607 |
processing_ms, idempotency_key)
|
| 608 |
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
| 609 |
(record.api_key, record.tier.value, record.timestamp, record.endpoint,
|
| 610 |
+
json.dumps(record.request_body, default=str) if record.request_body else None,
|
| 611 |
+
json.dumps(record.response, default=str) if record.response else None,
|
| 612 |
record.error, record.processing_ms, idempotency_key)
|
| 613 |
)
|
| 614 |
conn.commit()
|
|
|
|
| 644 |
processing_ms, idempotency_key)
|
| 645 |
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
| 646 |
(record.api_key, tier_value, record.timestamp, record.endpoint,
|
| 647 |
+
json.dumps(record.request_body, default=str) if record.request_body else None,
|
| 648 |
+
json.dumps(record.response, default=str) if record.response else None,
|
| 649 |
record.error, record.processing_ms, None)
|
| 650 |
)
|
| 651 |
conn.commit()
|
tests/test_usage_tracker.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
| 1 |
import json
|
| 2 |
import os
|
|
|
|
| 3 |
|
| 4 |
import psycopg2
|
| 5 |
import pytest
|
|
@@ -177,3 +178,31 @@ def test_insert_audit_log_writes_response_row(tracker):
|
|
| 177 |
assert logs[0]["endpoint"] == "/api/v1/intents/evaluate/response"
|
| 178 |
assert logs[0]["tier"] == "unknown"
|
| 179 |
assert json.loads(logs[0]["response"]) == {"recommended_action": "approve"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import json
|
| 2 |
import os
|
| 3 |
+
from datetime import datetime
|
| 4 |
|
| 5 |
import psycopg2
|
| 6 |
import pytest
|
|
|
|
| 178 |
assert logs[0]["endpoint"] == "/api/v1/intents/evaluate/response"
|
| 179 |
assert logs[0]["tier"] == "unknown"
|
| 180 |
assert json.loads(logs[0]["response"]) == {"recommended_action": "approve"}
|
| 181 |
+
|
| 182 |
+
|
| 183 |
+
def test_consume_quota_and_log_handles_non_json_native_request_body(tracker):
|
| 184 |
+
"""request_body/response are whatever a Pydantic model's plain
|
| 185 |
+
.model_dump() returns, e.g. ReliabilityEvent.timestamp in
|
| 186 |
+
app/api/routes_governance.py's HealingDecisionRequest -- a raw
|
| 187 |
+
datetime, not the ISO string model_dump(mode="json") would produce.
|
| 188 |
+
json.dumps has no default encoder for datetime, so any real request
|
| 189 |
+
carrying one raised TypeError here, outside any try/except in the
|
| 190 |
+
/healing/evaluate handler, on every call (surfaced while verifying the
|
| 191 |
+
tier=None fix for that same endpoint: fixing tier alone still crashed,
|
| 192 |
+
one layer deeper, on this). default=str makes the insert tolerant of
|
| 193 |
+
datetime and any other type json.dumps doesn't natively handle."""
|
| 194 |
+
tracker.get_or_create_api_key("datetime-body-key", tenant_id="test")
|
| 195 |
+
record = UsageRecord(
|
| 196 |
+
api_key="datetime-body-key",
|
| 197 |
+
tier=Tier.FREE,
|
| 198 |
+
timestamp=time.time(),
|
| 199 |
+
endpoint="/api/v1/healing/evaluate",
|
| 200 |
+
request_body={"event": {"component": "svc", "timestamp": datetime.now()}},
|
| 201 |
+
)
|
| 202 |
+
|
| 203 |
+
result = tracker.increment_usage_sync(record)
|
| 204 |
+
assert result is True
|
| 205 |
+
|
| 206 |
+
logs = tracker.get_audit_logs("datetime-body-key", limit=10)
|
| 207 |
+
assert len(logs) == 1
|
| 208 |
+
assert "timestamp" in json.loads(logs[0]["request_body"])["event"]
|