禁用特定Javascript文件的控制台访问

时间:2019-02-08 14:00:27

标签: javascript

在当前有很多依赖项的项目中,我需要一种对特定库禁用控制台访问的方法,以使这些文件不能使用任何控制台功能。

我当然可以通过简单地在库捆绑中找到并替换控制台功能来禁用控制台功能,但是由于该项目具有很多依赖关系,因此更新库变得非常麻烦。

我知道我可以通过使用空功能块覆盖控制台功能来禁用控制台功能:

console.log = function(){};

但是,这将禁用整个项目的控制台功能。因此,我正在寻找一种实现方式,或者寻找一行代码来禁用特定文件或代码块的控制台功能。

3 个答案:

答案 0 :(得分:2)

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的函数的名称,或者可能包含文件名,甚至可能包含行号和列号 >。
  • 之后,您创建列入白名单的“中间件” 。这将使用调用者函数数据并确定它是否可以记录内容。这将基于先前定义的白名单完成。您可以在此“中间件”中选择首选条件。
  • 然后,您实际上是通过覆盖新记录器来替换console.log。该记录器将要记录的消息作为参数(也许有多个参数?)。在此功能中,您还需要找到与呼叫者功能(想要调用console.log)有关的数据。
  • 一旦有了呼叫者数据,就可以使用白名单中间件来确定它是否可以记录内容

获取有关调用方功能的信息

这部分有点“棘手”(但是在这种情况下,它完成了工作)。我们基本上会创建一个 Error 并检查其stack属性,例如new Error().stack。这将给我们这种痕迹

  

错误       在console.log.arg [作为日志](https://stacksnippets.net/js:25:7)       打招呼(https://stacksnippets.net/js:41:11)       在https://stacksnippets.net/js:48:1

在处理(分割,映射等)跟踪之后,我们获得了调用者函数数据。例如,这里有

  • 调用者函数的名称: hello
  • 文件名: https://stacksnippets.net/js
  • 行和列号: 41:11 (注意缩小符)

此位是受VLAZ'sHow to disable console.log messages based on criteria from specific javascript source (method, file) or message contents答案的启发,因此请务必将其签出。真的很好,内容很详尽。

注意

要了解跟踪,我们可以执行new Error().stack.split("at")[INDEX].trim().split(' '),其中INDEX是要在堆栈跟踪中定位的函数调用的位置。因此,如果您要获得与本示例中使用的不同的“级别” ,请尝试更改INDEX

答案 1 :(得分:0)

只需重新定义控制台以登录条件,您的条件当然就是检查哪个库正在访问该功能:

// 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!')

希望对您有所帮助:)

答案 2 :(得分:0)

是的,您可以根据文件的路径禁用控制台日志!这是一个解决方案:

// 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

这是基于以下事实:new Error()会生成堆栈跟踪,该堆栈跟踪可识别(递归地)错误来自哪个文件。

基于此观察,您可以定义一个正则表达式数组,该数组与您不希望听到其日志的库的名称匹配。通过重新定义console.log,您可以变得非常具体和富有创意,但是我保持了简单。

但是,请注意这一点(尤其是在使用Webpack时):如果将所有JS资产捆绑到一个bundle.js中,则堆栈跟踪将始终指向bundle.js ,从而记录所有内容。您必须走出我的代码的距离,例如使用stack-source-map,但是我在您的项目上没有足够的细节来提供解决方案。我希望以上想法对您足够。