fancy caching works now
This commit is contained in:
@@ -1,5 +1,18 @@
|
||||
'use client';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Bar } from 'react-chartjs-2';
|
||||
import {
|
||||
Chart as ChartJS,
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
BarElement,
|
||||
Title,
|
||||
Tooltip,
|
||||
Legend,
|
||||
ChartOptions,
|
||||
} from 'chart.js';
|
||||
|
||||
ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend);
|
||||
|
||||
interface PostStats {
|
||||
slug: string;
|
||||
@@ -13,6 +26,8 @@ export default function RustStatusPage() {
|
||||
const [stats, setStats] = useState<PostStats[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [autoRefresh, setAutoRefresh] = useState(false);
|
||||
const autoRefreshRef = React.useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
const fetchStats = async () => {
|
||||
setLoading(true);
|
||||
@@ -31,45 +46,156 @@ export default function RustStatusPage() {
|
||||
|
||||
React.useEffect(() => {
|
||||
fetchStats();
|
||||
const interval = setInterval(fetchStats, 5000);
|
||||
return () => clearInterval(interval);
|
||||
// Listen for post changes via BroadcastChannel
|
||||
let bc: BroadcastChannel | null = null;
|
||||
if (typeof window !== 'undefined' && 'BroadcastChannel' in window) {
|
||||
bc = new BroadcastChannel('posts-changed');
|
||||
bc.onmessage = (event) => {
|
||||
if (event.data === 'changed') {
|
||||
fetchStats();
|
||||
}
|
||||
};
|
||||
}
|
||||
return () => {
|
||||
if (bc) bc.close();
|
||||
if (autoRefreshRef.current) clearInterval(autoRefreshRef.current);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Handle auto-refresh toggle
|
||||
React.useEffect(() => {
|
||||
if (autoRefresh) {
|
||||
autoRefreshRef.current = setInterval(fetchStats, 2000);
|
||||
} else if (autoRefreshRef.current) {
|
||||
clearInterval(autoRefreshRef.current);
|
||||
autoRefreshRef.current = null;
|
||||
}
|
||||
return () => {
|
||||
if (autoRefreshRef.current) clearInterval(autoRefreshRef.current);
|
||||
};
|
||||
}, [autoRefresh]);
|
||||
|
||||
// Dashboard summary calculations
|
||||
const totalHits = stats.reduce((sum, s) => sum + s.cache_hits, 0);
|
||||
const totalMisses = stats.reduce((sum, s) => sum + s.cache_misses, 0);
|
||||
const avgInterpret = stats.length ? (stats.reduce((sum, s) => sum + s.last_interpret_time_ms, 0) / stats.length).toFixed(1) : 0;
|
||||
const avgCompile = stats.length ? (stats.reduce((sum, s) => sum + s.last_compile_time_ms, 0) / stats.length).toFixed(1) : 0;
|
||||
|
||||
// Chart data
|
||||
const chartData = {
|
||||
labels: stats.map(s => s.slug),
|
||||
datasets: [
|
||||
{
|
||||
label: 'Cache Hits',
|
||||
data: stats.map(s => s.cache_hits),
|
||||
backgroundColor: 'rgba(34,197,94,0.7)',
|
||||
},
|
||||
{
|
||||
label: 'Cache Misses',
|
||||
data: stats.map(s => s.cache_misses),
|
||||
backgroundColor: 'rgba(239,68,68,0.7)',
|
||||
},
|
||||
],
|
||||
};
|
||||
const chartOptions: ChartOptions<'bar'> = {
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: { position: 'top' },
|
||||
title: { display: true, text: 'Cache Hits & Misses per Post' },
|
||||
},
|
||||
scales: {
|
||||
x: { stacked: true },
|
||||
y: { stacked: true, beginAtZero: true },
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="p-8 max-w-4xl mx-auto">
|
||||
<h1 className="text-2xl font-bold mb-6">Rust Parser Status</h1>
|
||||
{loading && <div>Loading...</div>}
|
||||
{error && <div className="text-red-500">{error}</div>}
|
||||
{!loading && !error && (
|
||||
<div className="overflow-x-auto">
|
||||
<table className="min-w-full border border-gray-300 bg-white shadow-md rounded">
|
||||
<thead>
|
||||
<tr className="bg-gray-100">
|
||||
<th className="px-4 py-2 text-left">Slug</th>
|
||||
<th className="px-4 py-2 text-right">Cache Hits</th>
|
||||
<th className="px-4 py-2 text-right">Cache Misses</th>
|
||||
<th className="px-4 py-2 text-right">Last Interpret Time (ms)</th>
|
||||
<th className="px-4 py-2 text-right">Last Compile Time (ms)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{stats.length === 0 ? (
|
||||
<tr><td colSpan={5} className="text-center py-4">No stats available.</td></tr>
|
||||
) : (
|
||||
stats.map(stat => (
|
||||
<tr key={stat.slug} className="border-t">
|
||||
<td className="px-4 py-2 font-mono">{stat.slug}</td>
|
||||
<td className="px-4 py-2 text-right">{stat.cache_hits}</td>
|
||||
<td className="px-4 py-2 text-right">{stat.cache_misses}</td>
|
||||
<td className="px-4 py-2 text-right">{stat.last_interpret_time_ms}</td>
|
||||
<td className="px-4 py-2 text-right">{stat.last_compile_time_ms}</td>
|
||||
</tr>
|
||||
))
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="p-8 max-w-6xl mx-auto">
|
||||
<h1 className="text-3xl font-bold mb-8 text-center">Rust Parser Dashboard</h1>
|
||||
<div className="flex justify-end gap-4 mb-4">
|
||||
<button
|
||||
onClick={fetchStats}
|
||||
className="px-4 py-2 bg-blue-600 text-white rounded shadow hover:bg-blue-700"
|
||||
>
|
||||
Refresh
|
||||
</button>
|
||||
<label className="flex items-center gap-2 cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={autoRefresh}
|
||||
onChange={e => setAutoRefresh(e.target.checked)}
|
||||
className="form-checkbox"
|
||||
/>
|
||||
<span className="text-sm">Auto-refresh every 2s</span>
|
||||
</label>
|
||||
</div>
|
||||
{loading && (
|
||||
<div className="flex flex-col items-center justify-center h-64">
|
||||
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-gray-900 mb-4"></div>
|
||||
<div className="text-lg">Loading stats...</div>
|
||||
</div>
|
||||
)}
|
||||
{error && (
|
||||
<div className="text-red-500 text-center text-lg">{error}</div>
|
||||
)}
|
||||
{!loading && !error && (
|
||||
<>
|
||||
{/* Summary Cards */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
|
||||
<div className="bg-green-100 rounded-lg p-6 flex flex-col items-center shadow">
|
||||
<span className="text-2xl font-bold text-green-700">{totalHits}</span>
|
||||
<span className="text-gray-700 mt-2">Total Cache Hits</span>
|
||||
</div>
|
||||
<div className="bg-red-100 rounded-lg p-6 flex flex-col items-center shadow">
|
||||
<span className="text-2xl font-bold text-red-700">{totalMisses}</span>
|
||||
<span className="text-gray-700 mt-2">Total Cache Misses</span>
|
||||
</div>
|
||||
<div className="bg-blue-100 rounded-lg p-6 flex flex-col items-center shadow">
|
||||
<span className="text-2xl font-bold text-blue-700">{avgInterpret} ms</span>
|
||||
<span className="text-gray-700 mt-2">Avg Interpret Time</span>
|
||||
</div>
|
||||
<div className="bg-purple-100 rounded-lg p-6 flex flex-col items-center shadow">
|
||||
<span className="text-2xl font-bold text-purple-700">{avgCompile} ms</span>
|
||||
<span className="text-gray-700 mt-2">Avg Compile Time</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bar Chart */}
|
||||
<div className="bg-white rounded-lg shadow p-6 mb-10">
|
||||
<Bar data={chartData} options={chartOptions} height={120} />
|
||||
</div>
|
||||
|
||||
{/* Raw Data Table */}
|
||||
<div className="overflow-x-auto">
|
||||
<table className="min-w-full border border-gray-300 bg-white shadow-md rounded">
|
||||
<thead>
|
||||
<tr className="bg-gray-100">
|
||||
<th className="px-4 py-2 text-left">Slug</th>
|
||||
<th className="px-4 py-2 text-right">Cache Hits</th>
|
||||
<th className="px-4 py-2 text-right">Cache Misses</th>
|
||||
<th className="px-4 py-2 text-right">Last Interpret Time (ms)</th>
|
||||
<th className="px-4 py-2 text-right">Last Compile Time (ms)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{stats.length === 0 ? (
|
||||
<tr><td colSpan={5} className="text-center py-4">No stats available.</td></tr>
|
||||
) : (
|
||||
stats.map(stat => (
|
||||
<tr key={stat.slug} className="border-t">
|
||||
<td className="px-4 py-2 font-mono">{stat.slug}</td>
|
||||
<td className="px-4 py-2 text-right">{stat.cache_hits}</td>
|
||||
<td className="px-4 py-2 text-right">{stat.cache_misses}</td>
|
||||
<td className="px-4 py-2 text-right">{stat.last_interpret_time_ms}</td>
|
||||
<td className="px-4 py-2 text-right">{stat.last_compile_time_ms}</td>
|
||||
</tr>
|
||||
))
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user