Skip to main content
Glama
USAGE_TRACKING_FIX.md5.59 kB
# Usage Tracking Fix - Production Incident Resolution **Date:** 2025-10-14 **Status:** ✅ RESOLVED **Severity:** Medium ## Problem Usage tracking middleware was not recording metrics for MCP tool calls in production, despite API requests working correctly. ## Root Causes Identified ### 1. Path Mismatch - **Issue:** Middleware only tracked `/api/` paths - **Reality:** MCP tool calls use `/mcp` endpoint - **Impact:** No MCP requests were being tracked ### 2. Missing Environment Variables - **Issue:** Systemd service didn't load `.env` file - **Impact:** Supabase credentials unavailable, RPC calls failed silently - **Fix:** Added `EnvironmentFile=/opt/hostaway-mcp/.env` to service ### 3. Middleware Registration Order - **Issue:** UsageTrackingMiddleware registered AFTER MCPAuthMiddleware - **Reality:** Middleware executes in reverse registration order - **Impact:** Tracking ran before `organization_id` was set by auth - **Fix:** Moved UsageTrackingMiddleware registration BEFORE auth ### 4. Authentication Header Extraction - **Issue:** MCPAuthMiddleware passed Header object to `verify_api_key` - **Fix:** Manually extract header value: `request.headers.get("X-API-Key")` ## Fixes Applied ### 1. Updated Middleware Path Tracking **File:** `src/api/middleware/usage_tracking.py` ```python # Before: Only /api/* if not request.url.path.startswith("/api/"): return await call_next(request) # After: Both /api/* and /mcp path = request.url.path is_tracked = path.startswith("/api/") or path.startswith("/mcp") if not is_tracked: return await call_next(request) ``` ### 2. Enhanced Tool Name Extraction **File:** `src/api/middleware/usage_tracking.py` ```python @staticmethod def _extract_tool_name(path: str) -> str: # Handle MCP endpoints specially if path.startswith("/mcp"): parts = path.strip("/").split("/") if len(parts) > 1: return parts[1] return "mcp_root" else: # API paths: /api/v1/resource_name/... parts = path.strip("/").split("/") if len(parts) >= 3: return parts[2] return "unknown" ``` ### 3. Fixed Middleware Order **File:** `src/api/main.py` ```python # Correct order: UsageTracking BEFORE Auth (so it runs AFTER) app.add_middleware(UsageTrackingMiddleware) app.add_middleware(MCPAuthMiddleware) ``` ### 4. Fixed Auth Middleware **File:** `src/api/main.py` ```python # Protect both MCP and API endpoints if request.url.path.startswith("/mcp") or request.url.path.startswith("/api/"): # Extract API key from header manually x_api_key = request.headers.get("X-API-Key") try: await verify_api_key(request, x_api_key) except Exception as e: return JSONResponse( status_code=401, content={"detail": str(e)}, headers={"WWW-Authenticate": "ApiKey"}, ) ``` ### 5. Updated Systemd Service **File:** `/etc/systemd/system/hostaway-mcp.service` ```ini [Service] EnvironmentFile=/opt/hostaway-mcp/.env # ← Added this line ``` ### 6. Added Debug Logging **File:** `src/api/middleware/usage_tracking.py` ```python # File-based logging for production debugging import logging file_handler = logging.FileHandler('/tmp/usage_tracking.log') logger = logging.getLogger('usage_tracking') logger.addHandler(file_handler) logger.info(f"Tracking usage for org {organization_id}, path: {path}") ``` ## Verification ### Database Metrics ```sql SELECT * FROM usage_metrics WHERE month_year = '2025-10'; ``` **Results:** - Organization ID: 1 - Total Requests: 5 - Unique Tools: ['test_listings', 'unknown', '400569', 'revenue'] - Last Updated: 2025-10-15T03:09:56.884913+00:00 ### Test Commands ```bash # Check service status systemctl status hostaway-mcp # View tracking logs tail -f /tmp/usage_tracking.log # Query database psql -c "SELECT * FROM usage_metrics WHERE organization_id = 1;" ``` ## Deployment Steps (For Future Reference) 1. **Update code on server:** ```bash cd /opt/hostaway-mcp tar -xzf hostaway-mcp-deploy.tar.gz ``` 2. **Update systemd service:** ```bash vi /etc/systemd/system/hostaway-mcp.service # Add: EnvironmentFile=/opt/hostaway-mcp/.env systemctl daemon-reload ``` 3. **Restart service:** ```bash systemctl restart hostaway-mcp ``` 4. **Verify tracking:** ```bash # Make test request curl -H "X-API-Key: YOUR_KEY" http://localhost:8080/api/v1/listings # Check logs tail /tmp/usage_tracking.log # Check database # (Query shown above) ``` ## Lessons Learned 1. **Middleware order matters:** FastAPI/Starlette executes middleware in reverse registration order 2. **Environment loading:** Systemd services need explicit `EnvironmentFile` directive 3. **Path assumptions:** Don't assume all API traffic uses `/api/` prefix 4. **Silent failures:** Try/except blocks should log to files in production, not just stdout 5. **Header extraction:** Dependency injection doesn't work in middleware - extract manually ## Future Improvements 1. **Better tool name extraction:** Current logic shows some "unknown" and numeric values 2. **Metrics aggregation:** Consider hourly/daily rollups for performance 3. **Alerting:** Add monitoring for when tracking fails 4. **Testing:** Add integration tests for middleware execution order ## Related Files - `src/api/middleware/usage_tracking.py` - Main tracking logic - `src/api/main.py` - Middleware registration and auth - `/etc/systemd/system/hostaway-mcp.service` - Service configuration - `supabase/migrations/20251013000004_functions.sql` - RPC function

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/darrentmorgan/hostaway-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server