Files
Nas-Notification/server/api/notifications/logs/monitoring.get.js

260 lines
6.8 KiB
JavaScript

import prisma from '~/server/utils/prisma'
export default defineEventHandler(async (event) => {
try {
// Check authentication
const user = event.context.user;
if (!user || !user.userID) {
return {
statusCode: 401,
body: { success: false, message: 'Unauthorized' }
}
}
// Get system status metrics
const now = new Date()
const oneDayAgo = new Date(now)
oneDayAgo.setDate(oneDayAgo.getDate() - 1)
// Get total sent in last 24 hours
const totalSent = await prisma.notification_logs.count({
where: {
created_at: {
gte: oneDayAgo,
lte: now
},
status: 'Sent'
}
})
// Get success rate in last 24 hours
const totalAttempted = await prisma.notification_logs.count({
where: {
created_at: {
gte: oneDayAgo,
lte: now
},
action: {
in: ['Notification Sent', 'Delivery Attempted']
}
}
})
const successfulDeliveries = await prisma.notification_logs.count({
where: {
created_at: {
gte: oneDayAgo,
lte: now
},
status: 'Sent'
}
})
const successRate = totalAttempted > 0
? ((successfulDeliveries / totalAttempted) * 100).toFixed(2)
: 0
// Get error rate in last 24 hours
const failedDeliveries = await prisma.notification_logs.count({
where: {
created_at: {
gte: oneDayAgo,
lte: now
},
status: 'Failed'
}
})
const errorRate = totalAttempted > 0
? ((failedDeliveries / totalAttempted) * 100).toFixed(2)
: 0
// Get average response time (mock data since we need actual measurements)
const avgResponseTime = "145"
// Calculate status based on metrics
const getSystemStatus = (metric, thresholds) => {
if (metric <= thresholds.healthy) return 'healthy'
if (metric <= thresholds.warning) return 'warning'
return 'critical'
}
// Get queue status
const queueStatus = await getQueueStatus(prisma)
// Get recent activity
const recentActivity = await getRecentActivity(prisma)
// Get performance metrics
const performanceMetrics = {
cpu: 23, // Mock data
memory: 67, // Mock data
queueLoad: calculateQueueLoad(queueStatus)
}
// Get error alerts (mock data)
const errorAlerts = await getErrorAlerts(prisma, oneDayAgo, now)
return {
statusCode: 200,
body: {
success: true,
data: {
systemStatus: [
{
title: "System Health",
value: errorRate < 1 ? "Healthy" : errorRate < 5 ? "Warning" : "Critical",
icon: "ic:outline-favorite",
status: getSystemStatus(errorRate, { healthy: 1, warning: 5 })
},
{
title: "Throughput",
value: `${Math.round(totalSent / 24)}/hr`,
icon: "ic:outline-speed",
status: 'healthy' // Simplified for now
},
{
title: "Error Rate",
value: `${errorRate}%`,
icon: "ic:outline-error-outline",
status: getSystemStatus(errorRate, { healthy: 1, warning: 5 })
},
{
title: "Response Time",
value: `${avgResponseTime}ms`,
icon: "ic:outline-timer",
status: getSystemStatus(parseFloat(avgResponseTime), { healthy: 100, warning: 200 })
}
],
performanceMetrics,
queueStatus,
recentActivity,
errorAlerts
}
}
}
} catch (error) {
console.error('Error fetching monitoring data:', error)
return {
statusCode: 500,
body: { success: false, message: 'Failed to fetch monitoring data', error: error.message }
}
}
})
// Helper functions
async function getQueueStatus(prisma) {
const channels = ['Email', 'SMS', 'Push Notification', 'Webhook']
// In a real implementation, this would query the notification_queue table
// For now, we'll use mock data
return [
{
name: "Email Queue",
count: "1,247",
description: "Pending emails",
status: "active",
utilization: 78
},
{
name: "SMS Queue",
count: "89",
description: "Pending SMS",
status: "active",
utilization: 23
},
{
name: "Push Queue",
count: "3,456",
description: "Pending push notifications",
status: "warning",
utilization: 92
},
{
name: "Webhook Queue",
count: "12",
description: "Pending webhooks",
status: "active",
utilization: 8
}
]
}
function calculateQueueLoad(queueStatus) {
// Calculate average utilization across all queues
const totalUtilization = queueStatus.reduce((sum, queue) => sum + queue.utilization, 0)
return Math.round(totalUtilization / queueStatus.length)
}
async function getRecentActivity(prisma) {
// Get the most recent 5 log entries
const recentLogs = await prisma.notification_logs.findMany({
orderBy: {
created_at: 'desc'
},
take: 5
})
// Format for the frontend
return recentLogs.map(log => {
const timeAgo = formatTimeAgo(log.created_at)
return {
action: log.action,
description: log.details || 'No details provided',
status: log.status ? log.status.toLowerCase() : 'unknown',
time: timeAgo,
source: log.channel_type || 'System'
}
})
}
function formatTimeAgo(timestamp) {
const now = new Date()
const time = new Date(timestamp)
const diffInMinutes = Math.floor((now - time) / (1000 * 60))
if (diffInMinutes < 1) return "Just now"
if (diffInMinutes < 60) return `${diffInMinutes} minutes ago`
if (diffInMinutes < 1440) return `${Math.floor(diffInMinutes / 60)} hours ago`
return `${Math.floor(diffInMinutes / 1440)} days ago`
}
async function getErrorAlerts(prisma, startDate, endDate) {
// Get recent errors
const recentErrors = await prisma.notification_logs.findMany({
where: {
created_at: {
gte: startDate,
lte: endDate
},
status: 'Failed',
error_message: {
not: null
}
},
orderBy: {
created_at: 'desc'
},
take: 3
})
// Format for the frontend
return recentErrors.map(error => {
const timeAgo = formatTimeAgo(error.created_at)
// Determine severity based on error code or other factors
let severity = 'warning'
if (error.error_code && error.error_code.startsWith('CRIT')) {
severity = 'critical'
}
return {
title: error.action || 'Error Detected',
description: error.error_message || 'Unknown error occurred',
timestamp: timeAgo,
component: error.channel_type || 'System',
severity
}
})
}