From cc21b68493fd2323b85bc54c34c65e9cee0236fa Mon Sep 17 00:00:00 2001 From: NarrowsProjects Date: Mon, 1 Jun 2026 10:02:56 +0200 Subject: [PATCH 1/4] feat: create FilterLogger class --- lib/server/Loggers/FilterLogger.js | 53 ++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 lib/server/Loggers/FilterLogger.js diff --git a/lib/server/Loggers/FilterLogger.js b/lib/server/Loggers/FilterLogger.js new file mode 100644 index 0000000000..2a94e06035 --- /dev/null +++ b/lib/server/Loggers/FilterLogger.js @@ -0,0 +1,53 @@ +/** + * @license + * Copyright CERN and copyright holders of ALICE O2. This software is + * distributed under the terms of the GNU General Public License v3 (GPL + * Version 3), copied verbatim in the file "COPYING". + * + * See http://alice-o2.web.cern.ch/license for full licensing information. + * + * 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, LogLevel } = require('@aliceo2/web-ui'); + +/** + * Logger dedicated to filter-related endpoint access events. + */ +class FilterLogger { + /** + * Creates an instance of FilterLogger. + */ + constructor() { + LogManager.configure({ infologger: true }); + this._logger = LogManager.getLogger('FILTERING'); + this._logLevel = LogLevel.OPERATIONS; + } + + /** + * Logs an informational message about endpoint access and applied filters. + * + * @param {object} request the request received at any given endpoint. + * @param {string} endpoint the endpoint that was accessed. + * @param {string|number} id identifier of the user accessing the endpoint. + * @param {Object} [filters={}] filters applied to the request. + * @returns {void} + */ + infoMessage({ path, session: { id }, query = {} }) { + const filters = query.filters ?? {}; + + let message = `Endpoint ${path} was accessed by user ${id} `; + + if (!Object.keys(filters).length) { + message += 'without filters'; + } else { + message += 'with the following filters:\n'; + message += JSON.stringify(filters); + } + + this._logger.infoMessage(message, { level: this._logLevel }); + } +} + +module.exports = new FilterLogger(); From 7260c0f63bea83853308501aeec8b2bd2f155e36 Mon Sep 17 00:00:00 2001 From: NarrowsProjects Date: Mon, 1 Jun 2026 10:04:40 +0200 Subject: [PATCH 2/4] feat: create infoLoggerListener --- .../InfoLoggerListener.middleware.js | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 lib/server/middleware/InfoLoggerListener.middleware.js diff --git a/lib/server/middleware/InfoLoggerListener.middleware.js b/lib/server/middleware/InfoLoggerListener.middleware.js new file mode 100644 index 0000000000..858b8a805d --- /dev/null +++ b/lib/server/middleware/InfoLoggerListener.middleware.js @@ -0,0 +1,23 @@ +/** + * @license + * Copyright CERN and copyright holders of ALICE O2. This software is + * distributed under the terms of the GNU General Public License v3 (GPL + * Version 3), copied verbatim in the file "COPYING". + * + * See http://alice-o2.web.cern.ch/license for full licensing information. + * + * 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. + */ + +/** + * Logger based middleware generator + * + * @param {Class} logger class that exposes an infoMessage function that recceives the request and then sends specific data to InfoLogger + * @return {(function(*, *, *): void)} the infoLoggerListener middleware + */ +exports.infoLoggerListenerMiddleware = (logger) => (request, _response, next) => { + logger.infoMessage(request); + next(); +}; From 6ed0a4595f2300512825782d49a28e1fe34d3e89 Mon Sep 17 00:00:00 2001 From: NarrowsProjects Date: Mon, 1 Jun 2026 10:18:08 +0200 Subject: [PATCH 3/4] feat: add InfoLogger middleware overview page endpoints --- lib/server/routers/dataPasses.router.js | 4 +++- lib/server/routers/environments.router.js | 4 +++- lib/server/routers/lhcFills.router.js | 4 +++- lib/server/routers/lhcPeriodsStatistics.router.js | 4 +++- lib/server/routers/logs.router.js | 4 +++- lib/server/routers/qcFlag.router.js | 4 +++- lib/server/routers/runs.router.js | 4 +++- lib/server/routers/simulationPasses.router.js | 4 +++- 8 files changed, 24 insertions(+), 8 deletions(-) diff --git a/lib/server/routers/dataPasses.router.js b/lib/server/routers/dataPasses.router.js index 34f97d2547..89e0e7cd58 100644 --- a/lib/server/routers/dataPasses.router.js +++ b/lib/server/routers/dataPasses.router.js @@ -14,11 +14,13 @@ const { DataPassesController } = require('../controllers/dataPasses.controller.js'); const { rbacMiddleware } = require('../middleware/rbac.middleware.js'); const { BkpRoles } = require('../../domain/enums/BkpRoles.js'); +const FilterLogger = require('../Loggers/FilterLogger.js'); +const { infoLoggerListenerMiddleware } = require('../middleware/InfoLoggerListener.middleware.js'); exports.dataPassesRouter = { path: '/dataPasses', method: 'get', - controller: DataPassesController.listDataPassesHandler, + controller: [infoLoggerListenerMiddleware(FilterLogger), DataPassesController.listDataPassesHandler], children: [ { diff --git a/lib/server/routers/environments.router.js b/lib/server/routers/environments.router.js index 56d4066e73..1c0769bc68 100644 --- a/lib/server/routers/environments.router.js +++ b/lib/server/routers/environments.router.js @@ -12,11 +12,13 @@ */ const { EnvironmentsController } = require('../controllers'); +const FilterLogger = require('../Loggers/FilterLogger'); +const { infoLoggerListenerMiddleware } = require('../middleware/InfoLoggerListener.middleware'); module.exports = { method: 'get', path: '/environments', - controller: EnvironmentsController.getAllEnvironments, + controller: [infoLoggerListenerMiddleware(FilterLogger), EnvironmentsController.getAllEnvironments], children: [ { method: 'post', diff --git a/lib/server/routers/lhcFills.router.js b/lib/server/routers/lhcFills.router.js index 2b33cedb8c..73bc50433e 100644 --- a/lib/server/routers/lhcFills.router.js +++ b/lib/server/routers/lhcFills.router.js @@ -12,13 +12,15 @@ */ const { LhcFillsController } = require('../controllers'); +const FilterLogger = require('../Loggers/FilterLogger'); +const { infoLoggerListenerMiddleware } = require('../middleware/InfoLoggerListener.middleware'); module.exports = { path: '/lhcFills', children: [ { method: 'get', - controller: LhcFillsController.listLhcFills, + controller: [infoLoggerListenerMiddleware(FilterLogger), LhcFillsController.listLhcFills], }, { method: 'post', diff --git a/lib/server/routers/lhcPeriodsStatistics.router.js b/lib/server/routers/lhcPeriodsStatistics.router.js index 073288903c..feb0f4b058 100644 --- a/lib/server/routers/lhcPeriodsStatistics.router.js +++ b/lib/server/routers/lhcPeriodsStatistics.router.js @@ -12,13 +12,15 @@ */ const { LhcPeriodStatisticsController } = require('../controllers/lhcPeriodStatistics.controller.js'); +const FilterLogger = require('../Loggers/FilterLogger.js'); +const { infoLoggerListenerMiddleware } = require('../middleware/InfoLoggerListener.middleware.js'); exports.lhcPeriodsRouter = { path: '/lhcPeriodsStatistics', children: [ { method: 'get', - controller: LhcPeriodStatisticsController.listLhcPeriodStatisticsHandler, + controller: [infoLoggerListenerMiddleware(FilterLogger), LhcPeriodStatisticsController.listLhcPeriodStatisticsHandler], }, { method: 'get', diff --git a/lib/server/routers/logs.router.js b/lib/server/routers/logs.router.js index d4381dc170..9c115f855e 100644 --- a/lib/server/routers/logs.router.js +++ b/lib/server/routers/logs.router.js @@ -12,12 +12,14 @@ */ const { LogsController } = require('../controllers'); +const FilterLogger = require('../Loggers/FilterLogger'); const { multerMiddleware: { attachmentMiddleware } } = require('../middleware'); +const { infoLoggerListenerMiddleware } = require('../middleware/InfoLoggerListener.middleware'); module.exports = { method: 'get', path: '/logs', - controller: LogsController.listLogs, + controller: [infoLoggerListenerMiddleware(FilterLogger), LogsController.listLogs], children: [ { method: 'get', diff --git a/lib/server/routers/qcFlag.router.js b/lib/server/routers/qcFlag.router.js index 569a6802ec..f97a565c86 100644 --- a/lib/server/routers/qcFlag.router.js +++ b/lib/server/routers/qcFlag.router.js @@ -13,6 +13,8 @@ const { BkpRoles } = require('../../domain/enums/BkpRoles.js'); const { QcFlagController } = require('../controllers/qcFlag.controller.js'); +const FilterLogger = require('../Loggers/FilterLogger.js'); +const { infoLoggerListenerMiddleware } = require('../middleware/InfoLoggerListener.middleware.js'); const { rbacMiddleware } = require('../middleware/rbac.middleware.js'); exports.qcFlagsRouter = { @@ -21,7 +23,7 @@ exports.qcFlagsRouter = { { path: 'gaq', method: 'get', - controller: QcFlagController.getGaqQcFlagsHandler, + controller: [infoLoggerListenerMiddleware(FilterLogger), QcFlagController.getGaqQcFlagsHandler], }, { path: 'summary', diff --git a/lib/server/routers/runs.router.js b/lib/server/routers/runs.router.js index cfff057864..59d453d9bc 100644 --- a/lib/server/routers/runs.router.js +++ b/lib/server/routers/runs.router.js @@ -12,6 +12,8 @@ */ const { RunsController } = require('../controllers'); +const FilterLogger = require('../Loggers/FilterLogger'); +const { infoLoggerListenerMiddleware } = require('../middleware/InfoLoggerListener.middleware'); module.exports = { children: [ @@ -30,7 +32,7 @@ module.exports = { }, { method: 'get', - controller: RunsController.listRuns, + controller: [infoLoggerListenerMiddleware(FilterLogger), RunsController.listRuns], }, { method: 'get', diff --git a/lib/server/routers/simulationPasses.router.js b/lib/server/routers/simulationPasses.router.js index 057a914fbc..ccd7ba18c1 100644 --- a/lib/server/routers/simulationPasses.router.js +++ b/lib/server/routers/simulationPasses.router.js @@ -12,6 +12,8 @@ */ const { SimulationPassesController } = require('../controllers/simulationPasses.controller.js'); +const FilterLogger = require('../Loggers/FilterLogger.js'); +const { infoLoggerListenerMiddleware } = require('../middleware/InfoLoggerListener.middleware.js'); exports.simulationPassesRouter = { path: '/simulationPasses', @@ -23,7 +25,7 @@ exports.simulationPassesRouter = { }, { method: 'get', - controller: SimulationPassesController.listSimulationPassesHandler, + controller: [infoLoggerListenerMiddleware(FilterLogger), SimulationPassesController.listSimulationPassesHandler], }, ], }; From 2a2686cb9e34cefc039e6de1c376e6f44331d351 Mon Sep 17 00:00:00 2001 From: NarrowsProjects Date: Mon, 1 Jun 2026 10:33:26 +0200 Subject: [PATCH 4/4] feat: configrue winston wrapper to exclude logs when in a testing environment --- lib/server/Loggers/FilterLogger.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/server/Loggers/FilterLogger.js b/lib/server/Loggers/FilterLogger.js index 2a94e06035..53d9a7ab1f 100644 --- a/lib/server/Loggers/FilterLogger.js +++ b/lib/server/Loggers/FilterLogger.js @@ -19,10 +19,11 @@ class FilterLogger { /** * Creates an instance of FilterLogger. */ - constructor() { + constructor(silent = process.env.NODE_ENV === 'test') { LogManager.configure({ infologger: true }); this._logger = LogManager.getLogger('FILTERING'); this._logLevel = LogLevel.OPERATIONS; + this._silent = silent; } /** @@ -35,6 +36,10 @@ class FilterLogger { * @returns {void} */ infoMessage({ path, session: { id }, query = {} }) { + if (this._silent) { + return; + } + const filters = query.filters ?? {}; let message = `Endpoint ${path} was accessed by user ${id} `;