No description
Find a file
DJP 31358a8b86 fix: Repair Top Agents tab after LibreChat transaction shape change
LibreChat stopped tagging agent transactions with model: agent_xxx around
2026-03; new agent transactions record the underlying LLM and link to the
message via messageId. Aggregate from messages -> transactions and union
with the legacy path so historical and current data both show.

Also create createdAt / messageId / (createdAt, model) indexes on startup.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 17:08:26 -04:00
config Initial commit: LibreChat Analytics Dashboard 2026-03-11 16:48:40 -04:00
docs docs: Add migration guide for moving LibreChat install to /opt 2026-03-13 11:24:32 -04:00
public feat: Add User Lookup tab with search and full user workup 2026-03-20 15:09:43 -04:00
routes feat: Add User Lookup tab with search and full user workup 2026-03-20 15:09:43 -04:00
services fix: Repair Top Agents tab after LibreChat transaction shape change 2026-04-28 17:08:26 -04:00
.dockerignore Initial commit: LibreChat Analytics Dashboard 2026-03-11 16:48:40 -04:00
.env.example Initial commit: LibreChat Analytics Dashboard 2026-03-11 16:48:40 -04:00
.gitignore Initial commit: LibreChat Analytics Dashboard 2026-03-11 16:48:40 -04:00
docker-compose.yml fix: Add librechat_default as external network in docker-compose 2026-03-11 17:13:10 -04:00
Dockerfile Initial commit: LibreChat Analytics Dashboard 2026-03-11 16:48:40 -04:00
package-lock.json Initial commit: LibreChat Analytics Dashboard 2026-03-11 16:48:40 -04:00
package.json Initial commit: LibreChat Analytics Dashboard 2026-03-11 16:48:40 -04:00
README.md docs: Add ASCII architecture and data flow diagrams 2026-03-11 19:44:20 -04:00
server.js fix: Repair Top Agents tab after LibreChat transaction shape change 2026-04-28 17:08:26 -04:00

LibreChat Analytics Dashboard

Usage analytics dashboard for LibreChat. Queries the existing MongoDB to show model/agent usage, costs, and top users with time filtering.

Features

  • Overview — Total cost, tokens, active users, conversations with time-series charts
  • Users — Top users ranked by cost with token and conversation counts
  • Models — Model breakdown with prompt/completion token and cost split
  • Agents — Agent usage with underlying model resolution
  • Time Filtering — 24H, 7D, 30D, or custom date range
  • Auto-refresh — Updates every 60 seconds
  • API Key Auth — Dashboard protected by API key (prompted on first visit)

Prerequisites

  • Docker and Docker Compose
  • LibreChat already running with MongoDB
  • Access to LibreChat's nginx config (for proxy setup)

Installation

1. Clone the repo

cd /opt
git clone https://x-token-auth:{ACCESS_TOKEN}@bitbucket.org/zlalani/librechat-analytics.git
cd librechat-analytics

Or with SSH:

git clone git@bitbucket.org:zlalani/librechat-analytics.git

2. Configure environment

cp .env.example .env
nano .env

Set the following values:

MONGO_URI=mongodb://mongodb:27017/LibreChat
DASHBOARD_API_KEY=your-secure-key-here
PORT=3001

Important:

  • Change DASHBOARD_API_KEY to a secure value. This is required to access the dashboard.
  • Do NOT use & or other special characters in the API key (breaks URL parsing).
  • mongodb in the URI is the container name of LibreChat's MongoDB — change if yours is different.

3. Build and run

docker compose up -d --build

The container automatically joins LibreChat's Docker network (librechat_default) so it can reach MongoDB. If your LibreChat network has a different name, edit docker-compose.yml and change the name: under the librechat network.

4. Configure Nginx

Edit LibreChat's nginx config to proxy the dashboard. The nginx config location depends on your setup:

  • Standard deploy: /home/<user>/LibreChat/client/nginx.conf
  • Alternate location: /opt/LibreChat/client/nginx.conf

Add this location block before the location /api block:

location /librechat-analytics/ {
    proxy_pass http://librechat-analytics:3001/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

Then reload nginx:

docker exec LibreChat-NGINX nginx -s reload

5. Verify

# Health check (no auth required)
curl http://localhost:3001/health

# Test API (requires API key)
curl -H "x-api-key: your-secure-key-here" 'http://localhost:3001/api/summary?period=30d'

6. Access the dashboard

Open https://your-domain/librechat-analytics/ in your browser.

On first visit you'll be prompted to enter the API key. It gets saved in your browser's localStorage so you only need to enter it once.

Updating

cd /opt/librechat-analytics
git pull
docker compose up -d --build

No need to reconfigure nginx or re-enter the API key after updates.

Ports

Service Port Notes
Analytics Dashboard 3001 Bound to 127.0.0.1 only (not exposed externally)
LibreChat 3080 No conflict
Code Interpreter 8000/8005 No conflict

The dashboard is only accessible externally through the nginx proxy.

Authentication

The dashboard is protected by an API key set in .env. When accessing the dashboard:

  1. Browser prompts for the API key on first visit
  2. Key is stored in browser localStorage
  3. All API requests include the key in the x-api-key header

To reset the key in your browser: open DevTools (F12) > Application > Local Storage > delete analyticsApiKey, then refresh.

Architecture

                         https://your-domain
                                |
                        +-------v--------+
                        |   Nginx Proxy  |
                        |  (LibreChat)   |
                        +---+-------+----+
                            |       |
               /api, /chat  |       |  /librechat-analytics/*
                            |       |
                    +-------v--+  +-v------------------+
                    | LibreChat |  | Analytics Dashboard |
                    |  :3080    |  |  :3001              |
                    +-------+---+  +---------+----------+
                            |                |
                            |   MongoDB      |
                            |   queries      |
                            |                |
                        +---v----------------v---+
                        |        MongoDB         |
                        |  (LibreChat database)  |
                        |                        |
                        |  collections:          |
                        |   - transactions       |
                        |   - users              |
                        |   - agents             |
                        +------------------------+
  User sends message in LibreChat
        |
        v
  +------------------+     +------------------+     +-------------------+
  | LibreChat calls  |---->| LLM processes    |---->| LibreChat records |
  | LLM API          |     | prompt + reply   |     | transaction       |
  | (Claude, GPT,    |     | returns tokens   |     | in MongoDB        |
  |  Gemini, etc.)   |     | used             |     |                   |
  +------------------+     +------------------+     +--------+----------+
                                                             |
                              Transaction record:            |
                              +----------------------------+ |
                              | user: ObjectId             |<+
                              | model: "claude-sonnet-4-6" |
                              | tokenType: "prompt"        |
                              | rawAmount: -15234          |
                              | tokenValue: -45.702        |
                              |   (rawAmount x $3/1M)      |
                              | createdAt: Date            |
                              +----------------------------+
                                                |
                                                v
                              +----------------------------+
                              | Analytics Dashboard reads  |
                              | tokenValue from MongoDB    |
                              |                            |
                              | cost = |tokenValue| / 1M  |
                              |      = 45.702 / 1000000   |
                              |      = $0.000046           |
                              +----------------------------+

Cost Calculation

How it works

The dashboard does not calculate costs itself. Costs come directly from LibreChat's MongoDB transactions collection, which records every API call.

When a user sends a message, LibreChat:

  1. Records the token usage in the transactions collection with fields like rawAmount (token count, stored as negative), tokenType (prompt or completion), and model
  2. Looks up the model's pricing from its internal pricing table (api/models/tx.js)
  3. Calculates tokenValue = rawAmount × rate where rate is USD per 1M tokens
  4. Stores tokenValue alongside the transaction

The dashboard reads tokenValue and converts to USD: cost = Math.abs(tokenValue) / 1,000,000

This means costs reflect the rate that was active at the time of the API call. If pricing changes, old transactions keep their original cost (which is correct — they were billed at the old rate).

Where pricing lives

The pricing table is in LibreChat's codebase at api/models/tx.js. It uses a longest-match pattern strategy — e.g. claude-sonnet-4-6 matches before the generic claude- fallback.

Agent transactions

When a user interacts with an Agent, LibreChat records model as agent_XYZ (the agent's ID). The dashboard resolves these to the underlying LLM model via the agents collection (cached, refreshed every 5 minutes).

Verified pricing (March 2026)

The following rates from LibreChat's tx.js have been validated against official provider pricing pages:

Anthropic Claude (source: platform.claude.com/docs/en/about-claude/pricing)

Model Input ($/1M tokens) Output ($/1M tokens) Verified
claude-opus-4-6 5.00 25.00 Yes
claude-sonnet-4-6 3.00 15.00 Yes
claude-sonnet-4 3.00 15.00 Yes
claude-opus-4-5 5.00 25.00 Yes
claude-opus-4 15.00 75.00 Yes
claude-haiku-4-5 1.00 5.00 Yes
claude-3-5-haiku 0.80 4.00 Yes
claude-3-opus 15.00 75.00 Yes
claude-3-haiku 0.25 1.25 Yes

OpenAI (source: openai.com/api/pricing)

Model Input ($/1M tokens) Output ($/1M tokens) Verified
gpt-4o 2.50 10.00 Yes
gpt-4o-mini 0.15 0.60 Yes
gpt-4.1 2.00 8.00 Yes
gpt-4.1-mini 0.40 1.60 Yes
gpt-4.1-nano 0.10 0.40 Yes
o1 15.00 60.00 Yes
o1-mini 1.10 4.40 Mismatch*
o3 2.00 8.00 Yes
o3-mini 1.10 4.40 Yes
o4-mini 1.10 4.40 Yes

*o1-mini: tx.js has $1.10/$4.40, current OpenAI pricing shows $3/$12. May reflect an older rate. Only affects you if using o1-mini.

Google Gemini (source: ai.google.dev/gemini-api/docs/pricing)

Model Input ($/1M tokens) Output ($/1M tokens) Verified
gemini-2.5-pro 1.25 10.00 Yes
gemini-2.5-flash 0.30 2.50 Yes
gemini-2.0-flash 0.10 0.40 Yes
gemini-2.0-flash-lite 0.075 0.30 Yes
gemini-1.5-flash 0.15 0.60 Deprecated

Note: Gemini 2.5 Pro has tiered pricing — prompts over 200K tokens cost $2.50/$15.00. tx.js uses the base tier which applies to most usage.

API Endpoints

All require x-api-key header. All accept ?period=24h|7d|30d|custom&start=ISO&end=ISO.

Endpoint Description
GET /health Health check (no auth)
GET /api/summary Total tokens, cost, users, conversations
GET /api/top-users?limit=10 Users ranked by cost
GET /api/top-models?limit=10 Models ranked by cost (resolves agent IDs to underlying LLM)
GET /api/top-agents?limit=10 Agents ranked by cost
GET /api/cost-breakdown Per-model input vs output cost split
GET /api/usage-over-time Time-series tokens and cost

Troubleshooting

No data showing:

  • Check the time period — try 30D if there's no recent usage
  • Check container logs: docker logs librechat-analytics --tail 20
  • Verify MongoDB connection: the health endpoint should return {"status":"ok"}

API key not prompting:

  • Clear localStorage: DevTools > Application > Local Storage > delete analyticsApiKey
  • Hard refresh: Ctrl+Shift+R

Container can't reach MongoDB:

  • Verify network: docker network inspect librechat_default — both mongodb and librechat-analytics should be listed
  • If LibreChat uses a different network name, update docker-compose.yml

Nginx 502 Bad Gateway:

  • Check the analytics container is running: docker ps | grep analytics
  • Check it's on the right network: docker network inspect librechat_default