Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | 1x 1x 1x 1x 1x 1x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 19x 19x 18x 18x 18x 1x 1x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x | export const dynamic = "force-dynamic";
import { Suspense } from 'react';
import { prisma } from '@/lib/prisma';
import { ErrorDashboard } from '@/components/admin/monitoring/ErrorDashboard';
async function getErrorStats() {
const [
totalErrors,
errorsToday,
openErrors,
errorsByCategory,
topErrors,
] = await Promise.all([
prisma.errorLog.count(),
prisma.errorLog.count({
where: {
createdAt: {
gte: new Date(new Date().setHours(0, 0, 0, 0)),
},
},
}),
prisma.errorStatistic.count({
where: { status: 'open' },
}),
prisma.errorLog.groupBy({
by: ['category'],
_count: true,
where: {
createdAt: {
gte: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), // Last 7 days
},
},
}),
prisma.errorStatistic.findMany({
take: 10,
where: { status: 'open' },
orderBy: { count: 'desc' },
}),
]);
return {
totalErrors,
errorsToday,
openErrors,
errorsByCategory,
topErrors: topErrors.map(e => ({
...e,
lastSeen: e.lastSeen.toISOString(),
})),
};
}
export default async function ErrorMonitoringPage() {
const stats = await getErrorStats();
return (
<div className="p-6">
<h1 className="text-2xl font-bold mb-6 text-gray-900 dark:text-white">Error Monitoring</h1>
<Suspense fallback={<div>Loading...</div>}>
<ErrorDashboard stats={stats} />
</Suspense>
</div>
);
}
|