From d5c9f9818dffdc17e481c8b040689e721fb762f5 Mon Sep 17 00:00:00 2001 From: Houwie7000 Date: Wed, 20 Nov 2024 18:04:52 +0100 Subject: [PATCH 1/8] Added logging for sql queries --- InfoLogger/lib/services/QueryService.js | 3 + .../lib/utils/preparedStatementParser.js | 55 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 InfoLogger/lib/utils/preparedStatementParser.js diff --git a/InfoLogger/lib/services/QueryService.js b/InfoLogger/lib/services/QueryService.js index 0d211ae23..9007265da 100644 --- a/InfoLogger/lib/services/QueryService.js +++ b/InfoLogger/lib/services/QueryService.js @@ -15,6 +15,7 @@ const mariadb = require('mariadb'); const { LogManager } = require('@aliceo2/web-ui'); const { fromSqlToNativeError } = require('../utils/fromSqlToNativeError'); +const { processPreparedSQLStatement } = require('../utils/preparedStatementParser'); class QueryService { /** @@ -82,6 +83,8 @@ class QueryService { const requestRows = `SELECT * FROM \`messages\` ${criteriaString} ORDER BY \`TIMESTAMP\` LIMIT ?;`; const startTime = Date.now(); // ms + this._logger.debugMessage(`SQL to execute: ${processPreparedSQLStatement(requestRows, values, limit)}`); + let rows = []; try { rows = await this._pool.query( diff --git a/InfoLogger/lib/utils/preparedStatementParser.js b/InfoLogger/lib/utils/preparedStatementParser.js new file mode 100644 index 000000000..f87348f9d --- /dev/null +++ b/InfoLogger/lib/utils/preparedStatementParser.js @@ -0,0 +1,55 @@ +/** + * @license + * Copyright 2019-2020 CERN and copyright holders of ALICE O2. + * See http://alice-o2.web.cern.ch/copyright for details of the copyright holders. + * All rights not expressly granted are reserved. + * + * This software is distributed under the terms of the GNU General Public + * License v3 (GPL Version 3), copied verbatim in the file "COPYING". + * + * In applying this license CERN does not waive the privileges and immunities + * granted to it by virtue of its status as an Intergovernmental Organization + * or submit itself to any jurisdiction. + */ + +/** + * Translate the SQL prepared statement to a regular SQL query. + * @param {string} requestRows The prepared SQL statement. + * @param {any} values Values for the prepared SQL statement. + * @param {number} limit Configured limit of the sql query results. + * @returns {string} the resulting SQL query as a string. + */ +function processPreparedSQLStatement(requestRows, values, limit) { + let sqlQuery = requestRows; + + const iterator = values.values(); + for (const value of iterator) { + if (Array.isArray(value)) { + sqlQuery = sqlQuery.replace('?', convertArrayToString(value)); + } else { + sqlQuery = sqlQuery.replace('?', value); + } + } + sqlQuery = sqlQuery.replace('?', limit); + + return sqlQuery; +} + +/** + * Helper function that converts arrays to strings with a single quote around the values. + * This function can later be expanded to handle values other than strings in the array. + * @param {Array} array Array to convert to string. + * @returns {string} a string representation of the input array. + */ +function convertArrayToString(array) { + let processedArray = ''; + array.forEach((v) => { + if (typeof v == 'string') { + processedArray += `'${v}',`; + } + }); + processedArray = processedArray.substring(0, processedArray.length - 1); + return processedArray; +} + +module.exports.processPreparedSQLStatement = processPreparedSQLStatement; From 5dba3c833ceab14b34339154693b76f41f61c4e1 Mon Sep 17 00:00:00 2001 From: Jasper Houweling Date: Thu, 21 Nov 2024 19:22:15 +0100 Subject: [PATCH 2/8] Fixed SQL formatting in logs --- InfoLogger/lib/utils/preparedStatementParser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InfoLogger/lib/utils/preparedStatementParser.js b/InfoLogger/lib/utils/preparedStatementParser.js index f87348f9d..2c980f2d2 100644 --- a/InfoLogger/lib/utils/preparedStatementParser.js +++ b/InfoLogger/lib/utils/preparedStatementParser.js @@ -27,7 +27,7 @@ function processPreparedSQLStatement(requestRows, values, limit) { if (Array.isArray(value)) { sqlQuery = sqlQuery.replace('?', convertArrayToString(value)); } else { - sqlQuery = sqlQuery.replace('?', value); + sqlQuery = sqlQuery.replace('?', `'${value}'`); } } sqlQuery = sqlQuery.replace('?', limit); From ac4988f6ac70dc916b0726a32355fabb80a80b69 Mon Sep 17 00:00:00 2001 From: Jasper Houweling Date: Sun, 24 Nov 2024 16:39:32 +0100 Subject: [PATCH 3/8] Added Live mode logging --- InfoLogger/lib/api.js | 8 +++++ .../lib/controller/LoggingController.js | 34 +++++++++++++++++++ InfoLogger/public/log/Log.js | 11 ++++++ 3 files changed, 53 insertions(+) create mode 100644 InfoLogger/lib/controller/LoggingController.js diff --git a/InfoLogger/lib/api.js b/InfoLogger/lib/api.js index e9f3450af..c53b3fcd5 100644 --- a/InfoLogger/lib/api.js +++ b/InfoLogger/lib/api.js @@ -26,6 +26,7 @@ const { serviceAvailabilityCheck } = require('./middleware/serviceAvailabilityCh const projPackage = require('./../package.json'); const config = require('./configProvider.js'); +const { LoggingController } = require('./controller/LoggingController.js'); let liveService = null; let queryService = null; @@ -42,6 +43,7 @@ module.exports.attachTo = async (http, ws) => { queryService.checkConnection(1, false); } const queryController = new QueryController(queryService); + const loggingController = new LoggingController(); const statusController = new StatusController(config, projPackage, ws); statusController.querySource = queryService; @@ -63,6 +65,12 @@ module.exports.attachTo = async (http, ws) => { { public: true }, ); + http.post( + '/logging/LiveFilterLog', + loggingController.postReceiveLogs.bind(loggingController), + { public: true }, + ); + http.get('/status/gui', statusController.getILGStatus.bind(statusController), { public: true }); http.get('/getFrameworkInfo', statusController.frameworkInfo.bind(statusController)); diff --git a/InfoLogger/lib/controller/LoggingController.js b/InfoLogger/lib/controller/LoggingController.js new file mode 100644 index 000000000..21be97d1c --- /dev/null +++ b/InfoLogger/lib/controller/LoggingController.js @@ -0,0 +1,34 @@ +/** + * @license + * Copyright 2019-2020 CERN and copyright holders of ALICE O2. + * See http://alice-o2.web.cern.ch/copyright for details of the copyright holders. + * All rights not expressly granted are reserved. + * + * This software is distributed under the terms of the GNU General Public + * License v3 (GPL Version 3), copied verbatim in the file "COPYING". + * + * In applying this license CERN does not waive the privileges and immunities + * granted to it by virtue of its status as an Intergovernmental Organization + * or submit itself to any jurisdiction. + */ + +const { LogManager } = require('@aliceo2/web-ui'); + +class LoggingController { + constructor() { + this._logger = LogManager.getLogger(`${process.env.npm_config_log_label ?? 'ilg'}/query-ctrl`); + } + + async postReceiveLogs(req, res) { + try { + const liveFilter = req.body; + this._logger.debugMessage(JSON.stringify(liveFilter)); + res.status(200); + } catch (error) { + this._logger.errorMessage(error.toString()); + res.status(400); + } + } +} + +exports.LoggingController = LoggingController; diff --git a/InfoLogger/public/log/Log.js b/InfoLogger/public/log/Log.js index 26f82ed7f..04c1d8528 100644 --- a/InfoLogger/public/log/Log.js +++ b/InfoLogger/public/log/Log.js @@ -354,6 +354,15 @@ export default class Log extends Observable { this.notify(); } + /** + * Log the Filter criteria to the backend. + * Fire and forget function. + * @param {LogFilter.criterias} criteria Criteria to log to the backend. + */ + async logLiveCriteria(criteria) { + await this.model.loader.post('/api/logging/LiveFilterLog', criteria); + } + /** * Forward call to `this.filter.setCriteria`. If live mode is enabled, * alert user that filtering will be affected. @@ -373,6 +382,8 @@ export default class Log extends Observable { } value = copy.join(' '); } + this.logLiveCriteria(this.filter.toObject()); + if (this.filter.setCriteria(field, operator, value)) { if (this.isLiveModeRunning()) { this.model.ws.setFilter(this.model.log.filter.toStringifyFunction()); From fcd0cc2a6cc39b06bc8f70a96613c6c0a5d78a55 Mon Sep 17 00:00:00 2001 From: Houwie7000 Date: Mon, 25 Nov 2024 10:31:19 +0100 Subject: [PATCH 4/8] Revert "Added Live mode logging" This reverts commit ac4988f6ac70dc916b0726a32355fabb80a80b69. --- InfoLogger/lib/api.js | 8 ----- .../lib/controller/LoggingController.js | 34 ------------------- InfoLogger/public/log/Log.js | 11 ------ 3 files changed, 53 deletions(-) delete mode 100644 InfoLogger/lib/controller/LoggingController.js diff --git a/InfoLogger/lib/api.js b/InfoLogger/lib/api.js index c53b3fcd5..e9f3450af 100644 --- a/InfoLogger/lib/api.js +++ b/InfoLogger/lib/api.js @@ -26,7 +26,6 @@ const { serviceAvailabilityCheck } = require('./middleware/serviceAvailabilityCh const projPackage = require('./../package.json'); const config = require('./configProvider.js'); -const { LoggingController } = require('./controller/LoggingController.js'); let liveService = null; let queryService = null; @@ -43,7 +42,6 @@ module.exports.attachTo = async (http, ws) => { queryService.checkConnection(1, false); } const queryController = new QueryController(queryService); - const loggingController = new LoggingController(); const statusController = new StatusController(config, projPackage, ws); statusController.querySource = queryService; @@ -65,12 +63,6 @@ module.exports.attachTo = async (http, ws) => { { public: true }, ); - http.post( - '/logging/LiveFilterLog', - loggingController.postReceiveLogs.bind(loggingController), - { public: true }, - ); - http.get('/status/gui', statusController.getILGStatus.bind(statusController), { public: true }); http.get('/getFrameworkInfo', statusController.frameworkInfo.bind(statusController)); diff --git a/InfoLogger/lib/controller/LoggingController.js b/InfoLogger/lib/controller/LoggingController.js deleted file mode 100644 index 21be97d1c..000000000 --- a/InfoLogger/lib/controller/LoggingController.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @license - * Copyright 2019-2020 CERN and copyright holders of ALICE O2. - * See http://alice-o2.web.cern.ch/copyright for details of the copyright holders. - * All rights not expressly granted are reserved. - * - * This software is distributed under the terms of the GNU General Public - * License v3 (GPL Version 3), copied verbatim in the file "COPYING". - * - * In applying this license CERN does not waive the privileges and immunities - * granted to it by virtue of its status as an Intergovernmental Organization - * or submit itself to any jurisdiction. - */ - -const { LogManager } = require('@aliceo2/web-ui'); - -class LoggingController { - constructor() { - this._logger = LogManager.getLogger(`${process.env.npm_config_log_label ?? 'ilg'}/query-ctrl`); - } - - async postReceiveLogs(req, res) { - try { - const liveFilter = req.body; - this._logger.debugMessage(JSON.stringify(liveFilter)); - res.status(200); - } catch (error) { - this._logger.errorMessage(error.toString()); - res.status(400); - } - } -} - -exports.LoggingController = LoggingController; diff --git a/InfoLogger/public/log/Log.js b/InfoLogger/public/log/Log.js index 04c1d8528..26f82ed7f 100644 --- a/InfoLogger/public/log/Log.js +++ b/InfoLogger/public/log/Log.js @@ -354,15 +354,6 @@ export default class Log extends Observable { this.notify(); } - /** - * Log the Filter criteria to the backend. - * Fire and forget function. - * @param {LogFilter.criterias} criteria Criteria to log to the backend. - */ - async logLiveCriteria(criteria) { - await this.model.loader.post('/api/logging/LiveFilterLog', criteria); - } - /** * Forward call to `this.filter.setCriteria`. If live mode is enabled, * alert user that filtering will be affected. @@ -382,8 +373,6 @@ export default class Log extends Observable { } value = copy.join(' '); } - this.logLiveCriteria(this.filter.toObject()); - if (this.filter.setCriteria(field, operator, value)) { if (this.isLiveModeRunning()) { this.model.ws.setFilter(this.model.log.filter.toStringifyFunction()); From 59497e94c5a4603d0b98ae92f6e5b7b4a023166d Mon Sep 17 00:00:00 2001 From: Jasper Houweling Date: Mon, 25 Nov 2024 16:19:06 +0100 Subject: [PATCH 5/8] Added tests for SQL logging --- .../lib/services/mocha-query-service.test.js | 51 +++++++++++++++---- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/InfoLogger/test/lib/services/mocha-query-service.test.js b/InfoLogger/test/lib/services/mocha-query-service.test.js index 21cebb18b..a71e76c26 100644 --- a/InfoLogger/test/lib/services/mocha-query-service.test.js +++ b/InfoLogger/test/lib/services/mocha-query-service.test.js @@ -17,8 +17,9 @@ const sinon = require('sinon'); const config = require('../../../config-default.js'); const { QueryService } = require('../../../lib/services/QueryService.js'); const { UnauthorizedAccessError, TimeoutError } = require('@aliceo2/web-ui'); +const { processPreparedSQLStatement } = require('../../../lib/utils/preparedStatementParser.js'); -describe(`'QueryService' test suite`, () => { +describe('\'QueryService\' test suite', () => { const filters = { timestamp: { since: -5, @@ -73,7 +74,7 @@ describe(`'QueryService' test suite`, () => { }; const emptySqlDataSource = new QueryService(undefined, {}); - describe(`'checkConnection()' - test suite`, () => { + describe('\'checkConnection()\' - test suite', () => { it('should reject with error when simple query fails', async () => { const sqlDataSource = new QueryService(config.mysql); sqlDataSource._isAvailable = true; @@ -205,6 +206,36 @@ describe(`'QueryService' test suite`, () => { ); }); + it('should be able to fill in a prepared statement and log it when executing a query', async () => { + const sqlDataSource = new QueryService(config.mysql); + sqlDataSource._logger = { + debugMessage: sinon.stub(), + }; + await sqlDataSource.queryFromFilters(realFilters, { limit: 10 }); + const completeSqlQuery = "SELECT * FROM `messages` WHERE `timestamp`>='1563794601.351' AND" + + " `timestamp`<='1563794661.354' AND `hostname` = 'test' AND NOT(`hostname` = 'testEx' AND" + + " `hostname` IS NOT NULL) AND `severity` IN ('D','W') ORDER BY `TIMESTAMP` LIMIT 10;"; + assert.strictEqual(sqlDataSource._logger.debugMessage.calledWith(`SQL to execute: ${completeSqlQuery}`), true); + // Test the processPreparedSQLStatement() function individually. + const requestedRows = 'SELECT * FROM `messages` WHERE `timestamp`>=? AND `timestamp`<=? AND `hostname` = ? ' + + 'AND NOT(`hostname` = ? AND `hostname` IS NOT NULL) AND `severity` IN (?) ORDER BY `TIMESTAMP` LIMIT 10'; + const values = [ + '1563794601.351', + '1563794661.354', + 'test', + 'testEx', + [ + 'D', + 'W', + ], + ]; + const sqlProcessedResult = processPreparedSQLStatement(requestedRows, values, 10); + const expectedSqlResult = "SELECT * FROM `messages` WHERE `timestamp`>='1563794601.351' AND `timestamp`" + + "<='1563794661.354' AND `hostname` = 'test' AND NOT(`hostname` = 'testEx' AND `hostname` IS NOT" + + " NULL) AND `severity` IN ('D','W') ORDER BY `TIMESTAMP` LIMIT 10"; + assert.strictEqual(sqlProcessedResult, expectedSqlResult); + }); + it('should successfully return result when filters are provided for querying', async () => { const query = 'SELECT * FROM `messages` WHERE `timestamp`>=? AND `timestamp`<=? AND `hostname` = ? ' + 'AND NOT(`hostname` = ? AND `hostname` IS NOT NULL) AND `severity` IN (?) ORDER BY `TIMESTAMP` LIMIT 10'; @@ -232,7 +263,7 @@ describe(`'QueryService' test suite`, () => { }); }); - describe('queryGroupCountLogsBySeverity() - test suite', ()=> { + describe('queryGroupCountLogsBySeverity() - test suite', () => { it(`should successfully return stats when queried for all known severities even if none is some are not returned by data service`, async () => { const dataService = new QueryService(config.mysql); @@ -255,13 +286,13 @@ describe(`'QueryService' test suite`, () => { it('should throw error if data service throws SQL', async () => { const dataService = new QueryService(config.mysql); dataService._pool = - { - query: sinon.stub().rejects({ - code: 'ER_ACCESS_DENIED_ERROR', - errno: 1045, - sqlMessage: 'Access denied', - }), - }; + { + query: sinon.stub().rejects({ + code: 'ER_ACCESS_DENIED_ERROR', + errno: 1045, + sqlMessage: 'Access denied', + }), + }; await assert.rejects( dataService.queryGroupCountLogsBySeverity(51234), From e7472ce2606fc86568378d4b5b6eccf4b5ca5f6e Mon Sep 17 00:00:00 2001 From: Jasper Houweling Date: Mon, 25 Nov 2024 16:52:22 +0100 Subject: [PATCH 6/8] fixed unit test by faking db answer --- InfoLogger/test/lib/services/mocha-query-service.test.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/InfoLogger/test/lib/services/mocha-query-service.test.js b/InfoLogger/test/lib/services/mocha-query-service.test.js index a71e76c26..ca5241987 100644 --- a/InfoLogger/test/lib/services/mocha-query-service.test.js +++ b/InfoLogger/test/lib/services/mocha-query-service.test.js @@ -211,6 +211,9 @@ describe('\'QueryService\' test suite', () => { sqlDataSource._logger = { debugMessage: sinon.stub(), }; + sqlDataSource._pool = { + query: sinon.stub().resolves([{ hostname: 'test', severity: 'W' }]), + }; await sqlDataSource.queryFromFilters(realFilters, { limit: 10 }); const completeSqlQuery = "SELECT * FROM `messages` WHERE `timestamp`>='1563794601.351' AND" + " `timestamp`<='1563794661.354' AND `hostname` = 'test' AND NOT(`hostname` = 'testEx' AND" + From be3d4ba95212794699733578140fa493cebb0093 Mon Sep 17 00:00:00 2001 From: Jasper Houweling Date: Tue, 26 Nov 2024 15:20:36 +0100 Subject: [PATCH 7/8] Processed feedback. Moved tests to separate file. --- .../lib/utils/preparedStatementParser.js | 8 +- .../services/mocha-preparedStatementParser.js | 79 +++++++++++++++++++ .../lib/services/mocha-query-service.test.js | 34 -------- 3 files changed, 83 insertions(+), 38 deletions(-) create mode 100644 InfoLogger/test/lib/services/mocha-preparedStatementParser.js diff --git a/InfoLogger/lib/utils/preparedStatementParser.js b/InfoLogger/lib/utils/preparedStatementParser.js index 2c980f2d2..c7dc3b8ec 100644 --- a/InfoLogger/lib/utils/preparedStatementParser.js +++ b/InfoLogger/lib/utils/preparedStatementParser.js @@ -14,9 +14,9 @@ /** * Translate the SQL prepared statement to a regular SQL query. - * @param {string} requestRows The prepared SQL statement. - * @param {any} values Values for the prepared SQL statement. - * @param {number} limit Configured limit of the sql query results. + * @param {string} requestRows - The prepared SQL statement. + * @param {object} values - Values for the prepared SQL statement. + * @param {number} limit - Configured limit of the sql query results. * @returns {string} the resulting SQL query as a string. */ function processPreparedSQLStatement(requestRows, values, limit) { @@ -38,7 +38,7 @@ function processPreparedSQLStatement(requestRows, values, limit) { /** * Helper function that converts arrays to strings with a single quote around the values. * This function can later be expanded to handle values other than strings in the array. - * @param {Array} array Array to convert to string. + * @param {Array} array - Array to convert to string. * @returns {string} a string representation of the input array. */ function convertArrayToString(array) { diff --git a/InfoLogger/test/lib/services/mocha-preparedStatementParser.js b/InfoLogger/test/lib/services/mocha-preparedStatementParser.js new file mode 100644 index 000000000..6326c670d --- /dev/null +++ b/InfoLogger/test/lib/services/mocha-preparedStatementParser.js @@ -0,0 +1,79 @@ +/** + * @license + * Copyright 2019-2020 CERN and copyright holders of ALICE O2. + * See http://alice-o2.web.cern.ch/copyright for details of the copyright holders. + * All rights not expressly granted are reserved. + * + * This software is distributed under the terms of the GNU General Public + * License v3 (GPL Version 3), copied verbatim in the file "COPYING". + * + * In applying this license CERN does not waive the privileges and immunities + * granted to it by virtue of its status as an Intergovernmental Organization + * or submit itself to any jurisdiction. + */ + +const assert = require('assert'); +const sinon = require('sinon'); +const config = require('../../../config-default.js'); +const { QueryService } = require('../../../lib/services/QueryService.js'); +const { processPreparedSQLStatement } = require('../../../lib/utils/preparedStatementParser.js'); + +describe('preparedStatementParser() - test suite', () => { + const realFilters = { + timestamp: { + since: -5, + until: -1, + $since: '2019-07-22T11:23:21.351Z', + $until: '2019-07-22T11:24:21.354Z', + }, + hostname: { + match: 'test', + exclude: 'testEx', + $match: 'test', + $exclude: 'testEx', + }, + severity: { + in: 'D I', + $in: ['D', 'W'], + }, + level: { + max: null, // 0, 1, 6, 11, 21 + $max: null, // 0, 1, 6, 11, 21 + }, + }; + + it('should be able to fill in a prepared statement', async () => { + const requestedRows = 'SELECT * FROM `messages` WHERE `timestamp`>=? AND `timestamp`<=? AND `hostname` = ? ' + + 'AND NOT(`hostname` = ? AND `hostname` IS NOT NULL) AND `severity` IN (?) ORDER BY `TIMESTAMP` LIMIT 10'; + const values = [ + '1563794601.351', + '1563794661.354', + 'test', + 'testEx', + [ + 'D', + 'W', + ], + ]; + const sqlProcessedResult = processPreparedSQLStatement(requestedRows, values, 10); + const expectedSqlResult = "SELECT * FROM `messages` WHERE `timestamp`>='1563794601.351' AND `timestamp`" + + "<='1563794661.354' AND `hostname` = 'test' AND NOT(`hostname` = 'testEx' AND `hostname` IS NOT" + + " NULL) AND `severity` IN ('D','W') ORDER BY `TIMESTAMP` LIMIT 10"; + assert.strictEqual(sqlProcessedResult, expectedSqlResult); + }); + + it('should log every executed sql query as debug', async () => { + const sqlDataSource = new QueryService(config.mysql); + sqlDataSource._logger = { + debugMessage: sinon.stub(), + }; + sqlDataSource._pool = { + query: sinon.stub().resolves([{ hostname: 'test', severity: 'W' }]), + }; + await sqlDataSource.queryFromFilters(realFilters, { limit: 10 }); + const completeSqlQuery = "SELECT * FROM `messages` WHERE `timestamp`>='1563794601.351' AND" + + " `timestamp`<='1563794661.354' AND `hostname` = 'test' AND NOT(`hostname` = 'testEx' AND" + + " `hostname` IS NOT NULL) AND `severity` IN ('D','W') ORDER BY `TIMESTAMP` LIMIT 10;"; + assert.strictEqual(sqlDataSource._logger.debugMessage.calledWith(`SQL to execute: ${completeSqlQuery}`), true); + }); +}); diff --git a/InfoLogger/test/lib/services/mocha-query-service.test.js b/InfoLogger/test/lib/services/mocha-query-service.test.js index ca5241987..592be59c5 100644 --- a/InfoLogger/test/lib/services/mocha-query-service.test.js +++ b/InfoLogger/test/lib/services/mocha-query-service.test.js @@ -17,7 +17,6 @@ const sinon = require('sinon'); const config = require('../../../config-default.js'); const { QueryService } = require('../../../lib/services/QueryService.js'); const { UnauthorizedAccessError, TimeoutError } = require('@aliceo2/web-ui'); -const { processPreparedSQLStatement } = require('../../../lib/utils/preparedStatementParser.js'); describe('\'QueryService\' test suite', () => { const filters = { @@ -206,39 +205,6 @@ describe('\'QueryService\' test suite', () => { ); }); - it('should be able to fill in a prepared statement and log it when executing a query', async () => { - const sqlDataSource = new QueryService(config.mysql); - sqlDataSource._logger = { - debugMessage: sinon.stub(), - }; - sqlDataSource._pool = { - query: sinon.stub().resolves([{ hostname: 'test', severity: 'W' }]), - }; - await sqlDataSource.queryFromFilters(realFilters, { limit: 10 }); - const completeSqlQuery = "SELECT * FROM `messages` WHERE `timestamp`>='1563794601.351' AND" + - " `timestamp`<='1563794661.354' AND `hostname` = 'test' AND NOT(`hostname` = 'testEx' AND" + - " `hostname` IS NOT NULL) AND `severity` IN ('D','W') ORDER BY `TIMESTAMP` LIMIT 10;"; - assert.strictEqual(sqlDataSource._logger.debugMessage.calledWith(`SQL to execute: ${completeSqlQuery}`), true); - // Test the processPreparedSQLStatement() function individually. - const requestedRows = 'SELECT * FROM `messages` WHERE `timestamp`>=? AND `timestamp`<=? AND `hostname` = ? ' - + 'AND NOT(`hostname` = ? AND `hostname` IS NOT NULL) AND `severity` IN (?) ORDER BY `TIMESTAMP` LIMIT 10'; - const values = [ - '1563794601.351', - '1563794661.354', - 'test', - 'testEx', - [ - 'D', - 'W', - ], - ]; - const sqlProcessedResult = processPreparedSQLStatement(requestedRows, values, 10); - const expectedSqlResult = "SELECT * FROM `messages` WHERE `timestamp`>='1563794601.351' AND `timestamp`" + - "<='1563794661.354' AND `hostname` = 'test' AND NOT(`hostname` = 'testEx' AND `hostname` IS NOT" + - " NULL) AND `severity` IN ('D','W') ORDER BY `TIMESTAMP` LIMIT 10"; - assert.strictEqual(sqlProcessedResult, expectedSqlResult); - }); - it('should successfully return result when filters are provided for querying', async () => { const query = 'SELECT * FROM `messages` WHERE `timestamp`>=? AND `timestamp`<=? AND `hostname` = ? ' + 'AND NOT(`hostname` = ? AND `hostname` IS NOT NULL) AND `severity` IN (?) ORDER BY `TIMESTAMP` LIMIT 10'; From dff17a8b2a1fa75e958431e61343d4e3fa279d7c Mon Sep 17 00:00:00 2001 From: Jasper Houweling Date: Tue, 26 Nov 2024 19:39:45 +0100 Subject: [PATCH 8/8] Fixed test placement --- .../services/mocha-preparedStatementParser.js | 41 ------------------- .../lib/services/mocha-query-service.test.js | 15 +++++++ 2 files changed, 15 insertions(+), 41 deletions(-) diff --git a/InfoLogger/test/lib/services/mocha-preparedStatementParser.js b/InfoLogger/test/lib/services/mocha-preparedStatementParser.js index 6326c670d..e5029e8b7 100644 --- a/InfoLogger/test/lib/services/mocha-preparedStatementParser.js +++ b/InfoLogger/test/lib/services/mocha-preparedStatementParser.js @@ -13,35 +13,9 @@ */ const assert = require('assert'); -const sinon = require('sinon'); -const config = require('../../../config-default.js'); -const { QueryService } = require('../../../lib/services/QueryService.js'); const { processPreparedSQLStatement } = require('../../../lib/utils/preparedStatementParser.js'); describe('preparedStatementParser() - test suite', () => { - const realFilters = { - timestamp: { - since: -5, - until: -1, - $since: '2019-07-22T11:23:21.351Z', - $until: '2019-07-22T11:24:21.354Z', - }, - hostname: { - match: 'test', - exclude: 'testEx', - $match: 'test', - $exclude: 'testEx', - }, - severity: { - in: 'D I', - $in: ['D', 'W'], - }, - level: { - max: null, // 0, 1, 6, 11, 21 - $max: null, // 0, 1, 6, 11, 21 - }, - }; - it('should be able to fill in a prepared statement', async () => { const requestedRows = 'SELECT * FROM `messages` WHERE `timestamp`>=? AND `timestamp`<=? AND `hostname` = ? ' + 'AND NOT(`hostname` = ? AND `hostname` IS NOT NULL) AND `severity` IN (?) ORDER BY `TIMESTAMP` LIMIT 10'; @@ -61,19 +35,4 @@ describe('preparedStatementParser() - test suite', () => { " NULL) AND `severity` IN ('D','W') ORDER BY `TIMESTAMP` LIMIT 10"; assert.strictEqual(sqlProcessedResult, expectedSqlResult); }); - - it('should log every executed sql query as debug', async () => { - const sqlDataSource = new QueryService(config.mysql); - sqlDataSource._logger = { - debugMessage: sinon.stub(), - }; - sqlDataSource._pool = { - query: sinon.stub().resolves([{ hostname: 'test', severity: 'W' }]), - }; - await sqlDataSource.queryFromFilters(realFilters, { limit: 10 }); - const completeSqlQuery = "SELECT * FROM `messages` WHERE `timestamp`>='1563794601.351' AND" + - " `timestamp`<='1563794661.354' AND `hostname` = 'test' AND NOT(`hostname` = 'testEx' AND" + - " `hostname` IS NOT NULL) AND `severity` IN ('D','W') ORDER BY `TIMESTAMP` LIMIT 10;"; - assert.strictEqual(sqlDataSource._logger.debugMessage.calledWith(`SQL to execute: ${completeSqlQuery}`), true); - }); }); diff --git a/InfoLogger/test/lib/services/mocha-query-service.test.js b/InfoLogger/test/lib/services/mocha-query-service.test.js index 592be59c5..b901cff9e 100644 --- a/InfoLogger/test/lib/services/mocha-query-service.test.js +++ b/InfoLogger/test/lib/services/mocha-query-service.test.js @@ -230,6 +230,21 @@ describe('\'QueryService\' test suite', () => { }; assert.deepStrictEqual(result, expectedResult); }); + + it('should log every executed sql query as debug', async () => { + const sqlDataSource = new QueryService(config.mysql); + sqlDataSource._logger = { + debugMessage: sinon.stub(), + }; + sqlDataSource._pool = { + query: sinon.stub().resolves([{ hostname: 'test', severity: 'W' }]), + }; + await sqlDataSource.queryFromFilters(realFilters, { limit: 10 }); + const completeSqlQuery = "SELECT * FROM `messages` WHERE `timestamp`>='1563794601.351' AND" + + " `timestamp`<='1563794661.354' AND `hostname` = 'test' AND NOT(`hostname` = 'testEx' AND" + + " `hostname` IS NOT NULL) AND `severity` IN ('D','W') ORDER BY `TIMESTAMP` LIMIT 10;"; + assert.strictEqual(sqlDataSource._logger.debugMessage.calledWith(`SQL to execute: ${completeSqlQuery}`), true); + }); }); describe('queryGroupCountLogsBySeverity() - test suite', () => {