Files
Nas-Notification/server/api/notifications/queue/performance.get.js

145 lines
4.4 KiB
JavaScript

import prisma from "~/server/utils/prisma";
export default defineEventHandler(async (event) => {
try {
const now = new Date();
const last24Hours = new Date(now.getTime() - 24 * 60 * 60 * 1000);
const last60Minutes = new Date(now.getTime() - 60 * 60 * 1000);
// Fetch comprehensive queue metrics
const [
totalProcessedToday,
totalCompletedToday,
totalFailedToday,
queuedJobs,
processingJobs,
completedLastHour,
allJobsToday
] = await Promise.all([
// Total processed (completed + failed) in last 24 hours
prisma.notification_queue.count({
where: {
OR: [{ status: "completed" }, { status: "failed" }],
updated_at: { gte: last24Hours },
},
}),
// Successful jobs in last 24 hours
prisma.notification_queue.count({
where: {
status: "completed",
updated_at: { gte: last24Hours },
},
}),
// Failed jobs in last 24 hours
prisma.notification_queue.count({
where: {
status: "failed",
updated_at: { gte: last24Hours },
},
}),
// Currently queued jobs
prisma.notification_queue.count({
where: { status: "queued" },
}),
// Currently processing jobs
prisma.notification_queue.count({
where: { status: "processing" },
}),
// Completed in last hour
prisma.notification_queue.count({
where: {
status: "completed",
updated_at: { gte: last60Minutes },
},
}),
// Get sample jobs to calculate average processing time
prisma.notification_queue.findMany({
where: {
status: "completed",
updated_at: { gte: last24Hours },
last_attempt_at: { not: null },
},
select: {
created_at: true,
last_attempt_at: true,
},
take: 100,
}),
]);
// Calculate throughput (messages per minute)
const throughputPerMinute = Math.round(totalProcessedToday / (24 * 60));
const currentThroughput = completedLastHour; // Last hour throughput
const peakThroughput = Math.round(currentThroughput * 1.3); // Estimate peak
const avgThroughput = throughputPerMinute;
// Calculate success rate
const successRate = totalProcessedToday > 0
? ((totalCompletedToday / totalProcessedToday) * 100).toFixed(1)
: "100";
// Calculate error rate
const errorRate = totalProcessedToday > 0
? ((totalFailedToday / totalProcessedToday) * 100).toFixed(1)
: "0";
// Calculate queue load percentage
const totalCapacity = 1000; // Assume max capacity
const queueLoad = Math.min(100, Math.round(((queuedJobs + processingJobs) / totalCapacity) * 100));
// Calculate average response time from actual data
let avgResponseTime = 0;
if (allJobsToday.length > 0) {
const responseTimes = allJobsToday
.filter(job => job.last_attempt_at)
.map(job => {
const diff = new Date(job.last_attempt_at).getTime() - new Date(job.created_at).getTime();
return Math.abs(diff);
});
if (responseTimes.length > 0) {
avgResponseTime = Math.round(
responseTimes.reduce((sum, time) => sum + time, 0) / responseTimes.length
);
}
}
// Fallback if no data
if (avgResponseTime === 0) avgResponseTime = 250;
// Active workers (estimate based on processing jobs)
const activeWorkers = processingJobs > 0 ? Math.min(10, processingJobs) : 1;
return {
success: true,
data: {
metrics: {
throughput: throughputPerMinute.toString(),
uptime: successRate,
workers: activeWorkers.toString(),
queueLoad: queueLoad.toString(),
},
throughput: {
current: currentThroughput.toString(),
peak: peakThroughput.toString(),
average: avgThroughput.toString(),
},
systemStatus: {
uptimeToday: successRate,
responseTime: avgResponseTime.toString(),
errorRate: errorRate,
},
},
};
} catch (error) {
console.error("Error fetching queue performance:", error);
throw createError({
statusCode: 500,
statusMessage: "Failed to fetch queue performance metrics",
data: {
error: error.message,
},
});
} finally {
}
});