feat: add image route usage telemetry

This commit is contained in:
QiuSW
2026-07-08 22:44:17 +08:00
parent 25a4080177
commit d5656b4f56
13 changed files with 379 additions and 18 deletions
+123
View File
@@ -1168,6 +1168,43 @@ class GenerateApiTests(TestCase):
with patch("apps.api.generation.get_provider", return_value=provider or self.provider):
return self.client.post(path, payload, format="json", **self.auth_header(), **extra)
def telemetry_event_from_logs(self, captured):
events = [
getattr(record, "generation_route_usage", None)
for record in captured.records
if getattr(record, "generation_route_usage", None)
]
self.assertEqual(len(events), 1)
return events[0]
def assert_generation_telemetry_is_safe(self, event, *, payload=None):
self.assertEqual(
set(event),
{
"event",
"route_type",
"api_key_id",
"api_key_prefix",
"user_id",
"client_version",
"alias",
"status",
"latency_ms",
"error_code",
"http_status",
},
)
serialized = json.dumps(event, ensure_ascii=False)
self.assertNotIn(self.raw_key, serialized)
self.assertNotIn("SECRET_RAW", serialized)
self.assertNotIn("prompt", serialized)
self.assertNotIn("image_base64", serialized)
if payload:
self.assertNotIn(str(payload.get("prompt") or ""), serialized)
encoded_image = str(payload.get("image_base64") or "")
if encoded_image:
self.assertNotIn(encoded_image, serialized)
def assert_generation_not_charged(self):
self.wallet.refresh_from_db()
self.assertEqual(self.wallet.points_balance, 100)
@@ -1288,6 +1325,92 @@ class GenerateApiTests(TestCase):
self.assertEqual(call.result_summary, "image_bytes=21")
self.assertNotIn("SECRET_RAW", call.result_ref + call.result_summary)
def test_sync_image_usage_telemetry_logs_safe_client_version_and_key_identity(self):
encoded = base64.b64encode(b"input-image").decode("ascii")
payload = {
"prompt": "生成图片遥测测试",
"model": self.image_alias,
"image_base64": f"data:image/png;base64,{encoded}",
"resolution": "1K",
"aspect_ratio": "1:1",
}
with self.assertLogs("cmhub.api.generation_usage", level="INFO") as captured:
response = self.post_with_provider(
"/api/v1/generate/image",
payload,
HTTP_X_CLIENT_VERSION="0.1.1",
)
self.assertEqual(response.status_code, 200)
event = self.telemetry_event_from_logs(captured)
self.assertEqual(event["event"], "generation_route_usage")
self.assertEqual(event["route_type"], "sync")
self.assertEqual(event["api_key_id"], self.api_key.id)
self.assertEqual(event["api_key_prefix"], self.api_key.key_prefix)
self.assertEqual(event["user_id"], self.user.id)
self.assertEqual(event["client_version"], "0.1.1")
self.assertEqual(event["alias"], self.image_alias)
self.assertEqual(event["status"], "success")
self.assertEqual(event["error_code"], "")
self.assertEqual(event["http_status"], 200)
self.assertIsInstance(event["latency_ms"], int)
self.assertGreaterEqual(event["latency_ms"], 0)
self.assert_generation_telemetry_is_safe(event, payload=payload)
def test_async_image_submit_usage_telemetry_logs_safe_success_event(self):
payload = {
"prompt": "生成异步图片遥测测试",
"model": self.image_alias,
"resolution": "1K",
}
with self.assertLogs("cmhub.api.generation_usage", level="INFO") as captured:
response = self.post_with_provider(
"/api/v1/generate/image/tasks",
payload,
HTTP_X_CLIENT_VERSION="0.1.2",
)
self.assertEqual(response.status_code, 202)
event = self.telemetry_event_from_logs(captured)
self.assertEqual(event["route_type"], "async")
self.assertEqual(event["api_key_id"], self.api_key.id)
self.assertEqual(event["api_key_prefix"], self.api_key.key_prefix)
self.assertEqual(event["user_id"], self.user.id)
self.assertEqual(event["client_version"], "0.1.2")
self.assertEqual(event["alias"], self.image_alias)
self.assertEqual(event["status"], "success")
self.assertEqual(event["error_code"], "")
self.assertEqual(event["http_status"], 202)
self.assert_generation_telemetry_is_safe(event, payload=payload)
def test_async_image_submit_usage_telemetry_logs_error_code_without_sensitive_data(self):
self.wallet.points_balance = 1
self.wallet.save(update_fields=("points_balance", "updated_at"))
payload = {
"prompt": "余额不足遥测测试",
"model": self.image_alias,
"resolution": "1K",
}
with self.assertLogs("cmhub.api.generation_usage", level="INFO") as captured:
response = self.post_with_provider(
"/api/v1/generate/image/tasks",
payload,
HTTP_X_CLIENT_VERSION="0.1.3",
)
self.assertEqual(response.status_code, 402)
event = self.telemetry_event_from_logs(captured)
self.assertEqual(event["route_type"], "async")
self.assertEqual(event["status"], "error")
self.assertEqual(event["error_code"], "insufficient_points")
self.assertEqual(event["http_status"], 402)
self.assertEqual(event["client_version"], "0.1.3")
self.assertEqual(event["alias"], self.image_alias)
self.assert_generation_telemetry_is_safe(event, payload=payload)
@override_settings(
MODERATION_ENABLED=True,
MODERATION_PROVIDER="keyword",