diff --git a/.eslintrc.json b/.eslintrc.json index 65529ee..7d1bc4e 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,34 +1,68 @@ { - "env": { - "browser": true, - "commonjs": true, - "es2021": true, - "node": true, - "jest": true - }, - "extends": [ - "eslint:recommended" + "env": { + "browser": true, + "commonjs": true, + "es2021": true, + "node": true, + "jest": true + }, + "extends": [ + "eslint:recommended" + ], + "parserOptions": { + "ecmaVersion": "latest" + }, + "rules": { + "indent": [ + "error", + 2 ], - "parserOptions": { - "ecmaVersion": "latest" - }, - "rules": { - "indent": ["error", 2], - "linebreak-style": ["error", "unix"], - "quotes": ["error", "single"], - "semi": ["error", "always"], - "no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], - "no-console": "off", - "no-trailing-spaces": "error", - "eol-last": "error", - "comma-dangle": ["error", "never"], - "object-curly-spacing": ["error", "always"], - "array-bracket-spacing": ["error", "never"], - "space-before-function-paren": ["error", "never"], - "keyword-spacing": "error", - "space-infix-ops": "error", - "no-multiple-empty-lines": ["error", { "max": 2 }], - "prefer-const": "error", - "no-var": "error" - } - } \ No newline at end of file + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "error", + "single" + ], + "semi": [ + "error", + "always" + ], + "no-unused-vars": [ + "error", + { + "argsIgnorePattern": "^_" + } + ], + "no-console": "off", + "no-trailing-spaces": "error", + "eol-last": "error", + "comma-dangle": [ + "error", + "never" + ], + "object-curly-spacing": [ + "error", + "always" + ], + "array-bracket-spacing": [ + "error", + "never" + ], + "space-before-function-paren": [ + "error", + "never" + ], + "keyword-spacing": "error", + "space-infix-ops": "error", + "no-multiple-empty-lines": [ + "error", + { + "max": 2 + } + ], + "prefer-const": "error", + "no-var": "error" + } +} \ No newline at end of file diff --git a/package.json b/package.json index b952e3d..f882d5b 100644 --- a/package.json +++ b/package.json @@ -1,47 +1,53 @@ { - "name": "harbor-ci-cd-demo", - "version": "1.0.0", - "description": "System Monitoring Dashboard - Harbor CI/CD Demo", - "main": "src/app.js", - "scripts": { - "start": "node src/app.js", - "dev": "nodemon src/app.js", - "test": "jest", - "test:watch": "jest --watch", - "test:coverage": "jest --coverage", - "lint": "eslint src/ tests/", - "lint:fix": "eslint src/ tests/ --fix" - }, - "keywords": ["monitoring", "dashboard", "nodejs", "cicd", "harbor"], - "author": "Your Name", - "license": "MIT", - "dependencies": { - "express": "^4.18.2", - "cors": "^2.8.5", - "helmet": "^7.1.0", - "morgan": "^1.10.0", - "compression": "^1.7.4", - "dotenv": "^16.3.1" - }, - "devDependencies": { - "jest": "^29.7.0", - "supertest": "^6.3.3", - "eslint": "^8.53.0", - "nodemon": "^3.0.1" - }, - "jest": { - "testEnvironment": "node", - "collectCoverageFrom": [ - "src/**/*.js", - "!src/public/**" - ], - "coverageThreshold": { - "global": { - "branches": 80, - "functions": 80, - "lines": 80, - "statements": 80 - } + "name": "harbor-ci-cd-demo", + "version": "1.0.0", + "description": "System Monitoring Dashboard - Harbor CI/CD Demo", + "main": "src/app.js", + "scripts": { + "start": "node src/app.js", + "dev": "nodemon src/app.js", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "lint": "eslint src/ tests/", + "lint:fix": "eslint src/ tests/ --fix" + }, + "keywords": [ + "monitoring", + "dashboard", + "nodejs", + "cicd", + "harbor" + ], + "author": "Your Name", + "license": "MIT", + "dependencies": { + "express": "^4.18.2", + "cors": "^2.8.5", + "helmet": "^7.1.0", + "morgan": "^1.10.0", + "compression": "^1.7.4", + "dotenv": "^16.3.1" + }, + "devDependencies": { + "jest": "^29.7.0", + "supertest": "^6.3.3", + "eslint": "^8.53.0", + "nodemon": "^3.0.1" + }, + "jest": { + "testEnvironment": "node", + "collectCoverageFrom": [ + "src/**/*.js", + "!src/public/**" + ], + "coverageThreshold": { + "global": { + "branches": 80, + "functions": 80, + "lines": 80, + "statements": 80 } } - } \ No newline at end of file + } +} \ No newline at end of file diff --git a/src/app.js b/src/app.js index 5123207..6ebb5aa 100644 --- a/src/app.js +++ b/src/app.js @@ -47,7 +47,7 @@ app.get('/debug/files', (req, res) => { url: `http://localhost:${PORT}/${file}` }; }); - + res.json({ publicPath, files: fileDetails, @@ -101,7 +101,7 @@ app.get('/test-static', (req, res) => { app.get('/', (req, res) => { const indexPath = path.join(publicPath, 'index.html'); console.log('๐ Serving index.html from:', indexPath); - + if (require('fs').existsSync(indexPath)) { res.sendFile(indexPath); } else { @@ -119,7 +119,7 @@ app.use((err, req, res, next) => { // 404 handler app.use('*', (req, res) => { console.log('๐ 404 for:', req.originalUrl); - res.status(404).json({ + res.status(404).json({ error: 'Not Found', url: req.originalUrl, message: 'Static file or route not found' diff --git a/src/middleware/logger.js b/src/middleware/logger.js index b1b8b7c..9d3b339 100644 --- a/src/middleware/logger.js +++ b/src/middleware/logger.js @@ -3,10 +3,10 @@ const { incrementCounter, recordHistogram } = require('../utils/metrics'); // Request logging and metrics middleware function logger(req, res, next) { const startTime = Date.now(); - + // Log request start console.log(`${new Date().toISOString()} - ${req.method} ${req.url} - ${req.ip}`); - + // Increment request counter incrementCounter('http_requests_total', { method: req.method, @@ -15,24 +15,24 @@ function logger(req, res, next) { // Override res.end to capture response time and status const originalEnd = res.end; - res.end = function(chunk, encoding) { + res.end = function (chunk, encoding) { const responseTime = Date.now() - startTime; - + // Record response time histogram recordHistogram('http_request_duration_ms', responseTime, { method: req.method, status_code: res.statusCode }); - + // Increment response counter incrementCounter('http_responses_total', { method: req.method, status_code: res.statusCode }); - + // Log request completion console.log(`${new Date().toISOString()} - ${req.method} ${req.url} - ${res.statusCode} - ${responseTime}ms`); - + // Call original end method originalEnd.call(this, chunk, encoding); }; diff --git a/src/public/app.js b/src/public/app.js index 4d09b7b..c6dcec5 100644 --- a/src/public/app.js +++ b/src/public/app.js @@ -1,113 +1,113 @@ class MonitoringDashboard { - constructor() { - this.refreshInterval = null; - this.autoRefresh = true; - this.refreshRate = 30000; // 30 seconds - this.init(); - } + constructor() { + this.refreshInterval = null; + this.autoRefresh = true; + this.refreshRate = 30000; // 30 seconds + this.init(); + } - async init() { - await this.loadAllData(); - this.startAutoRefresh(); - this.setupEventListeners(); - } + async init() { + await this.loadAllData(); + this.startAutoRefresh(); + this.setupEventListeners(); + } - async loadAllData() { - this.updateStatus('loading', 'Loading...'); - - try { - await Promise.all([ - this.loadSystemInfo(), - this.loadMemoryUsage(), - this.loadHealthStatus(), - this.loadApiMetrics(), - this.loadProcessInfo() - ]); - - this.updateStatus('healthy', 'System Healthy'); - this.updateLastUpdated(); - } catch (error) { - console.error('Error loading data:', error); - this.updateStatus('error', 'Error Loading Data'); - } - } + async loadAllData() { + this.updateStatus('loading', 'Loading...'); - async loadSystemInfo() { - try { - const response = await fetch('/api/system'); - const result = await response.json(); - - if (result.success) { - this.renderSystemInfo(result.data); - } else { - throw new Error(result.error); - } - } catch (error) { - this.renderError('system-info', 'Failed to load system information'); - } - } + try { + await Promise.all([ + this.loadSystemInfo(), + this.loadMemoryUsage(), + this.loadHealthStatus(), + this.loadApiMetrics(), + this.loadProcessInfo() + ]); - async loadMemoryUsage() { - try { - const response = await fetch('/api/memory'); - const result = await response.json(); - - if (result.success) { - this.renderMemoryUsage(result.data); - } else { - throw new Error(result.error); - } - } catch (error) { - this.renderError('memory-usage', 'Failed to load memory data'); - } + this.updateStatus('healthy', 'System Healthy'); + this.updateLastUpdated(); + } catch (error) { + console.error('Error loading data:', error); + this.updateStatus('error', 'Error Loading Data'); } + } - async loadHealthStatus() { - try { - const response = await fetch('/health/detailed'); - const result = await response.json(); - - this.renderHealthStatus(result); - this.updateOverallStatus(result.status); - } catch (error) { - this.renderError('health-status', 'Failed to load health data'); - this.updateStatus('error', 'Health Check Failed'); - } + async loadSystemInfo() { + try { + const response = await fetch('/api/system'); + const result = await response.json(); + + if (result.success) { + this.renderSystemInfo(result.data); + } else { + throw new Error(result.error); + } + } catch (error) { + this.renderError('system-info', 'Failed to load system information'); } + } - async loadApiMetrics() { - try { - const response = await fetch('/api/metrics'); - const result = await response.json(); - - if (result.success) { - this.renderApiMetrics(result.data); - } else { - throw new Error(result.error); - } - } catch (error) { - this.renderError('api-metrics', 'Failed to load metrics'); - } + async loadMemoryUsage() { + try { + const response = await fetch('/api/memory'); + const result = await response.json(); + + if (result.success) { + this.renderMemoryUsage(result.data); + } else { + throw new Error(result.error); + } + } catch (error) { + this.renderError('memory-usage', 'Failed to load memory data'); } + } - async loadProcessInfo() { - try { - const response = await fetch('/api/process'); - const result = await response.json(); - - if (result.success) { - this.renderProcessInfo(result.data); - } else { - throw new Error(result.error); - } - } catch (error) { - this.renderError('process-info', 'Failed to load process information'); - } + async loadHealthStatus() { + try { + const response = await fetch('/health/detailed'); + const result = await response.json(); + + this.renderHealthStatus(result); + this.updateOverallStatus(result.status); + } catch (error) { + this.renderError('health-status', 'Failed to load health data'); + this.updateStatus('error', 'Health Check Failed'); } + } - renderSystemInfo(data) { - const container = document.getElementById('system-info'); - container.innerHTML = ` + async loadApiMetrics() { + try { + const response = await fetch('/api/metrics'); + const result = await response.json(); + + if (result.success) { + this.renderApiMetrics(result.data); + } else { + throw new Error(result.error); + } + } catch (error) { + this.renderError('api-metrics', 'Failed to load metrics'); + } + } + + async loadProcessInfo() { + try { + const response = await fetch('/api/process'); + const result = await response.json(); + + if (result.success) { + this.renderProcessInfo(result.data); + } else { + throw new Error(result.error); + } + } catch (error) { + this.renderError('process-info', 'Failed to load process information'); + } + } + + renderSystemInfo(data) { + const container = document.getElementById('system-info'); + container.innerHTML = `
Real-time system metrics and health monitoring
-Real-time system metrics and health monitoring
+