From 98db319eff300099b8667f778b6b8661c65287ce Mon Sep 17 00:00:00 2001 From: Merlin Beutlberger Date: Fri, 6 Dec 2024 10:06:51 +0100 Subject: [PATCH] [FEATURE] Console: Add module filtering Allow filtering of log messages by module names using environment variable UI5_LOG_MODULES. Inspired by the 'debug' npm package. Examples: UI5_LOG_MODULES=specifications:*,graph:Module,Build ui5 build UI5_LOG_MODULES=graph:*,-graph:providers:* ui5 serve --verbose --- lib/loggers/ProjectBuild.js | 18 ++++++++ lib/writers/Console.js | 86 ++++++++++++++++++++++++++++++++++++- 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/lib/loggers/ProjectBuild.js b/lib/loggers/ProjectBuild.js index 83f39497..61c81115 100644 --- a/lib/loggers/ProjectBuild.js +++ b/lib/loggers/ProjectBuild.js @@ -83,6 +83,24 @@ class ProjectBuild extends Logger { this._log(level, `${this.#projectName}: Finished task ${taskName}`); } } + + skipTask(taskName) { + if (!this.#tasksToRun || !this.#tasksToRun.includes(taskName)) { + throw new Error(`loggers/ProjectBuild#skipTask: Unknown task ${taskName}`); + } + const level = "info"; + const hasListeners = this._emit(ProjectBuild.PROJECT_BUILD_STATUS_EVENT_NAME, { + level, + projectName: this.#projectName, + projectType: this.#projectType, + taskName, + status: "task-skip", + }); + + if (!hasListeners) { + this._log(level, `${this.#projectName}: Skipping task ${taskName}`); + } + } } export default ProjectBuild; diff --git a/lib/writers/Console.js b/lib/writers/Console.js index ff233098..b93c6472 100644 --- a/lib/writers/Console.js +++ b/lib/writers/Console.js @@ -21,6 +21,7 @@ class Console { #progressBarContainer; #progressBar; #progressProjectWeight; + #moduleFilter; constructor() { this._handleLogEvent = this.#handleLogEvent.bind(this); @@ -29,6 +30,66 @@ class Console { this._handleBuildMetadataEvent = this.#handleBuildMetadataEvent.bind(this); this._handleProjectBuildMetadataEvent = this.#handleProjectBuildMetadataEvent.bind(this); this._handleStop = this.disable.bind(this); + this.#initFiters(); + } + + #initFiters() { + const modulesPatterns = process.env.UI5_LOG_MODULES; + if (!modulesPatterns) { + this.#moduleFilter = null; + return; + } + const enabledModules = []; + const enabledNamespaces = []; + const disabledModules = []; + const disabledNamespaces = []; + // Example of modulePattern: "module1,module2:submodule:subsubmodule,module3:*:-module3:submodule" + modulesPatterns.split(",").forEach((modulePattern) => { + const pattern = modulePattern.trim(); + if (pattern.startsWith("-")) { + if (pattern.endsWith(":*")) { + disabledNamespaces.push(pattern.substring(1, pattern.length - 2)); + } else { + disabledModules.push(pattern.substring(1)); + } + } else { + if (pattern.endsWith(":*")) { + enabledNamespaces.push(pattern.substring(0, pattern.length - 2)); + } else { + enabledModules.push(pattern); + } + } + }); + + this.#moduleFilter = { + enabledModules, + enabledNamespaces, + disabledModules, + disabledNamespaces, + }; + } + + #filterModule(moduleName) { + if (!this.#moduleFilter) { + return true; + } + if (this.#moduleFilter.disabledModules.includes(moduleName)) { + return false; + } + if (this.#moduleFilter.enabledModules.includes(moduleName)) { + return true; + } + const moduleParts = moduleName.split(":"); + for (let i = moduleParts.length - 1; i > 0; i--) { + const namespace = moduleParts.slice(0, i).join(":"); + if (this.#moduleFilter.disabledNamespaces.includes(namespace)) { + return false; + } + if (this.#moduleFilter.enabledNamespaces.includes(namespace)) { + return true; + } + } + return false; } /** @@ -137,7 +198,9 @@ class Console { } #handleLogEvent({level, message, moduleName}) { - this.#writeMessage(level, `${chalk.blue(moduleName)} ${message}`); + if (this.#filterModule(moduleName)) { + this.#writeMessage(level, `${chalk.blue(moduleName)} ${message}`); + } } #handleBuildMetadataEvent({projectsToBuild}) { @@ -328,6 +391,27 @@ class Console { taskMetadata.executionEnded = true; message = `${chalk.green(figures.tick)} Finished task ${chalk.bold(taskName)}`; + // Update progress bar (if used) + this._getProgressBar()?.increment(1); + break; + case "task-skip": + if (taskMetadata.executionSkipped) { + throw new Error(`writers/Console: ` + + `Unexpected duplicate task-skip event for project ${projectName}, task ${taskName}`); + } + if (taskMetadata.executionStarted) { + throw new Error(`writers/Console: ` + + `Unexpected task-skip event for project ${projectName}, task ${taskName}. ` + + `Task execution already started`); + } + if (taskMetadata.executionEnded) { + throw new Error(`writers/Console: ` + + `Unexpected task-skip event for project ${projectName}, task ${taskName}. ` + + `Task execution already ended`); + } + taskMetadata.executionEnded = true; + message = `${chalk.green(figures.tick)} Skipping task ${chalk.bold(taskName)}`; + // Update progress bar (if used) this._getProgressBar()?.increment(1); break;