Spaces:
Running
Running
Upload 94 files
Browse files- app.py +6 -4
- runtime_log_privacy.py +40 -0
app.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
# ⚙️ 后端逻辑/核心服务端.py (Hugging Face Spaces app.py)
|
| 2 |
-
from runtime_log_privacy import install_uvicorn_privacy_filters, route_label
|
| 3 |
install_uvicorn_privacy_filters()
|
| 4 |
|
| 5 |
from fastapi import FastAPI, File, UploadFile, Form, Depends, HTTPException, Request
|
|
@@ -171,7 +171,7 @@ async def validation_exception_handler(request, exc):
|
|
| 171 |
@app.exception_handler(Exception)
|
| 172 |
async def global_exception_handler(request, exc):
|
| 173 |
"""🚀 P3优化:全局异常处理,捕获所有未预期异常"""
|
| 174 |
-
error_id =
|
| 175 |
logger.error(f"Unhandled Exception [{error_id}] | {route_label(request)} | error_type={type(exc).__name__}")
|
| 176 |
return JSONResponse(
|
| 177 |
status_code=500,
|
|
@@ -180,7 +180,8 @@ async def global_exception_handler(request, exc):
|
|
| 180 |
"服务器内部错误,请稍后重试",
|
| 181 |
"internal_error",
|
| 182 |
error_id=error_id
|
| 183 |
-
)
|
|
|
|
| 184 |
)
|
| 185 |
|
| 186 |
|
|
@@ -364,8 +365,9 @@ app.add_middleware(
|
|
| 364 |
allow_credentials=False,
|
| 365 |
allow_methods=["*"],
|
| 366 |
allow_headers=["*"],
|
| 367 |
-
expose_headers=["ETag", "X-Ranking-Error-Scope"],
|
| 368 |
)
|
|
|
|
| 369 |
|
| 370 |
# ==========================================
|
| 371 |
# 路由挂载
|
|
|
|
| 1 |
# ⚙️ 后端逻辑/核心服务端.py (Hugging Face Spaces app.py)
|
| 2 |
+
from runtime_log_privacy import install_uvicorn_privacy_filters, route_label, RequestTraceMiddleware
|
| 3 |
install_uvicorn_privacy_filters()
|
| 4 |
|
| 5 |
from fastapi import FastAPI, File, UploadFile, Form, Depends, HTTPException, Request
|
|
|
|
| 171 |
@app.exception_handler(Exception)
|
| 172 |
async def global_exception_handler(request, exc):
|
| 173 |
"""🚀 P3优化:全局异常处理,捕获所有未预期异常"""
|
| 174 |
+
error_id = getattr(request.state, 'ranking_request_id', None) or uuid.uuid4().hex
|
| 175 |
logger.error(f"Unhandled Exception [{error_id}] | {route_label(request)} | error_type={type(exc).__name__}")
|
| 176 |
return JSONResponse(
|
| 177 |
status_code=500,
|
|
|
|
| 180 |
"服务器内部错误,请稍后重试",
|
| 181 |
"internal_error",
|
| 182 |
error_id=error_id
|
| 183 |
+
),
|
| 184 |
+
headers={"X-Ranking-Request-Id": error_id}
|
| 185 |
)
|
| 186 |
|
| 187 |
|
|
|
|
| 365 |
allow_credentials=False,
|
| 366 |
allow_methods=["*"],
|
| 367 |
allow_headers=["*"],
|
| 368 |
+
expose_headers=["ETag", "X-Ranking-Error-Scope", "X-Ranking-Request-Id"],
|
| 369 |
)
|
| 370 |
+
app.add_middleware(RequestTraceMiddleware)
|
| 371 |
|
| 372 |
# ==========================================
|
| 373 |
# 路由挂载
|
runtime_log_privacy.py
CHANGED
|
@@ -1,5 +1,45 @@
|
|
| 1 |
"""运行服务器日志不记录请求目标、客户端标识或异常正文。"""
|
| 2 |
import logging
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
|
| 4 |
|
| 5 |
def route_label(request):
|
|
|
|
| 1 |
"""运行服务器日志不记录请求目标、客户端标识或异常正文。"""
|
| 2 |
import logging
|
| 3 |
+
import time
|
| 4 |
+
import uuid
|
| 5 |
+
from types import SimpleNamespace
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class RequestTraceMiddleware:
|
| 9 |
+
def __init__(self, app, logger=None):
|
| 10 |
+
self.app = app
|
| 11 |
+
self.logger = logger or logging.getLogger('ComfyUI-Ranking.Request')
|
| 12 |
+
|
| 13 |
+
async def __call__(self, scope, receive, send):
|
| 14 |
+
if scope['type'] != 'http':
|
| 15 |
+
return await self.app(scope, receive, send)
|
| 16 |
+
request_id = uuid.uuid4().hex
|
| 17 |
+
scope.setdefault('state', {})['ranking_request_id'] = request_id
|
| 18 |
+
started = time.monotonic()
|
| 19 |
+
status = 500
|
| 20 |
+
completed = False
|
| 21 |
+
|
| 22 |
+
async def traced_send(message):
|
| 23 |
+
nonlocal status, completed
|
| 24 |
+
if message['type'] == 'http.response.start':
|
| 25 |
+
status = message['status']
|
| 26 |
+
message = dict(message)
|
| 27 |
+
message['headers'] = [(key, value) for key, value in message.get('headers', [])
|
| 28 |
+
if key.lower() != b'x-ranking-request-id']
|
| 29 |
+
message['headers'].append((b'x-ranking-request-id', request_id.encode('ascii')))
|
| 30 |
+
await send(message)
|
| 31 |
+
if message['type'] == 'http.response.body' and not message.get('more_body', False):
|
| 32 |
+
completed = True
|
| 33 |
+
|
| 34 |
+
try:
|
| 35 |
+
return await self.app(scope, receive, traced_send)
|
| 36 |
+
finally:
|
| 37 |
+
method = scope.get('method')
|
| 38 |
+
if method not in {'GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'CONNECT', 'TRACE'}:
|
| 39 |
+
method = 'unknown'
|
| 40 |
+
self.logger.info('REQUEST_FINISHED | request_id=%s | method=%s | route=%s | status=%d | duration_ms=%.3f | completed=%s',
|
| 41 |
+
request_id, method, route_label(SimpleNamespace(scope=scope)), status,
|
| 42 |
+
max(0, (time.monotonic() - started) * 1000), completed)
|
| 43 |
|
| 44 |
|
| 45 |
def route_label(request):
|