Import source: app/backend/src/lib/error-digest
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import { prisma } from '../db.js';
|
||||
import { sendEmail } from './email.js';
|
||||
|
||||
const ALERT_THRESHOLD = 50;
|
||||
const ALERT_RECIPIENT = process.env.ADMIN_ALERT_EMAIL || '';
|
||||
|
||||
export async function sendErrorDigest(): Promise<{ sent: boolean; count: number }> {
|
||||
const since = new Date();
|
||||
since.setHours(0, 0, 0, 0);
|
||||
|
||||
const errors = await prisma.clientError.findMany({
|
||||
where: { createdAt: { gte: since } },
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 100,
|
||||
});
|
||||
|
||||
const count = await prisma.clientError.count({
|
||||
where: { createdAt: { gte: since } },
|
||||
});
|
||||
|
||||
if (count < ALERT_THRESHOLD || !ALERT_RECIPIENT) {
|
||||
return { sent: false, count };
|
||||
}
|
||||
|
||||
const topMessages = Object.entries(
|
||||
errors.reduce<Record<string, number>>((acc, e) => {
|
||||
acc[e.message] = (acc[e.message] || 0) + 1;
|
||||
return acc;
|
||||
}, {}),
|
||||
)
|
||||
.sort(([, a], [, b]) => b - a)
|
||||
.slice(0, 10);
|
||||
|
||||
const html = `
|
||||
<div dir="rtl" style="font-family: Vazirmatn, sans-serif; max-width: 600px; margin: 0 auto;">
|
||||
<h2 style="color: #C94C4C;">گزارش خطاهای روزانه تکناو</h2>
|
||||
<p>تعداد خطاها در ۲۴ ساعت گذشته: <strong>${count}</strong></p>
|
||||
<h3>بیشترین تکرار:</h3>
|
||||
<ul>
|
||||
${topMessages.map(([msg, cnt]) => `<li><code>${msg}</code> (${cnt} بار)</li>`).join('')}
|
||||
</ul>
|
||||
<p style="color: #5F6B6D; font-size: 12px;">این گزارش از پنل خطاهای تکناو ارسال شده است.</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
await sendEmail({ to: ALERT_RECIPIENT, subject: `گزارش خطاهای تکناو — ${count} خطا`, html });
|
||||
return { sent: true, count };
|
||||
}
|
||||
Reference in New Issue
Block a user