What Kind of Analytics Does FreeLLMAPI Collect? Complete Data Collection Guide
FreeLLMAPI collects comprehensive usage analytics across nine dimensions—summary metrics, per-model/per-platform/per-client breakdowns, API key tracking, timelines, error distributions, and individual request details—all exposed through REST endpoints in the analyticsRouter.
FreeLLMAPI is an open-source LLM proxy and routing layer that transparently records every aspect of proxied requests. Understanding what analytics FreeLLMAPI collects helps operators monitor costs, debug failures, and optimize model selection. This guide examines the complete analytics surface based on the source implementation in server/src/routes/analytics.ts.
Core Analytics Categories
All analytics endpoints are read-only aggregations from the requests table (raw rows) and request_hourly table (durable aggregates). Data retention is governed by REQUEST_ANALYTICS_MAX_ROWS and configurable time windows.
Overall Usage Summary
The GET /api/analytics/summary endpoint provides high-level operational visibility:
- Total requests and success rate (success ÷ (error + success))
- Token volume: input and output totals
- Latency percentiles: average, p50, p95, and time-to-first-token (TTFB)
- Estimated cost savings compared to paid-model pricing
- Routing behavior: pinned vs. auto-routed request counts and pin-honor rate
In server/src/routes/analytics.ts (lines 85-106), the summary aggregates across the request_hourly table with fallback pricing from server/src/db/model-pricing.ts. Lines 124-136 specifically compute pin-related metrics by analyzing the pinned flag and whether the honored provider matched the pin request.
Per-Model Analytics
The GET /api/analytics/by-model endpoint breaks down usage by the (platform, endpoint, model_id) tuple:
- Request count and success rate per model
- Average latency and token totals (input/output)
- Pin request counts and cost estimates
As implemented in server/src/routes/analytics.ts (lines 13-30), this uses provider_identity.ts utilities to generate stable display names for grouping. Custom endpoints are distinguished by their base URL.
Per-Platform Analytics
The GET /api/analytics/by-platform endpoint (lines 78-113) aggregates by provider platform:
- Request count, success rate, average latency, p95 latency, average TTFB
- Error count and average tokens-per-second throughput
- Input and output token totals
Platforms include built-in providers (OpenAI, Anthropic, Ollama, etc.) and custom endpoints, each split by base URL for granular tracking.
Per-Client Analytics
The GET /api/analytics/by-client endpoint (lines 64-82) groups by client_agent identifier:
- Total requests and success rate per client
- Token volume and average latency
- Last-seen timestamp for activity tracking
This distinguishes browser sessions, CLI tools, or custom integrations based on the client_agent field passed during request logging.
Per-API-Key Analytics
The GET /api/analytics/by-key endpoint (lines 93-111) tracks usage per stored API key:
- Request count, success rate, and latency per key
- Token totals with key label and platform when available
The aggregation includes deleted keys to preserve historical attribution while indicating their deprecated status.
Time-Series Timeline
The GET /api/analytics/timeline endpoint (lines 334-348) exposes hourly or daily time-series for visualization:
- Request volume over time
- Success and failure counts
- Token flow (input/output)
The interval parameter accepts hour or day bucketing.
Error Analysis
Two endpoints focus on failure patterns:
| Endpoint | Purpose | Implementation |
|---|---|---|
GET /api/analytics/error-distribution |
Errors grouped by category (rate-limited, auth, timeout, etc.) and platform | Lines 80-108 |
GET /api/analytics/errors |
List of latest errors (up to 50) with endpoint, model, and message | Lines 60-71 |
Error categories are derived from HTTP status codes and provider-specific error classification during request logging in server/src/lib/request-log.ts.
Request Inspection
For operational forensics:
GET /api/analytics/requests: Paginated recent calls with 7-day default window, filterable by status, provider, or platform (lines 94-124)GET /api/analytics/requests/:id: Full per-request payload including failover ladder (sequential attempts) and redacted error summaries (lines 156-176)
The failover ladder exposes the routing decisions that led to the final provider selection—critical for debugging auto-routing behavior.
How to Query Analytics Programmatically
Fetch Summary Metrics
import fetch from 'node-fetch';
async function getSummary(range = '7d') {
const resp = await fetch(`http://localhost:3000/api/analytics/summary?range=${range}`);
const data = await resp.json();
console.log('Total requests:', data.totalRequests);
console.log('Success rate (%):', data.successRate);
console.log('Avg latency (ms):', data.avgLatencyMs);
}
getSummary('24h');
Retrieve Per-Model Breakdown
async function getByModel() {
const resp = await fetch('http://localhost:3000/api/analytics/by-model?range=24h');
const models = await resp.json();
models.forEach(m => {
console.log(`${m.providerId} – ${m.displayName}: ${m.requests} req, ${m.successRate}% success`);
});
}
getByModel();
Build a Usage Timeline
async function drawTimeline() {
const r = await fetch('http://localhost:3000/api/analytics/timeline?range=30d&interval=day');
const points = await r.json(); // [{timestamp, requests, ...}, …]
// Example: output for external plotting
console.log(points.map(p => `${p.timestamp}: ${p.requests} requests, ${p.errors} errors`));
}
drawTimeline();
Filter Errors by Provider
async function recentErrors(providerId: string) {
const url = new URL('http://localhost:3000/api/analytics/errors');
url.searchParams.set('range', '24h');
const resp = await fetch(url);
const { detailed } = await resp.json();
const filtered = detailed.filter(e => e.providerId === providerId);
console.table(filtered.map(e => ({
id: e.id,
error: e.error,
createdAt: e.createdAt
})));
}
recentErrors('custom:my-local-ollama');
Data Storage and Retention Architecture
| Component | Purpose | Schema |
|---|---|---|
requests table |
Raw request rows | Individual request metadata, payloads, timing |
request_hourly table/ view |
Durable aggregates | Pre-computed totals by hour for fast queries |
REQUEST_ANALYTICS_MAX_ROWS env |
Retention limit | Prunes oldest raw rows while preserving aggregates |
According to the analyticsRouter implementation in server/src/routes/analytics.ts, all endpoints query request_hourly for historical ranges while requests serves recent-detail and per-request lookups.
Summary
- Nine analytics dimensions: summary, model, platform, client, API key, timeline, error distribution, recent errors, and individual requests
- All metrics computed server-side in
analytics.tswith no client-side telemetry - Read-only REST API with consistent
?range=parameter (e.g.,24h,7d,30d) - Failover ladder visibility uniquely exposes routing decision chains
- Cost estimation based on
model-pricing.tsfallback rates - Configurable retention via environment variables without aggregate loss
Frequently Asked Questions
Does FreeLLMAPI collect any client-side telemetry?
No. All analytics are server-side aggregations from proxied requests. The client_agent field is explicitly passed by the caller during API requests, not inferred from browser headers or external tracking.
How accurate is the cost savings calculation?
The estimated savings compare actual token usage against reference pricing from server/src/db/model-pricing.ts. These are approximate: they use fallback rates when provider-specific pricing is unavailable and don't account for negotiated enterprise discounts or regional pricing variations.
Can I export analytics data for external BI tools?
Yes. All endpoints return JSON and support standard HTTP clients. The timeline endpoint with interval=day is particularly suited for ETL pipelines. For direct database access, query the request_hourly SQLite table which holds pre-aggregated, retention-safe data.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →