如何根据来自特定javascript源(方法、文件)或消息内容的条件禁用console.log消息

gk7wooem  于 2023-01-07  发布在  Java
关注(0)|答案(6)|浏览(123)

我正在做一个项目,使用了相当多的js库,其中一个是输出到控制台可怕的很多,它是污染的电波如此严重,使它很难调试...
I know how to disable logging通过用这个重写console.log

(function (original) {
    console.enableLogging = function () {
        console.log = original;
    };
    console.disableLogging = function () {
        console.log = function () {};
    };
})(console.log);

但是它是如何根据消息来源的每个源(文件/URL)来执行此操作的?

2ic8powd

2ic8powd1#

序言

开头讨论了一般的工作原理。如果你只关心代码,跳过介绍,滚动到解决方案标题。

简介

问题:

在网络应用程序中有很多控制台噪音。2其中很大一部分噪音来自我们无法访问的第三方代码。3一些对数噪音也可能来自我们的代码。

要求:

通过停止日志来减少噪音。2 * 一些 * 日志仍然应该被保留,并且关于这些日志的决定应该与执行日志的代码分离。3所需的粒度是"每个文件"。4我们应该能够选择哪些文件添加或不添加日志消息。5最后,这将 * 不 * 用于生产代码。
假设:这将在开发人员控制的浏览器中运行。在这种情况下,我不会关注向后兼容性。

前期工作:

可以使用以下命令全局启用/禁用首次记录

(function (original) {
    console.enableLogging = function () {
        console.log = original;
    };
    console.disableLogging = function () {
        console.log = function () {};
    };
})(console.log);

(code张贴在问题中,但也在此供参考)

  • 然而,这不允许任何粒度。
  • 这可以修改为仅在特定模块上工作,但不能对第三方代码进行修改。
  • 一种混合的方法是全局禁用日志记录,但在每个模块中启用它。问题是,我们必须修改 * 每个 * 文件,并且我们将不会得到一些潜在有用的外部消息。

可以使用日志框架,但它可能是一个矫枉过正。虽然,老实说,这是我会去,我认为,但它可能需要一些集成到产品。
因此,我们需要一些重量轻,有一些配置,并不需要漂亮。

提案:

  • Loginator *(标题可能会更改)

让我们从基础开始-我们已经知道我们可以覆盖全局日志函数。我们将接受它并使用它。但首先,让我们认识到console对象支持的不仅仅是.log。可能会使用各种日志函数。所以,让我们禁用所有这些函数。
"沉默"

//shorthand for further code. 
function noop() {}

const savedFunctions = Object.keys(console)
  .reduce((memo, key) => {
    if(typeof console[key] == "function") {
      //keep a copy just in case we need it
      memo[key] = console[key];
      //de-fang any functions 
      console[key] = noop;
    }
    
    return memo;
  }, 
  {});

console.log("Hello?");
console.info("Hello-o-o-o?");
console.warn("Can anybody hear me?");
console.error("I guess there is nobody there...");

savedFunctions.log("MUAHAHAHA!")

这显然可以改进,但它展示了如何停止 * any * 和ll日志记录。实际上,console.error可能应该保留,console.warn也可能有用。但这不是万能的解决方案。
接下来,既然我们可以覆盖控制台功能...为什么不提供我们自己的呢?

    • 自定义日志记录**
const originalLog = console.log;
console.log = function selectiveHearing() {
  if (arguments[0].indexOf("die") !== -1) {
    arguments[0] = "Have a nice day!";
    }
  return originalLog.apply(console, arguments)
}

console.log("Hello.");
console.log("My name is Inigo Montoya.");
console.log("You killed my father.");
console.log("Prepare to die.");

这就是我们推出自己的迷你日志框架所需的所有工具。

    • 如何执行选择性日志记录**

唯一缺少的是确定内容来自哪个文件。我们只需要a stack trace

// The magic
console.log(new Error().stack);

/* SAMPLE:

Error
    at Object.module.exports.request (/home/vagrant/src/kumascript/lib/kumascript/caching.js:366:17)
    at attempt (/home/vagrant/src/kumascript/lib/kumascript/loaders.js:180:24)
    at ks_utils.Class.get (/home/vagrant/src/kumascript/lib/kumascript/loaders.js:194:9)
    at /home/vagrant/src/kumascript/lib/kumascript/macros.js:282:24
    at /home/vagrant/src/kumascript/node_modules/async/lib/async.js:118:13
    at Array.forEach (native)
    at _each (/home/vagrant/src/kumascript/node_modules/async/lib/async.js:39:24)
    at Object.async.each (/home/vagrant/src/kumascript/node_modules/async/lib/async.js:117:9)
    at ks_utils.Class.reloadTemplates (/home/vagrant/src/kumascript/lib/kumascript/macros.js:281:19)
    at ks_utils.Class.process (/home/vagrant/src/kumascript/lib/kumascript/macros.js:217:15)
*/

(此处复制相关位。)
的确,有一些更好的方法,但不是很多。它要么需要一个框架,要么是特定于浏览器的--错误堆栈没有"官方"支持,但它们在Chrome、Edge和Firefox中都能工作。另外,拜托--这只是一行字--我们想要简单,不介意肮脏,所以我很高兴能做出权衡。

溶液

将所有内容放在一起。**警告:**请勿在生产中使用此内容

(function(whitelist = [], functionsToPreserve = ["error"]) {
  function noop() {}

  //ensure we KNOW that there is a log function here, just in case
  const savedFunctions = { log: console.log }
        
  //proceed with nuking the rest of the chattiness away
  Object.keys(console)
    .reduce((memo, key) => {
      if(typeof console[key] == "function" && functionsToPreserve.indexOf(key) != -1 ) {
        memo[key] = console[key];
        console[key] = noop;
      }
    
      return memo;
    }, 
    savedFunctions); //<- it's a const so we can't re-assign it. Besides, we don't need to, if we use it as a seed for reduce()
  
  console.log = function customLog() {
    //index 0 - the error message
    //index 1 - this function
    //index 2 - the calling function, i.e., the actual one that did console.log()
    const callingFile = new Error().stack.split("\n")[2];
    
    if (whitelist.some(entry => callingFile.includes(entry))) {
      savedFunctions.log.apply(console, arguments)
    }
  }

})(["myFile.js"]) //hey, it's SOMEWHAT configurable

或是黑名单

(function(blacklist = [], functionsToPreserve = ["error"]) {
    function noop() {}

    //ensure we KNOW that there is a log function here, just in case
    const savedFunctions = {
        log: console.log
    }

    //proceed with nuking the rest of the chattiness away
    Object.keys(console)
        .reduce((memo, key) => {
                if (typeof console[key] == "function" && functionsToPreserve.indexOf(key) != -1) {
                    memo[key] = console[key];
                    console[key] = noop;
                }

                return memo;
            },
            savedFunctions); //<- it's a const so we can't re-assign it. Besides, we don't need to, if we use it as a seed for reduce()

    console.log = function customLog() {
        //index 0 - the error message
        //index 1 - this function
        //index 2 - the calling function, i.e., the actual one that did console.log()
        const callingFile = new Error().stack.split("\n")[2];

        if (blacklist.some(entry => callingFile.includes(entry))) {
            return;
        } else {
            savedFunctions.log.apply(console, arguments);
        }
    }

})(["myFile.js"])

所以,这是一个定制的日志记录器。当然,它不是完美的,但它可以完成这项工作。而且,嘿,因为白名单有点松散,它可以变成一个优势:

  • 要将共享一个子字符串的一组文件列入白名单,例如,所有myApp可以包括myApp1.jsmyApp2.jsmyApp3.js
  • 虽然如果你想要特定的文件,你可以只传递全名,包括扩展名。我怀疑会有一堆重复的文件名。
  • 最后,堆栈跟踪将包括调用函数的名称,如果有的话,所以你实际上可以传递它,并且它将基于每个函数加入白名单。但是,它依赖于函数有名称,并且函数名称更有可能冲突,所以要小心使用

除此之外,当然还有改进的地方,但这是它的基础。例如,info/warn方法也可以被覆盖。
所以,如果使用的话,应该只在开发版本中使用。有很多方法可以使它不进入生产,所以我不会讨论它们,但这里有一件事我可以提一下:你也可以使用这个 * 任何地方 * 如果你保存它作为一个小书签

javascript:!function(){function c(){}var a=arguments.length<=0||void 0===arguments[0]?[]:arguments[0],b=arguments.length<=1||void 0===arguments[1]?["error"]:arguments[1],d={log:console.log};Object.keys(console).reduce(function(a,d){return"function"==typeof console[d]&&b.indexOf(d)!=-1&&(a[d]=console[d],console[d]=c),a},d),console.log=function(){var c=(new Error).stack.split("\n")[2];a.some(function(a){return c.includes(a)})&&d.log.apply(console,arguments)}}(["myFile.js"]);

这是缩小版(虽然我先通过巴别塔,使用ES5缩小),而且在某种程度上仍然是可配置的,因为你可以改变你可以通过白名单的最后。但除此之外,它的工作原理是一样的,并且与代码库完全分离。它不会在页面加载时运行,但如果需要,您可以将其用作用户脚本(仍然是解耦的)或将其包含在其他JS文件之前 * 仅在dev/debug构建中 *。
这里需要注意的是--这将在Chrome、Edge和Firefox中运行。它们都是最新的浏览器,所以我假设开发者至少会使用其中的一种。这个问题被标记为Chrome,但我决定扩大支持范围。只有Chrome的解决方案 * 可能 * 运行得稍微好一点,但这并不是功能上的大损失。

jm81lzqq

jm81lzqq2#

我和你一样有麻烦。这就是我的方法。
简单用法:

localStorage.debug = [
    'enable/console/log/in/this/file.ts',
    'enable/console/log/in/this/folder/*',
    '-disable/console/log/in/this/file.ts',
    '-disable/console/log/in/this/folder/*',
    
    // enable all
    '*',
].join(',');

好处:它是零运行时。
免责声明:我是这个小工具的作者

kzipqqlq

kzipqqlq3#

它的工作在 chrome :...index.html

<html>
<body>
<script>
    (function(){
        var original = console.log;
        console.log = function(){
            var script = document.currentScript;
            alert(script.src);
            if(script.src === 'file:///C:/Users/degr/Desktop/script.js') {
                original.apply(console, arguments)
            }
        }
    })();
    console.log('this will be hidden');
</script>
<script src="script.js"></script>
</body>
</html>

...script.js

console.log('this will work');

Console.log不是从index.html工作的,而是从script.js工作的。这两个文件都位于我的桌面上。

ykejflvf

ykejflvf4#

我发现最新(2020年7月)的Chrome DevTools控制台中的这些设置很有帮助:
1.开发工具|控制台|(侧栏图标)|用户信息
1.开发工具|控制台|(齿轮图标)|仅选择上下文
1.开发工具|控制台|(齿轮图标)|隐藏网络
我最喜欢(1),我只看到来自“我的”代码的消息。(2)隐藏来自我的iframe的消息。

1szpjjfi

1szpjjfi5#

如果它是修改文件的选项,您可以在文件顶部设置一个标记,用于禁用日志:

var DEBUG = false;
DEBUG && console.log("cyberpunk 2077");

要禁用所有js文件的日志,请将其放在任何js文件的顶部:

var DEBUG = false;
if (!DEBUG) {
   console.log = () => {};
 }
cx6n0qe3

cx6n0qe36#

这不漂亮,但会起作用。
在文件中"bad"库的<script>标记之前放置类似下面的内容:

<script>function GetFile(JSFile) {      
    var MReq = new XMLHttpRequest();        
    MReq.open('GET', JSFile, false);    
    MReq.send();
    eval(MReq.responseText.replace(/console.log\(/g,"(function(){})("));            
}</script>

然后更换标签

<script src="badLib.js">

其中:

GetFile("badLib.js")

仅用于短时间调试。

相关问题