fastapi_endpoint_tracking_with_mongodb

A guide for recording FastAPI endpoint activity in MongoDB, a document database, and querying the stored data for analytics.

In plain words
What is it for?
Use it when implementing endpoint tracking services, integrating tracking into routes, configuring MongoDB, or adding tracking reports.
Why use it?
It explains how to add tracking, persistent storage, indexes, and an analytics endpoint to a FastAPI application.

Cursor rule

Install

Getting it into your agent

One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.

agentmods
npx agentmods add rules/jondoescoding/jondoescoding-coding-rules/fastapi_endpoint_tracking_with_mongodb
Clone the repo
git clone --depth 1 https://github.com/jondoescoding/jondoescoding-coding-rules
Per session 14 Only the description is in the session, so the agent can decide to use it. The body loads when it is invoked.
When invoked 3,249 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 1 finding. Scan, not verified.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5 $0.00014 $0.03249
Opus 5 $0.00007 $0.01625
Sonnet 5 $0.00003 $0.00650
Haiku 4.5 $0.00001 $0.00325

Measured yesterday against content hash ef1d33dbeb38, method: parsed. Prices are Anthropic first-party input rates as of 2026-08-30, from the pricing page.

Security

Grade A, and why

fastapi_endpoint_tracking_with_mongodb scanned grade A with 1 finding against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured yesterday.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Makes network callslowCapability

Not a fault in itself. Listed so you know the mod talks to something, and to what.

curl -X POST "http://localhost:8000/api/v0/your-endpoint" \
templates/cursor-rules/python/fast-api/fastapi_endpoint_tracking_with_mongodb.mdc · 499 lines

How it starts

The opening of the file, as written. The whole thing — 499 lines — stays where its author put it; the contents beside it link to each section on GitHub.

FastAPI MongoDB Endpoint Tracking Implementation Guide

This rule provides a comprehensive guide for implementing endpoint tracking in FastAPI applications with MongoDB storage, analytics, and performance monitoring.

🏗️ Architecture Overview

The tracking system consists of:

  1. Tracking Service - Core service that handles MongoDB operations
  2. Endpoint Integration - Direct service calls in FastAPI endpoints
  3. Analytics Endpoint - Query and aggregation interface
  4. MongoDB Storage - Persistent storage with optimized indexes

📁 File Structure

backend/src/
├── services/
│   └── endpoint_tracking_service.py  # Core tracking service
├── api/v0/
│   ├── your_router.py                # Endpoints with tracking integration
└── utils/
    └── config.py                     # MongoDB configuration

🔧 Implementation Steps

Step 1: Configuration Setup

Add MongoDB tracking configuration to config.py:

class Settings(BaseSettings):
    # MongoDB Configuration (for endpoint tracking)
    MONGODB_CONNECTION_STRING: str = "your_mongodb_connection_string"
    MONGODB_DATABASE_NAME: str = "your_database_name"
    
    # Endpoint tracking configuration
    MONGODB_TRACKING_COLLECTION: str = "fastapi_tracking"
    MONGODB_MAX_POOL_SIZE: int = 100
    MONGODB_MIN_POOL_SIZE: int = 10
    MONGODB_MAX_IDLE_TIME_MS: int = 30000

Step 2: Create Tracking Service

Create endpoint_tracking_service.py:

import time
from datetime import datetime, timezone, timedelta
from typing import Dict, Any, Optional
from pymongo import MongoClient
from fastapi import Request, Response
import json

from utils.config import get_settings
from utils.logger import get_logger

logger = get_logger(__name__)

class EndpointTrackingService:
    """Service for tracking endpoint usage and storing analytics in MongoDB."""
    
    def __init__(self):
        self.settings = get_settings()
        self._init_database()
        
    def _init_database(self):
        """Initialize MongoDB connection for endpoint tracking"""
        logger.info("Initializing MongoDB connection for endpoint tracking...")
        
        try:
            self.mongo_client = MongoClient(
                self.settings.MONGODB_CONNECTION_STRING,
                maxPoolSize=self.settings.MONGODB_MAX_POOL_SIZE,
                minPoolSize=self.settings.MONGODB_MIN_POOL_SIZE,
                maxIdleTimeMS=self.settings.MONGODB_MAX_IDLE_TIME_MS
            )
            self.mongo_db = self.mongo_client[self.settings.MONGODB_DATABASE_NAME]
            self.tracking_collection = self.mongo_db[self.settings.MONGODB_TRACKING_COLLECTION]
            
            # Create indexes for better query performance
            self._create_indexes()
            
            logger.info("✅ MongoDB endpoint tracking connection established")
        except Exception as e:
            logger.error(f"❌ Failed to connect to MongoDB for endpoint tracking: {e}")
            raise
    
    def _create_indexes(self):
        """Create indexes for optimized querying"""
        try:
            # Check existing indexes first to avoid conflicts
            existing_indexes = list(self.tracking_collection.list_indexes())
            existing_index_names = [idx.get('name', '') for idx in existing_indexes]
            
            # Index on endpoint and timestamp for time-series queries
            if 'endpoint_1_timestamp_-1' not in existing_index_names:
                self.tracking_collection.create_index([
                    ("endpoint", 1),
                    ("timestamp", -1)
                ], name='endpoint_1_timestamp_-1')
            
            # Index on status_code for error tracking
            if 'status_code_1' not in existing_index_names:
                self.tracking_collection.create_index("status_code", name='status_code_1')
            
            # Index on response_time for performance monitoring
            if 'response_time_1' not in existing_index_names:
                self.tracking_collection.create_index("response_time", name='response_time_1')
            
            logger.info("✅ MongoDB indexes created/verified for endpoint tracking")
        except Exception as e:
            logger.warning(f"Failed to create indexes: {e}")

    async def track_request(
        self,
        request: Request,
        response: Response,
        endpoint_name: str,
        custom_data: Dict[str, Any],
        start_time: float
    ) -> None:
        """
        Generic method to track any endpoint request
        
        Args:
            request: FastAPI request object
            response: FastAPI response object
            endpoint_name: Name/path of the endpoint
            custom_data: Endpoint-specific data to track
            start_time: Request start timestamp
        """
        try:
            end_time = time.time()
            response_time = end_time - start_time
            
            # Base tracking data structure
            tracking_data = {
                # Basic request metadata
                "endpoint": endpoint_name,
                "method": request.method,
                "timestamp": datetime.now(timezone.utc),
                "response_time": response_time,
                "status_code": response.status_code,
                
                # Request details
                "user_agent": request.headers.get("user-agent"),
                "client_ip": self._get_client_ip(request),
                "query_params": dict(request.query_params),
                
                # Custom endpoint-specific data
                "custom_data": custom_data,
                
                # Environment info
                "environment": self.settings.ENVIRONMENT,
            }
            
            # Insert into MongoDB
            result = self.tracking_collection.insert_one(tracking_data)
            logger.info(f"📊 Request tracked for {endpoint_name}: {result.inserted_id}")
            
        except Exception as e:
            logger.error(f"Failed to track request for {endpoint_name}: {e}")
    
    def _get_client_ip(self, request: Request) -> str:
        """Extract client IP address from request headers"""
        # Check for forwarded IP headers (common in production)
        forwarded_for = request.headers.get("x-forwarded-for")
        if forwarded_for:
            return forwarded_for.split(",")[0].strip()
        
        real_ip = request.headers.get("x-real-ip")
        if real_ip:
            return real_ip
        
        # Fallback to direct client IP
        return getattr(request.client, "host", "unknown")

    async def get_endpoint_analytics(
        self,
        endpoint: Optional[str] = None,
        hours: int = 24
    ) -> Dict[str, Any]:
        """
        Get analytics for tracked endpoints
        
        Args:
            endpoint: Specific endpoint to analyze (optional)
            hours: Number of hours to look back
            
        Returns:
            Analytics data including request counts, response times, etc.
        """
        try:
            # Calculate time range
            end_time = datetime.now(timezone.utc)
            start_time = end_time - timedelta(hours=hours)
            
            # Build query
            query = {
                "timestamp": {
                    "$gte": start_time,
                    "$lte": end_time
                }
            }
            
            if endpoint:
                query["endpoint"] = endpoint
            
            # Get aggregated data
            pipeline = [
                {"$match": query},
                {"$group": {
                    "_id": "$endpoint",
                    "request_count": {"$sum": 1},
                    "avg_response_time": {"$avg": "$response_time"},
                    "max_response_time": {"$max": "$response_time"},
                    "min_response_time": {"$min": "$response_time"},
                    "error_count": {
                        "$sum": {
                            "$cond": [{"$gte": ["$status_code", 400]}, 1, 0]
                        }
                    }
                }}
            ]
            
            results = list(self.tracking_collection.aggregate(pipeline))
            
            return {
                "time_range": {
                    "start": start_time.isoformat(),
                    "end": end_time.isoformat(),
                    "hours": hours
                },
                "analytics": results
            }
            
        except Exception as e:
            logger.error(f"Failed to get endpoint analytics: {e}")
            return {"error": str(e)}

# Create singleton instance
endpoint_tracking_service = EndpointTrackingService()

Read the full file on GitHub · 499 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. yesterday First seen · 499 lines · 14 tokens per session scan A ef1d33dbeb38

Subscribe to this mod's changes

fastapi_endpoint_tracking_with_mongodb is a cursor rule published in the GitHub repository jondoescoding/jondoescoding-coding-rules (2 stars, last pushed 1mo ago), licensed MIT. It adds 14 tokens to every session and 3,249 once invoked, about $0.0001 per session on Opus 5. A static security scan graded it A with 1 finding (makes network calls). No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.