WhoWhyWhen is an open source analytics platform that helps you track and understand your API usage. Built with FastAPI and Svelte, it provides comprehensive request tracking, bot detection, and performance monitoring for your APIs.
![]() |
![]() |
![]() |
![]() |
Backend:
Frontend:
Authentication:
Containerization:
Clone the repository:
git clone https://github.com/yourusername/whowhywhen.git
cd whowhywhen
Create a virtual environment and install dependencies:
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txt
Create a .env
file based on .env.example
:
cp .env.example .env
# Edit .env with your configuration
Run database migrations:
alembic upgrade head
Start the backend services:
uvicorn app.main_api:app --reload --port 8001
uvicorn app.main_dash:app --reload --port 8000
Navigate to the frontend directory:
cd who-why-when-landing-page
Install dependencies:
npm install
# or
yarn install
Start the development server:
npm run dev
# or
yarn dev
You can also run the entire application using Docker:
docker-compose up -d
The fastest way to get started is with Docker:
# Clone the repository
git clone https://github.com/navig-me/whowhywhen.git
cd whowhywhen
# Create and configure environment file
cp .env.example .env
# Edit .env with your settings
# Start the application
docker-compose up -d
Visit http://localhost:8000 to access the dashboard.
Add the WhoWhyWhen middleware to your application to start tracking API usage:
from fastapi import FastAPI, Request
from datetime import datetime
import httpx
app = FastAPI()
@app.middleware("http")
async def track_requests(request: Request, call_next):
# Record request start time
start_time = datetime.now()
# Process the request
response = await call_next(request)
# Calculate request duration
duration = (datetime.now() - start_time).total_seconds()
# Capture request details
data = {
"url": str(request.url),
"method": request.method,
"status_code": response.status_code,
"duration": duration,
"user_agent": request.headers.get("User-Agent"),
"ip_address": request.client.host,
}
# Send analytics to WhoWhyWhen asynchronously (non-blocking)
try:
async with httpx.AsyncClient(timeout=2.0) as client:
await client.post(
"http://your-whowhywhen-instance:8001/api/log",
headers={"X-API-KEY": "your-api-key"},
json=data
)
except Exception:
# Fail silently to avoid affecting the main application
pass
return response
const axios = require('axios');
function whowhywhenMiddleware(apiKey) {
return (req, res, next) => {
const startTime = Date.now();
// Store original end function
const originalEnd = res.end;
// Override end function to capture response details
res.end = function(...args) {
// Call original end function first
originalEnd.apply(res, args);
// Calculate duration
const duration = (Date.now() - startTime) / 1000;
// Send analytics (non-blocking)
axios.post('http://your-whowhywhen-instance:8001/api/log', {
url: req.originalUrl || req.url,
method: req.method,
status_code: res.statusCode,
duration: duration,
user_agent: req.headers['user-agent'] || '',
ip_address: req.ip || req.connection.remoteAddress
}, {
headers: { 'X-API-KEY': apiKey },
timeout: 2000
}).catch(() => {
// Fail silently
});
};
next();
};
}
// Add to your Express app
app.use(whowhywhenMiddleware('your-api-key'));
For more integration examples, see INTEGRATION.md.
Contributions are welcome! Here's how you can help:
Please see CONTRIBUTING.md for detailed contribution guidelines.
This project is licensed under the MIT License - see the LICENSE file for details.