Reputation: 157
In my current project with lots of dependencies I need a way to disable console access for specific libraries so that those files can't use any of the console functionality.
I could of course disable console functionality by simply finding and replacing it in the library bundle, but as this project has a lot of dependencies that would make updating libraries a huge hassle.
I'm aware that I can disable console functionality by overwriting it with an empty function block:
console.log = function(){};
But that disables the console functionality for the entire project. So im looking for an implementation, or a line of code with which I can disable console functionality for a specific file or code block.
Upvotes: 11
Views: 1406
Reputation: 4116
console.log
// Preserve the old console.log
const log = console.log;
// Used a dictionary because it's faster than lists for lookups
const whiteListedFunctions = {"hello": true};
// Whitelisting "middleware". We used the function's name "funcName"
// as a criteria, but it's adaptable
const isWhitelisted = callerData => callerData.funcName in whiteListedFunctions;
// Replacing the default "console.log"
console.log = arg => {
const stack = new Error().stack.split("at")[2].trim().split(' ');
const fileParts = stack[1].substr(1, stack[1].length - 2).split(':');
const callerData = {
funcName: stack[0],
file: fileParts.slice(0, fileParts.length - 2).join(':'),
lineColNumber: fileParts.slice(fileParts.length - 2).join(':')
};
if (isWhitelisted(callerData)) { // Filtering happens here
log(arg);
}
};
// Define the calling functions
function hello() { console.log("hello"); }
function world() { console.log("world"); }
hello(); // => Prints hello
world(); // => Doesn't print anything
console.log
or maybe the file name, or even the line and column numbers.console.log
by overriding with your new logger. This logger will take as an argument the message to log (maybe multiple arguments?). In this function you also need to find the data relating to the caller function (which wanted to call console.log
).This part is a little "hacky" (but it got the job done in this case). We basically create an Error
and check its stack
attribute like this new Error().stack
. Which will give us this trace
Error at console.log.arg [as log] (https://stacksnippets.net/js:25:7) at hello (https://stacksnippets.net/js:41:11) at https://stacksnippets.net/js:48:1
After processing (split, map, etc...) the trace we get the caller function data. For example here we have
This bit was inspired by VLAZ's answer in How to disable console.log messages based on criteria from specific javascript source (method, file) or message contents, so make sure to check it out. Really good and thorough post.
To make sense of the trace we can do new Error().stack.split("at")[INDEX].trim().split(' ')
where INDEX
is the position of the function call you want to target in the stack trace. So if you want to get a different "level" that the one used in this example, try changing INDEX
Upvotes: 2
Reputation: 18493
Yes, you can disable console logs from files based on their path! Here's a solution:
// in ./loud-lib.js module.exports = { logsSomething: () => console.log('hello from loud-lib') }
// in ./silent-lib.js module.exports = { logsSomething: () => console.log('hello from silent-lib') }
// in ./index.js const loud = require('./loud-lib'); const silent = require('./silent-lib'); // save console.log const log = console.log; // redefinition of console.log console.log = (...params) => { // define regexp for path of libraries that log too much const loudLibs = [/loud-lib/]; // check if the paths logged in the stacktract match with at least one regexp const tooLoud = !!loudLibs.find(reg => reg.test(new Error().stack)); // log only if the log is coming from a library that doesn't logs too much if (!tooLoud) log(...params); }; loud.logsSomething(); silent.logsSomething();
$ node ./index.js hello from silent-lib
This is based on the fact that new Error()
produces a stack trace that identifies from which file is the error coming from (recursively).
Based on this observation, you can define an array of regular expression that match the name of libraries you don't want to hear logs from. You can get really specific and creative with the re-definition of console.log
, but I kept it simple.
However, be aware of this (especially when using Webpack): if you bundle all your JS assets into one single bundle.js
, the stacktrace will always point to bundle.js
, thus logging everything. You'll have to go further from my code, for example by using stack-source-map, but I don't have sufficient details on your project to deliver a solution. I hope the ideas above are sufficient for you.
Upvotes: 0
Reputation: 953
Just redefine the console to log over a condition, your condition of course will be a check over which library is accessing the function:
// Your condition, could be anything
let condition = true;
/* Redefine the console object changing only the log function with your new version and keeping all the other functionalities intact
*/
let console = (old => ({
...old,
log: text => { if (condition) old.log(text) }
}))(window.console)
// Redefine the old console
window.console = console;
console.log('hello!')
Hope it helped :)
Upvotes: -1