librechat-analytics/public/index.html
DJP 65824fc3b3 Initial commit: LibreChat Analytics Dashboard
Express.js + Chart.js dashboard for LibreChat usage analytics.
Queries MongoDB transactions collection for model/agent usage, costs, and top users.
Dark theme with Montserrat font, black/gold (#FFC407) color scheme.
Docker-ready with API key authentication.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 16:48:40 -04:00

178 lines
6.4 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LibreChat Analytics</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="css/style.css">
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.7/dist/chart.umd.min.js"></script>
<script src="https://unpkg.com/lucide@latest"></script>
</head>
<body>
<div id="app">
<!-- Sidebar -->
<nav class="sidebar">
<div class="sidebar-header">
<svg class="logo-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 12V7H5a2 2 0 0 1 0-4h14v4"/>
<path d="M3 5v14a2 2 0 0 0 2 2h16v-5"/>
<path d="M18 12a2 2 0 0 0 0 4h4v-4Z"/>
</svg>
<span class="logo-text">Analytics</span>
</div>
<ul class="nav-links">
<li class="active" data-tab="overview">
<i data-lucide="bar-chart-3" style="width:20px;height:20px"></i>
Overview
</li>
<li data-tab="users">
<i data-lucide="users" style="width:20px;height:20px"></i>
Users
</li>
<li data-tab="models">
<i data-lucide="cpu" style="width:20px;height:20px"></i>
Models
</li>
<li data-tab="agents">
<i data-lucide="bot" style="width:20px;height:20px"></i>
Agents
</li>
</ul>
<div class="sidebar-footer">
Auto-refresh: 60s
</div>
</nav>
<!-- Main Content -->
<main class="content">
<div class="top-bar">
<h1>LibreChat Analytics</h1>
</div>
<!-- Filter Bar -->
<div class="filter-bar">
<div class="period-selector">
<button class="period-btn active" data-period="24h">24H</button>
<button class="period-btn" data-period="7d">7D</button>
<button class="period-btn" data-period="30d">30D</button>
<button class="period-btn" data-period="custom">Custom</button>
</div>
<div class="date-range-picker" id="dateRangePicker" style="display:none">
<input type="date" id="startDate">
<span class="date-separator">to</span>
<input type="date" id="endDate">
</div>
<span class="refresh-info" id="lastRefresh"></span>
</div>
<!-- Overview Tab -->
<div class="tab-content active" id="tab-overview">
<div class="stats-grid" id="summaryCards">
<div class="stat-card">
<div class="stat-icon cost"><i data-lucide="dollar-sign"></i></div>
<div><span class="stat-label">Total Cost</span><span class="stat-value" id="totalCost">--</span></div>
</div>
<div class="stat-card">
<div class="stat-icon tokens"><i data-lucide="zap"></i></div>
<div><span class="stat-label">Total Tokens</span><span class="stat-value" id="totalTokens">--</span></div>
</div>
<div class="stat-card">
<div class="stat-icon users"><i data-lucide="users"></i></div>
<div><span class="stat-label">Active Users</span><span class="stat-value" id="activeUsers">--</span></div>
</div>
<div class="stat-card">
<div class="stat-icon convos"><i data-lucide="message-square"></i></div>
<div><span class="stat-label">Conversations</span><span class="stat-value" id="conversations">--</span></div>
</div>
</div>
<div class="charts-grid">
<div class="chart-container chart-wide">
<h3>Usage Over Time</h3>
<canvas id="usageChart"></canvas>
</div>
<div class="chart-container">
<h3>Cost by Model</h3>
<canvas id="costByModelChart"></canvas>
</div>
<div class="chart-container">
<h3>Cost Breakdown (Input vs Output)</h3>
<canvas id="costBreakdownChart"></canvas>
</div>
</div>
</div>
<!-- Users Tab -->
<div class="tab-content" id="tab-users">
<div class="table-container">
<div class="table-header"><h3>Top Users by Cost</h3></div>
<table>
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Email</th>
<th class="text-right">Tokens</th>
<th class="text-right">Cost</th>
<th class="text-right">Conversations</th>
</tr>
</thead>
<tbody id="usersTableBody"></tbody>
</table>
</div>
</div>
<!-- Models Tab -->
<div class="tab-content" id="tab-models">
<div class="table-container">
<div class="table-header"><h3>Top Models by Cost</h3></div>
<table>
<thead>
<tr>
<th>#</th>
<th>Model</th>
<th class="text-right">Prompt Tokens</th>
<th class="text-right">Completion Tokens</th>
<th class="text-right">Prompt Cost</th>
<th class="text-right">Completion Cost</th>
<th class="text-right">Total Cost</th>
</tr>
</thead>
<tbody id="modelsTableBody"></tbody>
</table>
</div>
<div class="charts-grid">
<div class="chart-container chart-wide">
<h3>Model Cost Comparison (Input vs Output)</h3>
<canvas id="modelCostChart"></canvas>
</div>
</div>
</div>
<!-- Agents Tab -->
<div class="tab-content" id="tab-agents">
<div class="table-container">
<div class="table-header"><h3>Top Agents by Cost</h3></div>
<table>
<thead>
<tr>
<th>#</th>
<th>Agent Name</th>
<th>Underlying Model</th>
<th>Provider</th>
<th class="text-right">Tokens</th>
<th class="text-right">Cost</th>
<th class="text-right">Conversations</th>
</tr>
</thead>
<tbody id="agentsTableBody"></tbody>
</table>
</div>
</div>
</main>
</div>
<script src="js/app.js"></script>
</body>
</html>