OW IT-Consulting AB
OW IT-Consulting AB
  • Services
  • About
  • References
  • Contact
  • Blog
Server Monitoring Dashboard

Server Monitoring Dashboard

Dashboard
Servers & Services
Reports
Alerts Configuration
Settings

Status Overview

Loading servers status...

Latest Alerts

Loading alerts...

Performance Metrics

Loading performance metrics...

Manage Servers

Add New Server

Services

Your Servers

Loading servers...

Generate Reports

Report Results

Server Service Uptime % Avg Response (ms) Max Response (ms) Outages

Email Alerts Configuration

Alert History

Loading alert history...

Application Settings

Data Management

{ display: true, text: 'Service Response Times' }, legend: { position: 'bottom' } } } }); } // Get color for a service type function getServiceColor(serviceType, alpha = 1) { const colors = { 'ping': `rgba(52, 152, 219, ${alpha})`, 'http': `rgba(46, 204, 113, ${alpha})`, 'https': `rgba(46, 204, 113, ${alpha})`, 'ssh': `rgba(155, 89, 182, ${alpha})`, 'ftp': `rgba(230, 126, 34, ${alpha})`, 'smtp': `rgba(241, 196, 15, ${alpha})`, 'pop3': `rgba(231, 76, 60, ${alpha})`, 'imap': `rgba(26, 188, 156, ${alpha})`, 'dns': `rgba(52, 73, 94, ${alpha})`, 'tcp': `rgba(189, 195, 199, ${alpha})` }; return colors[serviceType] || `rgba(149, 165, 166, ${alpha})`; } // Format date for display function formatDate(date) { const options = { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit' }; return date.toLocaleDateString(undefined, options); } // Load server list for reports function loadServerListForReports() { const serverSelect = document.getElementById('report-server'); const servers = JSON.parse(localStorage.getItem(SERVERS_KEY)); // Clear existing options except "All Servers" while (serverSelect.options.length > 1) { serverSelect.remove(1); } // Add server options servers.forEach(server => { const option = document.createElement('option'); option.value = server.id; option.textContent = server.name; serverSelect.appendChild(option); }); // Update service options when server changes serverSelect.addEventListener('change', function() { loadServiceListForReports(this.value); }); // Load initial service list loadServiceListForReports(serverSelect.value); } // Load service list for reports based on selected server function loadServiceListForReports(serverId) { const serviceSelect = document.getElementById('report-service'); const servers = JSON.parse(localStorage.getItem(SERVERS_KEY)); // Clear existing options except "All Services" while (serviceSelect.options.length > 1) { serviceSelect.remove(1); } if (serverId === 'all') { // Add all services from all servers servers.forEach(server => { server.services.forEach(service => { const option = document.createElement('option'); option.value = `${server.id}_${service.id}`; option.textContent = `${server.name} - ${service.type.toUpperCase()}${service.port > 0 ? `:${service.port}` : ''}`; serviceSelect.appendChild(option); }); }); } else { // Add services for selected server const server = servers.find(s => s.id === serverId); if (server) { server.services.forEach(service => { const option = document.createElement('option'); option.value = service.id; option.textContent = `${service.type.toUpperCase()}${service.port > 0 ? `:${service.port}` : ''}`; serviceSelect.appendChild(option); }); } } } // Generate a report function generateReport() { const serverId = document.getElementById('report-server').value; const serviceId = document.getElementById('report-service').value; const period = document.getElementById('report-period').value; const date = document.getElementById('report-date').value; const servers = JSON.parse(localStorage.getItem(SERVERS_KEY)); const checks = JSON.parse(localStorage.getItem(CHECKS_KEY)); // Determine date range based on period const endDate = date ? new Date(date) : new Date(); endDate.setHours(23, 59, 59, 999); let startDate; if (period === 'daily') { startDate = new Date(endDate); startDate.setHours(0, 0, 0, 0); } else if (period === 'weekly') { startDate = new Date(endDate); startDate.setDate(startDate.getDate() - 6); startDate.setHours(0, 0, 0, 0); } else if (period === 'monthly') { startDate = new Date(endDate); startDate.setDate(1); startDate.setHours(0, 0, 0, 0); } // Filter checks based on date range const filteredChecks = checks.filter(check => { const checkDate = new Date(check.timestamp); return checkDate >= startDate && checkDate <= endDate; }); // Prepare report data let reportData = []; if (serverId === 'all') { // Report for all servers servers.forEach(server => { if (serviceId === 'all') { // All services server.services.forEach(service => { const serviceChecks = filteredChecks.filter(check => check.serverId === server.id && check.serviceId === service.id ); if (serviceChecks.length > 0) { reportData.push(generateServiceReport(server, service, serviceChecks)); } }); } else if (serviceId.includes('_')) { // Specific service across servers const [sId, svcId] = serviceId.split('_'); if (server.id === sId) { const service = server.services.find(s => s.id === svcId); if (service) { const serviceChecks = filteredChecks.filter(check => check.serverId === server.id && check.serviceId === service.id ); if (serviceChecks.length > 0) { reportData.push(generateServiceReport(server, service, serviceChecks)); } } } } }); } else { // Report for specific server const server = servers.find(s => s.id === serverId); if (server) { if (serviceId === 'all') { // All services for this server server.services.forEach(service => { const serviceChecks = filteredChecks.filter(check => check.serverId === server.id && check.serviceId === service.id ); if (serviceChecks.length > 0) { reportData.push(generateServiceReport(server, service, serviceChecks)); } }); } else { // Specific service const service = server.services.find(s => s.id === serviceId); if (service) { const serviceChecks = filteredChecks.filter(check => check.serverId === server.id && check.serviceId === service.id ); if (serviceChecks.length > 0) { reportData.push(generateServiceReport(server, service, serviceChecks)); } } } } } // Display report displayReport(reportData, startDate, endDate, period); } // Generate service report data function generateServiceReport(server, service, checks) { // Calculate uptime percentage const totalChecks = checks.length; const successfulChecks = checks.filter(check => check.success).length; const uptimePercentage = totalChecks > 0 ? (successfulChecks / totalChecks) * 100 : 0; // Calculate average and max response times let avgResponseTime = 0; let maxResponseTime = 0; const successfulChecksData = checks.filter(check => check.success); if (successfulChecksData.length > 0) { const responseTimes = successfulChecksData.map(check => check.responseTime); avgResponseTime = responseTimes.reduce((sum, time) => sum + time, 0) / successfulChecksData.length; maxResponseTime = Math.max(...responseTimes); } // Count outages let outages = 0; let inOutage = false; for (let i = 0; i < checks.length; i++) { if (!checks[i].success && !inOutage) { outages++; inOutage = true; } else if (checks[i].success) { inOutage = false; } } return { serverId: server.id, serverName: server.name, serviceId: service.id, serviceType: service.type, servicePort: service.port, threshold: service.threshold, checks: checks, uptime: uptimePercentage.toFixed(2), avgResponse: avgResponseTime.toFixed(2), maxResponse: maxResponseTime.toFixed(2), outages: outages }; } // Display report results function displayReport(reportData, startDate, endDate, period) { const reportResults = document.getElementById('report-results'); const reportTable = document.getElementById('report-table').querySelector('tbody'); if (reportData.length === 0) { alert('No data found for the selected period.'); return; } // Show report section reportResults.style.display = 'block'; // Clear previous table data reportTable.innerHTML = ''; // Add rows to table reportData.forEach(report => { const row = document.createElement('tr'); row.innerHTML = ` ${report.serverName} ${report.serviceType.toUpperCase()}${report.servicePort > 0 ? `:${report.servicePort}` : ''} ${report.uptime}% ${report.avgResponse} ms ${report.maxResponse} ms ${report.outages} `; reportTable.appendChild(row); }); // Create chart createReportChart(reportData, startDate, endDate, period); } // Create report chart function createReportChart(reportData, startDate, endDate, period) { const ctx = document.getElementById('report-chart').getContext('2d'); // Destroy previous chart instance if it exists if (window.reportChart) { window.reportChart.destroy(); } // Determine x-axis units based on period let timeUnit = 'hour'; if (period === 'weekly' || period === 'monthly') { timeUnit = 'day'; } // Prepare datasets const datasets = []; reportData.forEach(report => { datasets.push({ label: `${report.serverName} - ${report.serviceType.toUpperCase()}${report.servicePort > 0 ? `:${report.servicePort}` : ''}`, data: report.checks.map(check => ({ x: new Date(check.timestamp), y: check.success ? check.responseTime : null })), borderColor: getServiceColor(report.serviceType), backgroundColor: getServiceColor(report.serviceType, 0.1), tension: 0.1, pointRadius: 1, borderWidth: 2 }); }); // Create chart window.reportChart = new Chart(ctx, { type: 'line', data: { datasets: datasets }, options: { responsive: true, maintainAspectRatio: false, scales: { x: { type: 'time', time: { unit: timeUnit, displayFormats: { hour: 'HH:mm', day: 'MMM dd' } }, title: { display: true, text: 'Time' } }, y: { title: { display: true, text: 'Response Time (ms)' }, beginAtZero: true } }, plugins: { title: { display: true, text: 'Response Times (Last 24 Hours)' }, legend: { position: 'bottom' } } } }); } // Load a chart for a specific server in the server details view function loadServerChart(serverId) { const servers = JSON.parse(localStorage.getItem(SERVERS_KEY)); const checks = JSON.parse(localStorage.getItem(CHECKS_KEY)); const server = servers.find(s => s.id === serverId); if (!server) return; // Get all checks for this server const serverChecks = checks.filter(check => check.serverId === serverId); // Group checks by service const serviceChecks = {}; server.services.forEach(service => { serviceChecks[service.id] = serverChecks.filter(check => check.serviceId === service.id ).sort((a, b) => new Date(a.timestamp) - new Date(b.timestamp) ); }); // Prepare data for chart const datasets = []; server.services.forEach(service => { const serviceData = serviceChecks[service.id]; if (serviceData.length > 0) { datasets.push({ label: `${service.type.toUpperCase()}${service.port > 0 ? `:${service.port}` : ''}`, data: serviceData.map(check => ({ x: new Date(check.timestamp), y: check.success ? check.responseTime : null })), borderColor: getServiceColor(service.type), backgroundColor: getServiceColor(service.type, 0.1), tension: 0.1, pointRadius: 1, borderWidth: 2 }); } }); // Create chart const ctx = document.getElementById(`server-chart-${serverId}`).getContext('2d'); new Chart(ctx, { type: 'line', data: { datasets: datasets }, options: { responsive: true, maintainAspectRatio: false, scales: { x: { type: 'time', time: { unit: 'hour', displayFormats: { hour: 'HH:mm' } }, title: { display: true, text: 'Time' } }, y: { title: { display: true, text: 'Response Time (ms)' }, beginAtZero: true } }, plugins: { title: const serverList = document.getElementById('server-list'); const servers = JSON.parse(localStorage.getItem(SERVERS_KEY)); if (servers.length === 0) { serverList.innerHTML = '

No servers added yet. Use the form above to add your first server.

'; return; } let html = ''; servers.forEach(server => { html += `

${server.name}

Host: ${server.host}

Description: ${server.description || 'N/A'}

Services

`; server.services.forEach(service => { const serviceStatus = getServiceStatus(server.id, service.id); const statusClass = serviceStatus.status === 'up' ? 'status-up' : serviceStatus.status === 'down' ? 'status-down' : 'status-warning'; html += `
${serviceStatus.status} ${service.type.toUpperCase()} ${service.port > 0 ? `:${service.port}` : ''}
`; }); html += `
Show Details
`; }); serverList.innerHTML = html; // Add event listeners for server actions document.querySelectorAll('.edit-server').forEach(btn => { btn.addEventListener('click', function() { editServer(this.getAttribute('data-id')); }); }); document.querySelectorAll('.delete-server').forEach(btn => { btn.addEventListener('click', function() { deleteServer(this.getAttribute('data-id')); }); }); document.querySelectorAll('.edit-service').forEach(btn => { btn.addEventListener('click', function() { editService( this.getAttribute('data-server'), this.getAttribute('data-service') ); }); }); document.querySelectorAll('.delete-service').forEach(btn => { btn.addEventListener('click', function() { deleteService( this.getAttribute('data-server'), this.getAttribute('data-service') ); }); }); document.querySelectorAll('.show-details').forEach(btn => { btn.addEventListener('click', function() { const serverId = this.getAttribute('data-server'); const detailsDiv = document.getElementById(`server-details-${serverId}`); if (detailsDiv.style.display === 'block') { detailsDiv.style.display = 'none'; this.textContent = 'Show Details'; } else { detailsDiv.style.display = 'block'; this.textContent = 'Hide Details'; loadServerChart(serverId); } }); });