Spaces:
Paused
Paused
advanced logging
Browse files
app.py
CHANGED
|
@@ -147,15 +147,17 @@ async def thread_safe_auth_middleware(request: Request, call_next):
|
|
| 147 |
api_key = None
|
| 148 |
|
| 149 |
# Check if request has MCP session ID (for established sessions)
|
| 150 |
-
session_id = request.headers.get("Mcp-Session-Id")
|
| 151 |
if session_id:
|
| 152 |
-
logger.
|
| 153 |
if session_id in session_api_keys:
|
| 154 |
# Use stored API key for this session
|
| 155 |
api_key = session_api_keys[session_id]
|
| 156 |
-
logger.
|
| 157 |
else:
|
| 158 |
-
logger.
|
|
|
|
|
|
|
| 159 |
|
| 160 |
# Check for Bearer token (for new sessions or explicit auth)
|
| 161 |
authorization = request.headers.get("Authorization", "")
|
|
@@ -175,7 +177,9 @@ async def thread_safe_auth_middleware(request: Request, call_next):
|
|
| 175 |
if request.method == "DELETE" and session_id:
|
| 176 |
if session_id in session_api_keys:
|
| 177 |
del session_api_keys[session_id]
|
| 178 |
-
logger.
|
|
|
|
|
|
|
| 179 |
return await call_next(request)
|
| 180 |
|
| 181 |
if api_key:
|
|
@@ -190,13 +194,19 @@ async def thread_safe_auth_middleware(request: Request, call_next):
|
|
| 190 |
response = await call_next(request)
|
| 191 |
|
| 192 |
# If MCP returns a session ID, store our API key for future requests
|
| 193 |
-
|
| 194 |
-
if
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 200 |
|
| 201 |
return response
|
| 202 |
finally:
|
|
@@ -204,6 +214,11 @@ async def thread_safe_auth_middleware(request: Request, call_next):
|
|
| 204 |
WandBApiManager.reset_context_api_key(token)
|
| 205 |
else:
|
| 206 |
# No API key available, let request through for MCP to handle
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 207 |
return await call_next(request)
|
| 208 |
|
| 209 |
except Exception as e:
|
|
@@ -248,8 +263,46 @@ async def logging_middleware(request, call_next):
|
|
| 248 |
|
| 249 |
# Log request details
|
| 250 |
logger.info(f"Incoming request: {request.method} {request.url.path}")
|
| 251 |
-
|
| 252 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 253 |
|
| 254 |
# Track if this is an MCP endpoint
|
| 255 |
is_mcp = request.url.path.startswith("/mcp") or request.url.path == "/"
|
|
|
|
| 147 |
api_key = None
|
| 148 |
|
| 149 |
# Check if request has MCP session ID (for established sessions)
|
| 150 |
+
session_id = request.headers.get("Mcp-Session-Id") or request.headers.get("mcp-session-id")
|
| 151 |
if session_id:
|
| 152 |
+
logger.info(f"Request has MCP Session ID: {session_id[:8]}...")
|
| 153 |
if session_id in session_api_keys:
|
| 154 |
# Use stored API key for this session
|
| 155 |
api_key = session_api_keys[session_id]
|
| 156 |
+
logger.info(f"Session found in storage, using stored API key")
|
| 157 |
else:
|
| 158 |
+
logger.warning(f"Session ID {session_id[:8]}... NOT found in storage!")
|
| 159 |
+
logger.info(f" Active sessions ({len(session_api_keys)}): {[sid[:8] for sid in session_api_keys.keys()]}")
|
| 160 |
+
# Don't fail here - the request might have its own Bearer token
|
| 161 |
|
| 162 |
# Check for Bearer token (for new sessions or explicit auth)
|
| 163 |
authorization = request.headers.get("Authorization", "")
|
|
|
|
| 177 |
if request.method == "DELETE" and session_id:
|
| 178 |
if session_id in session_api_keys:
|
| 179 |
del session_api_keys[session_id]
|
| 180 |
+
logger.info(f"Session cleanup: Deleted session {session_id[:8]}... (Remaining sessions: {len(session_api_keys)})")
|
| 181 |
+
else:
|
| 182 |
+
logger.warning(f"Session cleanup: Attempted to delete non-existent session {session_id[:8]}...")
|
| 183 |
return await call_next(request)
|
| 184 |
|
| 185 |
if api_key:
|
|
|
|
| 194 |
response = await call_next(request)
|
| 195 |
|
| 196 |
# If MCP returns a session ID, store our API key for future requests
|
| 197 |
+
response_session_id = response.headers.get("Mcp-Session-Id") or response.headers.get("mcp-session-id")
|
| 198 |
+
if response_session_id:
|
| 199 |
+
if api_key:
|
| 200 |
+
# Check if this session already exists
|
| 201 |
+
if response_session_id in session_api_keys:
|
| 202 |
+
logger.debug(f"Session {response_session_id[:8]}... already exists, updating API key")
|
| 203 |
+
else:
|
| 204 |
+
logger.info(f"New MCP session created: {response_session_id[:8]}...")
|
| 205 |
+
session_api_keys[response_session_id] = api_key
|
| 206 |
+
logger.info(f"Session storage updated. Total sessions: {len(session_api_keys)}")
|
| 207 |
+
logger.debug(f" Active session IDs: {[sid[:8] for sid in session_api_keys.keys()]}")
|
| 208 |
+
else:
|
| 209 |
+
logger.warning(f"Session created but no API key to store: {response_session_id[:8]}...")
|
| 210 |
|
| 211 |
return response
|
| 212 |
finally:
|
|
|
|
| 214 |
WandBApiManager.reset_context_api_key(token)
|
| 215 |
else:
|
| 216 |
# No API key available, let request through for MCP to handle
|
| 217 |
+
logger.warning(f"No API key available for request to {request.url.path}")
|
| 218 |
+
logger.info(f" Session ID present: {bool(session_id)} ({session_id[:8] if session_id else 'None'}...)")
|
| 219 |
+
logger.info(f" Bearer token present: {bool(authorization.startswith('Bearer '))}")
|
| 220 |
+
logger.info(f" Request method: {request.method}")
|
| 221 |
+
logger.info(" Allowing request through for MCP to handle (may result in 401/404)")
|
| 222 |
return await call_next(request)
|
| 223 |
|
| 224 |
except Exception as e:
|
|
|
|
| 263 |
|
| 264 |
# Log request details
|
| 265 |
logger.info(f"Incoming request: {request.method} {request.url.path}")
|
| 266 |
+
|
| 267 |
+
# Log MCP-specific headers
|
| 268 |
+
mcp_session_id = request.headers.get("mcp-session-id")
|
| 269 |
+
if mcp_session_id:
|
| 270 |
+
logger.info(f" MCP Session ID in request: {mcp_session_id[:8]}...")
|
| 271 |
+
|
| 272 |
+
# Try to log request body for POST requests
|
| 273 |
+
if request.method == "POST" and request.url.path in ["/mcp", "/"]:
|
| 274 |
+
try:
|
| 275 |
+
# Clone the request body so we can read it
|
| 276 |
+
body_bytes = await request.body()
|
| 277 |
+
if body_bytes:
|
| 278 |
+
import json
|
| 279 |
+
try:
|
| 280 |
+
body_json = json.loads(body_bytes)
|
| 281 |
+
method = body_json.get("method", "unknown")
|
| 282 |
+
request_id = body_json.get("id", "unknown")
|
| 283 |
+
logger.info(f" JSON-RPC request: method={method}, id={request_id}")
|
| 284 |
+
if method == "tools/call":
|
| 285 |
+
tool_name = body_json.get("params", {}).get("name", "unknown")
|
| 286 |
+
logger.info(f" Tool call request for: {tool_name}")
|
| 287 |
+
except json.JSONDecodeError:
|
| 288 |
+
logger.debug(f" Request body (non-JSON): {body_bytes[:100]}")
|
| 289 |
+
|
| 290 |
+
# Reconstruct the request with the body we read
|
| 291 |
+
from starlette.datastructures import Headers
|
| 292 |
+
from starlette.requests import Request as StarletteRequest
|
| 293 |
+
|
| 294 |
+
# Create a new request with the body we read
|
| 295 |
+
scope = request.scope
|
| 296 |
+
scope["body"] = body_bytes
|
| 297 |
+
|
| 298 |
+
async def receive():
|
| 299 |
+
return {"type": "http.request", "body": body_bytes}
|
| 300 |
+
|
| 301 |
+
request = StarletteRequest(scope, receive)
|
| 302 |
+
else:
|
| 303 |
+
logger.debug(" No request body")
|
| 304 |
+
except Exception as e:
|
| 305 |
+
logger.debug(f" Could not read request body: {e}")
|
| 306 |
|
| 307 |
# Track if this is an MCP endpoint
|
| 308 |
is_mcp = request.url.path.startswith("/mcp") or request.url.path == "/"
|