Refactor gdjs.Logger to allow disabling specific log groups in the console (#3204)

* This reduces the logs during GDJS tests, as this was cluttering the
terminal.

Only show in developer changelog
This commit is contained in:
Florian Rival
2021-10-27 11:39:36 +01:00
committed by GitHub
parent 852ad1d92b
commit a3fdeec6a7
9 changed files with 164 additions and 69 deletions

View File

@@ -24,7 +24,7 @@ namespace gdjs {
type: 'info' | 'warning' | 'error',
group: string
) {
gdjs.log(group, message, type, false);
gdjs.Logger.getLoggerOutput().log(group, message, type, false);
};
/**

View File

@@ -1,5 +1,5 @@
namespace gdjs {
const logger = new gdjs.Logger('Firebase');
const logger = new gdjs.Logger('Firebase (setup)');
export namespace evtTools {
/**
* Firebase Event Tools

View File

@@ -1,23 +1,58 @@
namespace gdjs {
const _console = {
/**
* A LoggerOutput specifies a single method to be called to display
* or register a log.
*/
export interface LoggerOutput {
log(
group: string,
message: string,
type: 'info' | 'warning' | 'error',
internal?: boolean
): void;
}
const supportedConsoleFunctions = {
info: console.log,
warning: console.warn,
error: console.error,
};
/**
* Internal method for logging messages to the JS console or the Debugger if available.
* Should be used in engine code or extensions, console.log is fine for JS events.
* The default logging output: uses the JavaScript console.
*/
export let log = (
group: string,
message: string,
type: 'info' | 'warning' | 'error' = 'info',
internal = true
): void => {
const logger = _console[type] || _console.info;
logger(`[${group}] ${message}`);
};
class ConsoleLoggerOutput implements LoggerOutput {
private readonly discardedConsoleGroups = new Set<string>();
discardGroup(groupName: string) {
this.discardedConsoleGroups.add(groupName);
}
enableGroup(groupName: string) {
this.discardedConsoleGroups.delete(groupName);
}
log(
group: string,
message: string,
type: 'info' | 'warning' | 'error' = 'info',
internal = true
): void {
if (this.discardedConsoleGroups.has(group)) return;
const logger =
supportedConsoleFunctions[type] || supportedConsoleFunctions.info;
logger(`[${group}] ${message}`);
}
}
const consoleLoggerOutput = new ConsoleLoggerOutput();
/**
* The current output method - can be changed at runtime.
* By default, output to the JavaScript console.
*/
let loggerOutput: LoggerOutput = consoleLoggerOutput;
function objectsToString(objects: any[]): string {
return objects.reduce(
@@ -27,28 +62,56 @@ namespace gdjs {
}
/**
* A Console API like class for logging using GDevelop's logger.
* A Console API like class for logging in a GDevelop game.
*/
export class Logger {
private readonly group: string;
/**
* Create a new logger with the given group name.
* You can then use log, info, warn and error on this object.
*/
constructor(group: string) {
this.group = group;
}
log(...messages: any[]): void {
this.info(...messages);
loggerOutput.log(this.group, objectsToString(messages), 'info');
}
info(...messages: any[]): void {
log(this.group, objectsToString(messages), 'info');
loggerOutput.log(this.group, objectsToString(messages), 'info');
}
warn(...messages: any[]): void {
log(this.group, objectsToString(messages), 'warning');
loggerOutput.log(this.group, objectsToString(messages), 'warning');
}
error(...messages: any[]): void {
log(this.group, objectsToString(messages), 'error');
loggerOutput.log(this.group, objectsToString(messages), 'error');
}
/**
* Give access to the console output used by default by the logger.
* This can be useful to restore the default log method if you overrode it
* or to disable some logging in the console.
*/
static getDefaultConsoleLoggerOutput() {
return consoleLoggerOutput;
}
/**
* Return the current logger output (common to all gdjs.Logger instances).
*/
static getLoggerOutput(): LoggerOutput {
return loggerOutput;
}
/**
* Change the logger output (common to all gdjs.Logger instances).
*/
static setLoggerOutput(newLoggerOutput: LoggerOutput) {
loggerOutput = newLoggerOutput;
}
}
}

View File

@@ -4,7 +4,8 @@
* This project is released under the MIT License.
*/
namespace gdjs {
const logger = new gdjs.Logger('Scene manager');
const logger = new gdjs.Logger('RuntimeScene');
const setupWarningLogger = new gdjs.Logger('RuntimeScene (setup warnings)');
/**
* A scene being played, containing instances of objects rendered on screen.
@@ -437,7 +438,7 @@ namespace gdjs {
if (module && module.func) {
this._eventsFunction = module.func;
} else {
logger.warn(
setupWarningLogger.warn(
'No function found for running logic of scene ' + this._name
);
this._eventsFunction = function () {};

View File

@@ -168,62 +168,70 @@ namespace gdjs {
}
};
((log, info, debug, warn, error, gdjsLog) => {
// Hook the console logging functions to log to the Debugger as well
console.log = (...messages) => {
log(...messages);
this._consoleLogHook('info', ...messages);
};
const redirectJsLog = (
type: 'info' | 'warning' | 'error',
...messages
) => {
this.log(
'JavaScript',
messages.reduce(
(accumulator, value) => accumulator + value.toString(),
''
),
type,
false
);
};
console.debug = (...messages) => {
debug(...messages);
this._consoleLogHook('info', ...messages);
};
const originalConsole = {
log: console.log,
info: console.info,
debug: console.debug,
warn: console.warn,
error: console.error,
};
console.info = (...messages) => {
info(...messages);
this._consoleLogHook('info', ...messages);
};
// Hook the console logging functions to log to the Debugger as well
console.log = (...messages) => {
originalConsole.log(...messages);
redirectJsLog('info', ...messages);
};
console.warn = (...messages) => {
warn(...messages);
this._consoleLogHook('warning', ...messages);
};
console.debug = (...messages) => {
originalConsole.debug(...messages);
redirectJsLog('info', ...messages);
};
console.error = (...messages) => {
error(...messages);
this._consoleLogHook('error', ...messages);
};
console.info = (...messages) => {
originalConsole.info(...messages);
redirectJsLog('info', ...messages);
};
gdjs.log = (
console.warn = (...messages) => {
originalConsole.warn(...messages);
redirectJsLog('warning', ...messages);
};
console.error = (...messages) => {
originalConsole.error(...messages);
redirectJsLog('error', ...messages);
};
// Overwrite the default GDJS log outputs so that they
// both go to the console (or wherever they were configured to go)
// and sent to the remote debugger.
const existingLoggerOutput = gdjs.Logger.getLoggerOutput();
gdjs.Logger.setLoggerOutput({
log(
group: string,
message: string,
type: 'info' | 'warning' | 'error' = 'info',
internal = true
) => {
gdjsLog(group, message, type);
) {
existingLoggerOutput.log(group, message, type, internal);
this.log(group, message, type, internal);
};
})(
console.log,
console.info,
console.debug,
console.warn,
console.error,
gdjs.log
);
}
_consoleLogHook(type: 'info' | 'warning' | 'error', ...messages) {
this.log(
'JavaScript',
messages.reduce(
(accumulator, value) => accumulator + value.toString(),
''
),
type,
false
);
},
});
}
log(

View File

@@ -10,6 +10,13 @@ module.exports = function (config) {
config.set({
frameworks: ['mocha'],
browserNoActivityTimeout: 400000,
browsers: ['ChromeHeadless', 'EdgeHeadless', 'Chrome', 'Edge', 'Firefox'],
plugins: [
require('karma-chrome-launcher'),
require('@chiragrupani/karma-chromium-edge-launcher'),
require('karma-firefox-launcher'),
require('karma-mocha'),
],
client: {
mocha: {
reporter: 'html',
@@ -83,7 +90,8 @@ module.exports = function (config) {
// Test extensions:
'./tests/Extensions/**.js',
//All tests files:
// Other test initialization files:
'./tests-utils/init.js',
'./tests-utils/init.pixiruntimegamewithassets.js',
// Assets

View File

@@ -4,6 +4,12 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@chiragrupani/karma-chromium-edge-launcher": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@chiragrupani/karma-chromium-edge-launcher/-/karma-chromium-edge-launcher-2.1.1.tgz",
"integrity": "sha512-QK6M+1CYMbndWRaEAOpMW9kwF+JKcqyaEY2lqe8Nnm1hyOzSZaxTqXnLTZpk7RqQHhWCOduSU/XDvceWs4H74g==",
"dev": true
},
"accepts": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz",

View File

@@ -10,7 +10,9 @@
"test-benchmark": "karma start --browsers ChromeHeadless --single-run --enableBenchmarks",
"test-benchmark:watch": "karma start --browsers ChromeHeadless --enableBenchmarks",
"test:firefox": "karma start --browsers Firefox --single-run",
"test:firefox:watch": "karma start --browsers Firefox"
"test:firefox:watch": "karma start --browsers Firefox",
"test:edge": "karma start --browsers EdgeHeadless --single-run",
"test:edge:watch": "karma start --browsers EdgeHeadless"
},
"keywords": [
"HTML5",
@@ -28,6 +30,7 @@
"devDependencies": {
"karma": "^1.7.1",
"karma-chrome-launcher": "^2.2.0",
"@chiragrupani/karma-chromium-edge-launcher": "2.1.1",
"karma-firefox-launcher": "^1.1.0",
"karma-mocha": "^1.3.0"
}

View File

@@ -0,0 +1,6 @@
// @ts-check
// This file is called before all tests (but after GDJS is loaded).
// Disable a few logs that are too verbose:
gdjs.Logger.getDefaultConsoleLoggerOutput().discardGroup('Firebase (setup)');
gdjs.Logger.getDefaultConsoleLoggerOutput().discardGroup('RuntimeScene (setup warnings)');