From c9754799f8f34bf1aa54eb78d5d1227a08774359 Mon Sep 17 00:00:00 2001 From: intern1-arizon Date: Wed, 14 Aug 2024 12:20:36 +0530 Subject: [PATCH 1/5] logging status in db --- .env | 1 + package-lock.json | 163 +++++++++++++++++++++++++++++++ package.json | 2 + prisma-setup.js | 47 +++++++++ prisma/schema.prisma | 30 ++++++ src/helpers/default-config.js | 3 +- src/helpers/gather-os-metrics.js | 46 ++++++--- src/helpers/socket-io-init.js | 8 +- src/helpers/validate.js | 5 + 9 files changed, 285 insertions(+), 20 deletions(-) create mode 100644 .env create mode 100644 prisma-setup.js create mode 100644 prisma/schema.prisma diff --git a/.env b/.env new file mode 100644 index 0000000..4b0060c --- /dev/null +++ b/.env @@ -0,0 +1 @@ +DATABASE_URL='sqlserver://localhost:1433;database=gil_cms2;integratedSecurity=true;trustServerCertificate=true' \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index da3ec54..ca0c698 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.3.4", "license": "MIT", "dependencies": { + "@prisma/client": "^5.18.0", "axios": "0.26.0", "debug": "4.1.1", "handlebars": "^4.7.7", @@ -20,6 +21,7 @@ "chai": "4.3.6", "eslint": "8.10.0", "mocha": "9.2.1", + "prisma": "^5.18.0", "sinon": "13.0.1" }, "engines": { @@ -96,6 +98,81 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@prisma/client": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.18.0.tgz", + "integrity": "sha512-BWivkLh+af1kqC89zCJYkHsRcyWsM8/JHpsDMM76DjP3ZdEquJhXa4IeX+HkWPnwJ5FanxEJFZZDTWiDs/Kvyw==", + "hasInstallScript": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.13" + }, + "peerDependencies": { + "prisma": "*" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + } + } + }, + "node_modules/@prisma/debug": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.18.0.tgz", + "integrity": "sha512-f+ZvpTLidSo3LMJxQPVgAxdAjzv5OpzAo/eF8qZqbwvgi2F5cTOI9XCpdRzJYA0iGfajjwjOKKrVq64vkxEfUw==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.18.0.tgz", + "integrity": "sha512-ofmpGLeJ2q2P0wa/XaEgTnX/IsLnvSp/gZts0zjgLNdBhfuj2lowOOPmDcfKljLQUXMvAek3lw5T01kHmCG8rg==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "5.18.0", + "@prisma/engines-version": "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169", + "@prisma/fetch-engine": "5.18.0", + "@prisma/get-platform": "5.18.0" + } + }, + "node_modules/@prisma/engines/node_modules/@prisma/engines-version": { + "version": "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169.tgz", + "integrity": "sha512-a/+LpJj8vYU3nmtkg+N3X51ddbt35yYrRe8wqHTJtYQt7l1f8kjIBcCs6sHJvodW/EK5XGvboOiwm47fmNrbgg==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/fetch-engine": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.18.0.tgz", + "integrity": "sha512-I/3u0x2n31rGaAuBRx2YK4eB7R/1zCuayo2DGwSpGyrJWsZesrV7QVw7ND0/Suxeo/vLkJ5OwuBqHoCxvTHpOg==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "5.18.0", + "@prisma/engines-version": "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169", + "@prisma/get-platform": "5.18.0" + } + }, + "node_modules/@prisma/fetch-engine/node_modules/@prisma/engines-version": { + "version": "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169.tgz", + "integrity": "sha512-a/+LpJj8vYU3nmtkg+N3X51ddbt35yYrRe8wqHTJtYQt7l1f8kjIBcCs6sHJvodW/EK5XGvboOiwm47fmNrbgg==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/get-platform": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.18.0.tgz", + "integrity": "sha512-Tk+m7+uhqcKDgnMnFN0lRiH7Ewea0OEsZZs9pqXa7i3+7svS3FSCqDBCaM9x5fmhhkufiG0BtunJVDka+46DlA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "5.18.0" + } + }, "node_modules/@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -1669,6 +1746,23 @@ "node": ">= 0.8.0" } }, + "node_modules/prisma": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.18.0.tgz", + "integrity": "sha512-+TrSIxZsh64OPOmaSgVPH7ALL9dfU0jceYaMJXsNrTkFHO7/3RANi5K2ZiPB1De9+KDxCWn7jvRq8y8pvk+o9g==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/engines": "5.18.0" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=16.13" + } + }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -2225,6 +2319,66 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "@prisma/client": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.18.0.tgz", + "integrity": "sha512-BWivkLh+af1kqC89zCJYkHsRcyWsM8/JHpsDMM76DjP3ZdEquJhXa4IeX+HkWPnwJ5FanxEJFZZDTWiDs/Kvyw==", + "requires": {} + }, + "@prisma/debug": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.18.0.tgz", + "integrity": "sha512-f+ZvpTLidSo3LMJxQPVgAxdAjzv5OpzAo/eF8qZqbwvgi2F5cTOI9XCpdRzJYA0iGfajjwjOKKrVq64vkxEfUw==", + "devOptional": true + }, + "@prisma/engines": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.18.0.tgz", + "integrity": "sha512-ofmpGLeJ2q2P0wa/XaEgTnX/IsLnvSp/gZts0zjgLNdBhfuj2lowOOPmDcfKljLQUXMvAek3lw5T01kHmCG8rg==", + "devOptional": true, + "requires": { + "@prisma/debug": "5.18.0", + "@prisma/engines-version": "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169", + "@prisma/fetch-engine": "5.18.0", + "@prisma/get-platform": "5.18.0" + }, + "dependencies": { + "@prisma/engines-version": { + "version": "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169.tgz", + "integrity": "sha512-a/+LpJj8vYU3nmtkg+N3X51ddbt35yYrRe8wqHTJtYQt7l1f8kjIBcCs6sHJvodW/EK5XGvboOiwm47fmNrbgg==", + "devOptional": true + } + } + }, + "@prisma/fetch-engine": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.18.0.tgz", + "integrity": "sha512-I/3u0x2n31rGaAuBRx2YK4eB7R/1zCuayo2DGwSpGyrJWsZesrV7QVw7ND0/Suxeo/vLkJ5OwuBqHoCxvTHpOg==", + "devOptional": true, + "requires": { + "@prisma/debug": "5.18.0", + "@prisma/engines-version": "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169", + "@prisma/get-platform": "5.18.0" + }, + "dependencies": { + "@prisma/engines-version": { + "version": "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169.tgz", + "integrity": "sha512-a/+LpJj8vYU3nmtkg+N3X51ddbt35yYrRe8wqHTJtYQt7l1f8kjIBcCs6sHJvodW/EK5XGvboOiwm47fmNrbgg==", + "devOptional": true + } + } + }, + "@prisma/get-platform": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.18.0.tgz", + "integrity": "sha512-Tk+m7+uhqcKDgnMnFN0lRiH7Ewea0OEsZZs9pqXa7i3+7svS3FSCqDBCaM9x5fmhhkufiG0BtunJVDka+46DlA==", + "devOptional": true, + "requires": { + "@prisma/debug": "5.18.0" + } + }, "@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -3397,6 +3551,15 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, + "prisma": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.18.0.tgz", + "integrity": "sha512-+TrSIxZsh64OPOmaSgVPH7ALL9dfU0jceYaMJXsNrTkFHO7/3RANi5K2ZiPB1De9+KDxCWn7jvRq8y8pvk+o9g==", + "devOptional": true, + "requires": { + "@prisma/engines": "5.18.0" + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", diff --git a/package.json b/package.json index 910d856..7662338 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ }, "license": "MIT", "dependencies": { + "@prisma/client": "^5.18.0", "axios": "0.26.0", "debug": "4.1.1", "handlebars": "^4.7.7", @@ -83,6 +84,7 @@ "chai": "4.3.6", "eslint": "8.10.0", "mocha": "9.2.1", + "prisma": "^5.18.0", "sinon": "13.0.1" }, "funding": { diff --git a/prisma-setup.js b/prisma-setup.js new file mode 100644 index 0000000..2be2d82 --- /dev/null +++ b/prisma-setup.js @@ -0,0 +1,47 @@ +const fs = require('fs'); +const path = require('path'); + +const schemaContent = ` +datasource db { + provider = "sqlserver" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" +} + +model StatusLog { + id Int @id @default(autoincrement()) + timestamp DateTime + cpuCount Int + memory Float + pid Int + ppid Int + ctime BigInt + elapsed Float + load1 Float + load5 Float + load15 Float + heapTotal BigInt + heapUsed BigInt + response2xx Int + response3xx Int + response4xx Int + response5xx Int + responseMean Float + createdAt DateTime @default(now()) +} +`; + +const prismaDir = path.join(process.cwd(), 'prisma'); +const schemaPath = path.join(prismaDir, 'schema.prisma'); + +if (!fs.existsSync(prismaDir)) { + fs.mkdirSync(prismaDir); +} + +fs.writeFileSync(schemaPath, schemaContent); + +console.log('Prisma schema created. Please run `npx prisma generate` to generate the Prisma client.'); +console.log('Make sure to set the DATABASE_URL environment variable in your .env file.'); \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma new file mode 100644 index 0000000..e37493b --- /dev/null +++ b/prisma/schema.prisma @@ -0,0 +1,30 @@ +datasource db { + provider = "sqlserver" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" +} + +model StatusLog { + id Int @id @default(autoincrement()) + timestamp DateTime + cpuCount Int + memory Float + pid Int + ppid Int + ctime BigInt + elapsed Float + load1 Float + load5 Float + load15 Float + heapTotal BigInt + heapUsed BigInt + response2xx Int + response3xx Int + response4xx Int + response5xx Int + responseMean Float + createdAt DateTime @default(now()) +} \ No newline at end of file diff --git a/src/helpers/default-config.js b/src/helpers/default-config.js index 563acf6..8c303fd 100644 --- a/src/helpers/default-config.js +++ b/src/helpers/default-config.js @@ -32,4 +32,5 @@ module.exports = { }, ignoreStartsWith: '/admin', healthChecks: [], -}; + databaseLoggingInterval: 60, // New option for database logging interval +}; \ No newline at end of file diff --git a/src/helpers/gather-os-metrics.js b/src/helpers/gather-os-metrics.js index c886a02..709667f 100644 --- a/src/helpers/gather-os-metrics.js +++ b/src/helpers/gather-os-metrics.js @@ -3,16 +3,13 @@ const os = require('os'); const v8 = require('v8'); const sendMetrics = require('./send-metrics'); const debug = require('debug')('express-status-monitor'); +const { PrismaClient } = require('@prisma/client'); -let eventLoopStats; // eslint-disable-line +const prisma = new PrismaClient(); -try { - eventLoopStats = require('event-loop-stats'); // eslint-disable-line -} catch (error) { - console.warn('event-loop-stats not found, ignoring event loop metrics...'); -} +let lastDatabaseLog = 0; -module.exports = (io, span) => { +module.exports = (io, span, config) => { const defaultResponse = { 2: 0, 3: 0, @@ -37,19 +34,42 @@ module.exports = (io, span) => { stat.timestamp = Date.now(); stat.heap = v8.getHeapStatistics(); - if (eventLoopStats) { - stat.loop = eventLoopStats.sense(); - } - span.os.push(stat); if (!span.responses[0] || (last.timestamp + span.interval) * 1000 < Date.now()) { span.responses.push(defaultResponse); } - // todo: I think this check should be moved somewhere else + // Database logging + if (stat.timestamp - lastDatabaseLog >= config.databaseLoggingInterval * 1000) { + lastDatabaseLog = stat.timestamp; + prisma.statusLog.create({ + data: { + timestamp: new Date(stat.timestamp), + cpuCount: os.cpus().length, + memory: stat.memory, + pid: stat.pid, + ppid: stat.ppid, + ctime: BigInt(stat.ctime), + elapsed: stat.elapsed, + load1: stat.load[0], + load5: stat.load[1], + load15: stat.load[2], + heapTotal: BigInt(stat.heap.total_heap_size), + heapUsed: BigInt(stat.heap.used_heap_size), + response2xx: last[2], + response3xx: last[3], + response4xx: last[4], + response5xx: last[5], + responseMean: last.mean, + }, + }).catch(error => { + debug('Error logging to database:', error); + }); + } + if (span.os.length >= span.retention) span.os.shift(); if (span.responses[0] && span.responses.length > span.retention) span.responses.shift(); sendMetrics(io, span); }); -}; +}; \ No newline at end of file diff --git a/src/helpers/socket-io-init.js b/src/helpers/socket-io-init.js index d897070..e2db27d 100644 --- a/src/helpers/socket-io-init.js +++ b/src/helpers/socket-io-init.js @@ -1,7 +1,3 @@ -/* eslint strict: "off", init-declarations: "off" */ - -'use strict'; - const socketIo = require('socket.io'); const gatherOsMetrics = require('./gather-os-metrics'); @@ -39,10 +35,10 @@ module.exports = (server, config) => { config.spans.forEach(span => { span.os = []; span.responses = []; - const interval = setInterval(() => gatherOsMetrics(io, span), span.interval * 1000); + const interval = setInterval(() => gatherOsMetrics(io, span, config), span.interval * 1000); // Don't keep Node.js process up interval.unref(); }); } -}; +}; \ No newline at end of file diff --git a/src/helpers/validate.js b/src/helpers/validate.js index a623dd3..70ff298 100644 --- a/src/helpers/validate.js +++ b/src/helpers/validate.js @@ -46,5 +46,10 @@ module.exports = config => { ? config.healthChecks : defaultConfig.healthChecks + config.databaseLoggingInterval = + typeof config.databaseLoggingInterval === 'number' + ? config.databaseLoggingInterval + : defaultConfig.databaseLoggingInterval; + return config; }; From 1c920944ea64233075efe23a657192388c5b456a Mon Sep 17 00:00:00 2001 From: intern1-arizon Date: Wed, 14 Aug 2024 14:45:57 +0530 Subject: [PATCH 2/5] readme updated --- README.md | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/README.md b/README.md index 70c965f..6c76f37 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,87 @@ Simple, self-hosted module based on Socket.io and Chart.js to report realtime se Note: This plugin works on Node versions > 4.x +## Database Setup + +This package now includes database logging using Prisma with SQL Server. Follow these steps to set up: + +1. In your main project, create a `.env` file in the root directory if it doesn't exist already. Add the following line, replacing the placeholders with your actual database details: + + ``` + DATABASE_URL="sqlserver://localhost:1433;database=your_database;user=your_username;password=your_password;trustServerCertificate=true" + ``` + +Replace username, password, localhost, and your_database_name with your actual database credentials. + +2. In your main project's root directory, create a `prisma` folder if it doesn't exist. Inside this folder, create a `schema.prisma` file with the following content: + + ```prisma + datasource db { + provider = "sqlserver" + url = env("DATABASE_URL") + } + + generator client { + provider = "prisma-client-js" + } + + model StatusLog { + id Int @id @default(autoincrement()) + timestamp DateTime + cpuCount Int + memory Float + pid Int + ppid Int + ctime BigInt + elapsed Float + load1 Float + load5 Float + load15 Float + heapTotal BigInt + heapUsed BigInt + response2xx Int + response3xx Int + response4xx Int + response5xx Int + responseMean Float + createdAt DateTime @default(now()) + } + ``` + +3. In your main project's root directory, run the following commands: + + ```bash + npx prisma generate + npx prisma db push + ``` + + This will generate the Prisma client and create the necessary table in your database. + +## Usage + +In your main project, initialize the middleware in your Express app: + +```javascript +const express = require('express'); +const statusMonitor = require('express-status-monitor'); + +const app = express(); + +app.use(statusMonitor({ + path: '/status', + databaseLoggingInterval: 60 // Log to database every 60 seconds +})); + +// ... rest of your Express app setup +``` + +Make sure your SQL Server instance is running and accessible before starting your application. + +## Viewing Status + +Once your app is running, you can view the status page by navigating to the path you specified (e.g., `http://localhost:3000/status`). + + ## Run examples 1. Go to `cd examples/` From e0f7f37fdac57c9eae6ff51335186f7ee5fe1cf7 Mon Sep 17 00:00:00 2001 From: intern1-arizon Date: Tue, 10 Sep 2024 15:55:24 +0530 Subject: [PATCH 3/5] starts logging when server starts 1 --- README.md | 2 +- src/helpers/gather-os-metrics.js | 6 +++-- src/helpers/socket-io-init.js | 39 ++++++++++++++++++-------------- src/middleware-wrapper.js | 15 ++++-------- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 6c76f37..63c7ead 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ This package now includes database logging using Prisma with SQL Server. Follow Replace username, password, localhost, and your_database_name with your actual database credentials. -2. In your main project's root directory, create a `prisma` folder if it doesn't exist. Inside this folder, create a `schema.prisma` file with the following content: +2. In your main project's root directory, create a `prisma` folder if it doesn't exist. Inside this folder, create a `schema.prisma` file if it doesn't exist and add the following content: ```prisma datasource db { diff --git a/src/helpers/gather-os-metrics.js b/src/helpers/gather-os-metrics.js index 709667f..26fc31d 100644 --- a/src/helpers/gather-os-metrics.js +++ b/src/helpers/gather-os-metrics.js @@ -26,7 +26,7 @@ module.exports = (io, span, config) => { return; } - const last = span.responses[span.responses.length - 1]; + const last = span.responses[span.responses.length - 1] || defaultResponse; // Convert from B to MB stat.memory = stat.memory / 1024 / 1024; @@ -70,6 +70,8 @@ module.exports = (io, span, config) => { if (span.os.length >= span.retention) span.os.shift(); if (span.responses[0] && span.responses.length > span.retention) span.responses.shift(); - sendMetrics(io, span); + if (io) { + sendMetrics(io, span); + } }); }; \ No newline at end of file diff --git a/src/helpers/socket-io-init.js b/src/helpers/socket-io-init.js index e2db27d..38e8deb 100644 --- a/src/helpers/socket-io-init.js +++ b/src/helpers/socket-io-init.js @@ -12,25 +12,27 @@ const addSocketEvents = (socket, config) => { module.exports = (server, config) => { if (io === null || io === undefined) { - if (config.websocket !== null) { - io = config.websocket; - } else { - io = socketIo(server); - } - - io.on('connection', socket => { - if (config.authorize) { - config - .authorize(socket) - .then(authorized => { - if (!authorized) socket.disconnect('unauthorized'); - else addSocketEvents(socket, config); - }) - .catch(() => socket.disconnect('unauthorized')); + if (server) { + if (config.websocket !== null) { + io = config.websocket; } else { - addSocketEvents(socket, config); + io = socketIo(server); } - }); + + io.on('connection', socket => { + if (config.authorize) { + config + .authorize(socket) + .then(authorized => { + if (!authorized) socket.disconnect('unauthorized'); + else addSocketEvents(socket, config); + }) + .catch(() => socket.disconnect('unauthorized')); + } else { + addSocketEvents(socket, config); + } + }); + } config.spans.forEach(span => { span.os = []; @@ -40,5 +42,8 @@ module.exports = (server, config) => { // Don't keep Node.js process up interval.unref(); }); + + // Start gathering metrics immediately + gatherOsMetrics(io, config.spans[0], config); } }; \ No newline at end of file diff --git a/src/middleware-wrapper.js b/src/middleware-wrapper.js index 34f0eaa..81b695b 100644 --- a/src/middleware-wrapper.js +++ b/src/middleware-wrapper.js @@ -64,16 +64,9 @@ const middlewareWrapper = config => { } }; - /* Provide two properties, the middleware and HTML page renderer separately - * so that the HTML page can be authenticated while the middleware can be - * earlier in the request handling chain. Use like: - * ``` - * const statusMonitor = require('express-status-monitor')(config); - * server.use(statusMonitor); - * server.get('/status', isAuthenticated, statusMonitor.pageRoute); - * ``` - * discussion: https://github.com/RafalWilinski/express-status-monitor/issues/63 - */ + // Start logging immediately + socketIoInit(null, validatedConfig); + middleware.middleware = middleware; middleware.pageRoute = (req, res) => { healthChecker(validatedConfig.healthChecks).then(results => { @@ -84,4 +77,4 @@ const middlewareWrapper = config => { return middleware; }; -module.exports = middlewareWrapper; +module.exports = middlewareWrapper; \ No newline at end of file From c90fa29de1b145b02bba6c4097e20d4d7c2b7c37 Mon Sep 17 00:00:00 2001 From: intern1-arizon Date: Tue, 10 Sep 2024 16:27:45 +0530 Subject: [PATCH 4/5] Revert "starts logging when server starts 1" This reverts commit e0f7f37fdac57c9eae6ff51335186f7ee5fe1cf7. --- README.md | 2 +- src/helpers/gather-os-metrics.js | 6 ++--- src/helpers/socket-io-init.js | 39 ++++++++++++++------------------ src/middleware-wrapper.js | 15 ++++++++---- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 63c7ead..6c76f37 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ This package now includes database logging using Prisma with SQL Server. Follow Replace username, password, localhost, and your_database_name with your actual database credentials. -2. In your main project's root directory, create a `prisma` folder if it doesn't exist. Inside this folder, create a `schema.prisma` file if it doesn't exist and add the following content: +2. In your main project's root directory, create a `prisma` folder if it doesn't exist. Inside this folder, create a `schema.prisma` file with the following content: ```prisma datasource db { diff --git a/src/helpers/gather-os-metrics.js b/src/helpers/gather-os-metrics.js index 26fc31d..709667f 100644 --- a/src/helpers/gather-os-metrics.js +++ b/src/helpers/gather-os-metrics.js @@ -26,7 +26,7 @@ module.exports = (io, span, config) => { return; } - const last = span.responses[span.responses.length - 1] || defaultResponse; + const last = span.responses[span.responses.length - 1]; // Convert from B to MB stat.memory = stat.memory / 1024 / 1024; @@ -70,8 +70,6 @@ module.exports = (io, span, config) => { if (span.os.length >= span.retention) span.os.shift(); if (span.responses[0] && span.responses.length > span.retention) span.responses.shift(); - if (io) { - sendMetrics(io, span); - } + sendMetrics(io, span); }); }; \ No newline at end of file diff --git a/src/helpers/socket-io-init.js b/src/helpers/socket-io-init.js index 38e8deb..e2db27d 100644 --- a/src/helpers/socket-io-init.js +++ b/src/helpers/socket-io-init.js @@ -12,27 +12,25 @@ const addSocketEvents = (socket, config) => { module.exports = (server, config) => { if (io === null || io === undefined) { - if (server) { - if (config.websocket !== null) { - io = config.websocket; + if (config.websocket !== null) { + io = config.websocket; + } else { + io = socketIo(server); + } + + io.on('connection', socket => { + if (config.authorize) { + config + .authorize(socket) + .then(authorized => { + if (!authorized) socket.disconnect('unauthorized'); + else addSocketEvents(socket, config); + }) + .catch(() => socket.disconnect('unauthorized')); } else { - io = socketIo(server); + addSocketEvents(socket, config); } - - io.on('connection', socket => { - if (config.authorize) { - config - .authorize(socket) - .then(authorized => { - if (!authorized) socket.disconnect('unauthorized'); - else addSocketEvents(socket, config); - }) - .catch(() => socket.disconnect('unauthorized')); - } else { - addSocketEvents(socket, config); - } - }); - } + }); config.spans.forEach(span => { span.os = []; @@ -42,8 +40,5 @@ module.exports = (server, config) => { // Don't keep Node.js process up interval.unref(); }); - - // Start gathering metrics immediately - gatherOsMetrics(io, config.spans[0], config); } }; \ No newline at end of file diff --git a/src/middleware-wrapper.js b/src/middleware-wrapper.js index 81b695b..34f0eaa 100644 --- a/src/middleware-wrapper.js +++ b/src/middleware-wrapper.js @@ -64,9 +64,16 @@ const middlewareWrapper = config => { } }; - // Start logging immediately - socketIoInit(null, validatedConfig); - + /* Provide two properties, the middleware and HTML page renderer separately + * so that the HTML page can be authenticated while the middleware can be + * earlier in the request handling chain. Use like: + * ``` + * const statusMonitor = require('express-status-monitor')(config); + * server.use(statusMonitor); + * server.get('/status', isAuthenticated, statusMonitor.pageRoute); + * ``` + * discussion: https://github.com/RafalWilinski/express-status-monitor/issues/63 + */ middleware.middleware = middleware; middleware.pageRoute = (req, res) => { healthChecker(validatedConfig.healthChecks).then(results => { @@ -77,4 +84,4 @@ const middlewareWrapper = config => { return middleware; }; -module.exports = middlewareWrapper; \ No newline at end of file +module.exports = middlewareWrapper; From 1804c3a22b959994e0688e390d66e26c513eae58 Mon Sep 17 00:00:00 2001 From: intern1-arizon Date: Tue, 10 Sep 2024 19:16:28 +0530 Subject: [PATCH 5/5] bug fix --- src/helpers/gather-os-metrics.js | 91 ++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 41 deletions(-) diff --git a/src/helpers/gather-os-metrics.js b/src/helpers/gather-os-metrics.js index 709667f..c0a2f77 100644 --- a/src/helpers/gather-os-metrics.js +++ b/src/helpers/gather-os-metrics.js @@ -22,54 +22,63 @@ module.exports = (io, span, config) => { pidusage(process.pid, (err, stat) => { if (err) { - debug(err); + debug('Error in pidusage:', err); return; } - const last = span.responses[span.responses.length - 1]; + if (!stat) { + debug('No stat data returned from pidusage'); + return; + } - // Convert from B to MB - stat.memory = stat.memory / 1024 / 1024; - stat.load = os.loadavg(); - stat.timestamp = Date.now(); - stat.heap = v8.getHeapStatistics(); + try { + const last = span.responses[span.responses.length - 1] || defaultResponse; - span.os.push(stat); - if (!span.responses[0] || (last.timestamp + span.interval) * 1000 < Date.now()) { - span.responses.push(defaultResponse); - } + // Convert from B to MB + stat.memory = stat.memory / 1024 / 1024; + stat.load = os.loadavg(); + stat.timestamp = Date.now(); + stat.heap = v8.getHeapStatistics(); - // Database logging - if (stat.timestamp - lastDatabaseLog >= config.databaseLoggingInterval * 1000) { - lastDatabaseLog = stat.timestamp; - prisma.statusLog.create({ - data: { - timestamp: new Date(stat.timestamp), - cpuCount: os.cpus().length, - memory: stat.memory, - pid: stat.pid, - ppid: stat.ppid, - ctime: BigInt(stat.ctime), - elapsed: stat.elapsed, - load1: stat.load[0], - load5: stat.load[1], - load15: stat.load[2], - heapTotal: BigInt(stat.heap.total_heap_size), - heapUsed: BigInt(stat.heap.used_heap_size), - response2xx: last[2], - response3xx: last[3], - response4xx: last[4], - response5xx: last[5], - responseMean: last.mean, - }, - }).catch(error => { - debug('Error logging to database:', error); - }); - } + span.os.push(stat); + if (!span.responses[0] || (last.timestamp + span.interval) * 1000 < Date.now()) { + span.responses.push(defaultResponse); + } + + // Database logging + if (stat.timestamp - lastDatabaseLog >= config.databaseLoggingInterval * 1000) { + lastDatabaseLog = stat.timestamp; + prisma.statusLog.create({ + data: { + timestamp: new Date(stat.timestamp), + cpuCount: os.cpus().length, + memory: stat.memory, + pid: stat.pid, + ppid: stat.ppid || 0, + ctime: BigInt(stat.ctime || 0), + elapsed: stat.elapsed || 0, + load1: stat.load[0], + load5: stat.load[1], + load15: stat.load[2], + heapTotal: BigInt(stat.heap.total_heap_size), + heapUsed: BigInt(stat.heap.used_heap_size), + response2xx: last[2] || 0, + response3xx: last[3] || 0, + response4xx: last[4] || 0, + response5xx: last[5] || 0, + responseMean: last.mean || 0, + }, + }).catch(error => { + debug('Error logging to database:', error); + }); + } - if (span.os.length >= span.retention) span.os.shift(); - if (span.responses[0] && span.responses.length > span.retention) span.responses.shift(); + if (span.os.length >= span.retention) span.os.shift(); + if (span.responses[0] && span.responses.length > span.retention) span.responses.shift(); - sendMetrics(io, span); + sendMetrics(io, span); + } catch (error) { + debug('Error in gather-os-metrics:', error); + } }); }; \ No newline at end of file