From 88fbf7c182bc13f4ca85bc1bcdaad231fd1b45cb Mon Sep 17 00:00:00 2001 From: Glenn de Haan Date: Sun, 24 Mar 2024 12:21:08 +0100 Subject: [PATCH] Implemented a logger. Fix UniFi error messages. Implemented additional UniFi logging --- modules/log.js | 42 ++++++++++++++++++++++++++++++++++++++++++ modules/unifi.js | 35 +++++++++++++++++++---------------- package-lock.json | 13 ++++++++++++- package.json | 1 + server.js | 21 +++++++++++---------- 5 files changed, 85 insertions(+), 27 deletions(-) create mode 100644 modules/log.js diff --git a/modules/log.js b/modules/log.js new file mode 100644 index 0000000..b0ec485 --- /dev/null +++ b/modules/log.js @@ -0,0 +1,42 @@ +/** + * Import base packages + */ +const log = require('js-logger'); + +/** + * Check if we are using the dev version + */ +const dev = process.env.NODE_ENV !== 'production'; + +/** + * Setup logger + */ +const consoleLogger = log.createDefaultHandler({ + formatter: (messages, context) => { + // Get current date, change this to the current timezone, then generate a date-time string + const utcDate = new Date(); + const offset = utcDate.getTimezoneOffset(); + const date = new Date(utcDate.getTime() - (offset * 60 * 1000)); + const dateTimeString = date.toISOString().replace('T', ' ').replace('Z', ''); + + // Prefix each log message with a timestamp and log level + messages.unshift(`${dateTimeString} ${context.level.name}${context.level.name === 'INFO' || context.level.name === 'WARN' ? ' ' : ''}`); + } +}); + +/** + * Set all logger handlers + */ +log.setHandler((messages, context) => { + consoleLogger(messages, context); +}); + +/** + * Set log level + */ +log.setLevel(dev ? log.TRACE : log.INFO); + +/** + * Export the application logger + */ +module.exports = log; diff --git a/modules/unifi.js b/modules/unifi.js index c5c8927..4a2bf05 100644 --- a/modules/unifi.js +++ b/modules/unifi.js @@ -7,6 +7,7 @@ const unifi = require('node-unifi'); * Import own modules */ const configProvider = require('./config'); +const log = require('./log'); /** * Import own modules @@ -51,25 +52,26 @@ module.exports = (type, create = true) => { controller.createVouchers(type.expiration, 1, parseInt(type.usage) === 1 ? 1 : 0, null, typeof type.upload !== "undefined" ? type.upload : null, typeof type.download !== "undefined" ? type.download : null, typeof type.megabytes !== "undefined" ? type.megabytes : null).then((voucher_data) => { controller.getVouchers(voucher_data[0].create_time).then((voucher_data_complete) => { const voucher = `${[voucher_data_complete[0].code.slice(0, 5), '-', voucher_data_complete[0].code.slice(5)].join('')}`; + log.info(`[UniFi] Created voucher with code: ${voucher}`); resolve(voucher); }).catch((e) => { - console.log('[UniFi] Error while getting voucher!'); - console.log(e); + log.error('[UniFi] Error while getting voucher!'); + log.error(e); reject('[UniFi] Error while getting voucher!'); }); }).catch((e) => { - console.log('[UniFi] Error while creating voucher!'); - console.log(e); + log.error('[UniFi] Error while creating voucher!'); + log.error(e); reject('[UniFi] Error while creating voucher!'); }); }).catch((e) => { - console.log('[UniFi] Error while getting site stats!'); - console.log(e); + log.error('[UniFi] Error while getting site stats!'); + log.error(e); reject('[UniFi] Error while getting site stats!'); }); }).catch((e) => { - console.log('[UniFi] Error while logging in!'); - console.log(e); + log.error('[UniFi] Error while logging in!'); + log.error(e); reject('[UniFi] Error while logging in!'); }); }); @@ -88,25 +90,26 @@ module.exports = (type, create = true) => { }); /** - * Login and create a voucher + * Login and get vouchers */ controller.login(config.unifi.username, config.unifi.password).then(() => { controller.getSitesStats().then(() => { controller.getVouchers().then((vouchers) => { + log.info(`[UniFi] Found ${vouchers.length} voucher(s)`); resolve(vouchers); }).catch((e) => { - console.log('[UniFi] Error while getting voucher!'); - console.log(e); - reject('[UniFi] Error while getting voucher!'); + log.error('[UniFi] Error while getting vouchers!'); + log.error(e); + reject('[UniFi] Error while getting vouchers!'); }); }).catch((e) => { - console.log('[UniFi] Error while getting site stats!'); - console.log(e); + log.error('[UniFi] Error while getting site stats!'); + log.error(e); reject('[UniFi] Error while getting site stats!'); }); }).catch((e) => { - console.log('[UniFi] Error while logging in!'); - console.log(e); + log.error('[UniFi] Error while logging in!'); + log.error(e); reject('[UniFi] Error while logging in!'); }); }); diff --git a/package-lock.json b/package-lock.json index 079ef6d..e468e20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "cookie-parser": "^1.4.6", "ejs": "^3.1.9", "express": "^4.19.1", + "js-logger": "^1.6.1", "multer": "^1.4.5-lts.1", "node-unifi": "^2.5.1", "tailwindcss": "^3.4.1", @@ -22,7 +23,7 @@ "nodemon": "^3.1.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@alloc/quick-lru": { @@ -1134,6 +1135,11 @@ "jiti": "bin/jiti.js" } }, + "node_modules/js-logger": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/js-logger/-/js-logger-1.6.1.tgz", + "integrity": "sha512-yTgMCPXVjhmg28CuUH8CKjU+cIKL/G+zTu4Fn4lQxs8mRFH/03QTNvEFngcxfg/gRDiQAOoyCKmMTOm9ayOzXA==" + }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -3373,6 +3379,11 @@ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==" }, + "js-logger": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/js-logger/-/js-logger-1.6.1.tgz", + "integrity": "sha512-yTgMCPXVjhmg28CuUH8CKjU+cIKL/G+zTu4Fn4lQxs8mRFH/03QTNvEFngcxfg/gRDiQAOoyCKmMTOm9ayOzXA==" + }, "lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", diff --git a/package.json b/package.json index 5d4379a..8ba3f3e 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "cookie-parser": "^1.4.6", "ejs": "^3.1.9", "express": "^4.19.1", + "js-logger": "^1.6.1", "multer": "^1.4.5-lts.1", "node-unifi": "^2.5.1", "tailwindcss": "^3.4.1", diff --git a/server.js b/server.js index a61e5fd..c461283 100644 --- a/server.js +++ b/server.js @@ -11,6 +11,7 @@ const cookieParser = require('cookie-parser'); * Import own modules */ const config = require('./modules/config'); +const log = require('./modules/log'); const logo = require('./modules/logo'); const types = require('./modules/types'); const time = require('./modules/time'); @@ -46,32 +47,32 @@ logo(); * Log external config */ if (fs.existsSync('/data/options.json')) { - console.log('[Options] Found at /data/options.json'); + log.info('[Options] Found at /data/options.json'); } /** * Log service status */ -console.log(`[Service][Web] ${webService ? 'Enabled!' : 'Disabled!'}`); -console.log(`[Service][Api] ${apiService ? 'Enabled!' : 'Disabled!'}`); +log.info(`[Service][Web] ${webService ? 'Enabled!' : 'Disabled!'}`); +log.info(`[Service][Api] ${apiService ? 'Enabled!' : 'Disabled!'}`); /** * Log voucher types */ -console.log('[VoucherType] Loaded the following types:'); +log.info('[VoucherType] Loaded the following types:'); voucherTypes.forEach((type, key) => { - console.log(`[VoucherType][${key}] ${time(type.expiration)}, ${type.usage === '1' ? 'single-use' : 'multi-use'}${typeof type.upload === "undefined" && typeof type.download === "undefined" && typeof type.megabytes === "undefined" ? ', no limits' : `${typeof type.upload !== "undefined" ? `, upload bandwidth limit: ${type.upload} kb/s` : ''}${typeof type.download !== "undefined" ? `, download bandwidth limit: ${type.download} kb/s` : ''}${typeof type.megabytes !== "undefined" ? `, quota limit: ${type.megabytes} mb` : ''}`}`); + log.info(`[VoucherType][${key}] ${time(type.expiration)}, ${type.usage === '1' ? 'single-use' : 'multi-use'}${typeof type.upload === "undefined" && typeof type.download === "undefined" && typeof type.megabytes === "undefined" ? ', no limits' : `${typeof type.upload !== "undefined" ? `, upload bandwidth limit: ${type.upload} kb/s` : ''}${typeof type.download !== "undefined" ? `, download bandwidth limit: ${type.download} kb/s` : ''}${typeof type.megabytes !== "undefined" ? `, quota limit: ${type.megabytes} mb` : ''}`}`); }); /** * Log auth status */ -console.log(`[Auth] ${authDisabled ? 'Disabled!' : 'Enabled!'}`); +log.info(`[Auth] ${authDisabled ? 'Disabled!' : 'Enabled!'}`); /** * Log controller */ -console.log(`[UniFi] Using Controller on: ${config('unifi_ip') || process.env.UNIFI_IP || '192.168.1.1'}:${config('unifi_port') || process.env.UNIFI_PORT || 443} (Site ID: ${config('unifi_site_id') || process.env.UNIFI_SITE_ID || 'default'})`); +log.info(`[UniFi] Using Controller on: ${config('unifi_ip') || process.env.UNIFI_IP || '192.168.1.1'}:${config('unifi_port') || process.env.UNIFI_PORT || 443} (Site ID: ${config('unifi_site_id') || process.env.UNIFI_SITE_ID || 'default'})`); /** * Trust proxy @@ -122,9 +123,9 @@ app.use(sid); */ app.use((req, res, next) => { if(req.originalUrl.includes('/images') || req.originalUrl.includes('/dist') || req.originalUrl.includes('/manifest')) { - console.log(`[Web]: ${req.originalUrl}`); + log.info(`[Web]: ${req.originalUrl}`); } else { - console.log(`[Web][${req.sid}]: ${req.originalUrl}`); + log.info(`[Web][${req.sid}]: ${req.originalUrl}`); } next(); @@ -324,5 +325,5 @@ app.disable('x-powered-by'); * Start listening on port */ app.listen(3000, '0.0.0.0', () => { - console.log(`[App] Running on: 0.0.0.0:3000`); + log.info(`[App] Running on: 0.0.0.0:3000`); });