如何根据特定javascript源(方法,文件)或消息内容的条件禁用console.log消息 [英] How to disable console.log messages based on criteria from specific javascript source (method, file) or message contents

查看:100
本文介绍了如何根据特定javascript源(方法,文件)或消息内容的条件禁用console.log消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究使用相当多的js库的项目,其中一个是输出到控制台的很多东西,它污染了无线电波,这使得它很难调试....

I am working on project that uses quite a few js libraries and one of them is outputting awful lot into console, it is polluting the airwaves so bad that it makes it hard to debug....

我知道如何通过覆盖 console.log 完全禁用日志记录

I know how to disable logging completely by overriding console.log with this,

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

如何根据消息来源的源(文件/网址)执行此操作?

推荐答案

序言



开头讨论东西怎么样一般的工作。如果您只关心代码,请跳过简介并滚动到解决方案标题。

Web应用程序中存在大量控制台噪音。大量的噪音来自我们无法访问的第三方代码。一些日志噪音也可能来自我们的代码。

there is a lot of console noise in a web application. A significant amount of that noise is coming from third party code which we do not have access to. Some of the log noise might be coming from our code, as well.

降低噪音通过停止日志。 仍应保留一些日志,并且应该将与这些日志相关的决策与正在执行日志记录的代码分离。所需的粒度是每个文件。我们应该能够选择哪些文件添加或不添加日志消息。最后,这将 not 用于生产代码。

reduce the noise by stopping the log. Some logs should still be kept and the decision about those should be decoupled from the code that is doing the logging. The granularity needed is "per-file". We should be able to choose which files do or do not add log messages. Finally, this will not be used in production code.

假设:这将在开发人员控制的浏览器中运行。在这种情况下,我不会专注于向后兼容性。

Assumption: this will be ran in a developer controlled browser. In that case, I will not focus on backwards compatibility.

首先关闭日志记录可以是使用此全局启用/禁用

First off logging can be enabled/disabled globally using this

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

(问题中贴出的代码,此处也可供参考)

(code posted in the question but also here for reference)


  • 但是,这不允许任何粒度。

  • 这可以修改为仅适用于特定模块,但不能用于第三方代码。

  • 混合方法是全局禁用日志记录,但在每个模块中启用它。问题是我们必须修改我们文件的每个,我们不会得到一些可能有用的外部消息。

  • However, that does not allow for any granularity.
  • This could be modified to work on only specific modules but that cannot be done for third party code.
  • A mixed approach would be to disable logging globally but enable it in each of our modules. Problem there is that we have to modify each of our files and we will not get some potentially useful external messages.

可以使用日志框架,但这可能是一种过度杀伤。虽然,老实说,我认为这就是我想要的,但它可能需要与产品进行一些整合。

A logging framework can be used but it might be an overkill. Although, to be honest, that's what I'd go for, I think, but it may need some integration into the product.

所以,我们需要一些轻量级的东西-ish有一些配置而且不需要漂亮。

So, we need something light-weight-ish that has some configuration and does not need to be pretty.

登录者(标题可能会有变化)

The Loginator (title subject to change)

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

Let's start with the basics - we already know we can override the global log function. We'll take that and work with it. But first, let's recognise that the console object supports more than just .log. There could be various logging functions used. So-o-o, let's disable all of them.

沉默一切

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

这显然可以改善,但它展示了任何和ll日志记录可以停止。实际上,应该留下 console.error 并且 console.warn 也可能有用。但这不是万能的全部解决方案。

This can obviously be improved but it showcases how any and ll logging can be stopped. In reality, console.error should probably be left and console.warn might be also useful. But this is not the be-all-and-end-all solution.

接下来,因为我们可以覆盖控制台功能...为什么不提供我们自己的?

Next, since we can override console functionality...why not supply our own?

自定义记录

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.");

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

That is all the tools we need to roll our own mini-logging framework.

如何进行选择性记录

唯一缺少的是确定哪些文件来自哪个。我们只需堆栈跟踪

The only thing missing is to determine which file something is coming from. We just need 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)
*/

(相关位在这里复制。)

(Relevant bit copied here.)

是的,有一些更好的方法可以做到但不是很多。它要么需要框架,要么需要特定于浏览器 - 错误堆栈不支持正式,但它们可以在Chrome,Edge和Firefox中使用。此外,来吧 - 它实际上是一行 - 我们想要简单而不介意肮脏,所以我很乐意进行权衡。

True, there are some better ways to do it but not a lot. It would either require a framework or it's browser specific - error stacks are not officially supported but they work in Chrome, Edge, and Firefox. Also, come on - it's literally one line - we want simple and don't mind dirty, so I'm happy for the tradeoff.

全部放在一起。 警告:请勿在生产中使用此功能

Putting it all together. Warning: Do NOT use this in production

(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"])

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

So, this is a custom logger. Sure, it's not perfect but it will do the job. And, hey, since the whitelisting is a bit loose, it could be turned to an advantage:


  • 将一堆共享的文件列入白名单一个子字符串,比如说,所有 myApp 都可以包含 myApp1.js myApp2.js myApp3.js

  • 虽然如果您需要特定文件,您可以只传递全名,包括扩展名。我怀疑会有一堆重复的文件名。

  • 最后,堆栈跟踪将包含调用函数的名称(如果有),因此您实际上可以只传递它,并且将按功能列入白名单。但是,它依赖于具有名称的函数,并且函数名称更有可能发生冲突,因此请小心使用

  • to whitelist a bunch of files that share a substring, say, all myApp can include myApp1.js, myApp2.js, and myApp3.js.
  • although if you want specific files, you can just pass the full name, including extension. I doubt there would be a bunch of duplicate filenames.
  • finally, the stack trace will include the name of the calling function, if any, so you can actually just pass that and that will whitelist on per-function basis. However, it relies on the function having a name and it's more likely for function names to clash, so use with care

除此之外,肯定会有改进,但这是它的基础。例如, info / 警告方法也可以被覆盖。

Other than that, there can certainly be improvements but that is the basis of it. The info/warn methods can also be overriden, for example.

所以,如果使用的话,这应该只在dev版本中。有很多方法可以让它不投入生产,所以我不会讨论它们,但我可以提到一件事:如果你将它作为书签保存,你也可以在任何地方使用

So, this, if used, should only be in dev builds. There are a lot of ways to make it not go into production, so I won't discuss them but here is one thing I can mention: you can also use this anywhere if you save it as a bookmarklet

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"]);

这是缩小的(alt我首先通过Babel传递它,使用ES5缩小)并且仍然可配置,在某种程度上,因为你可以改变你可以通过白名单的最终结果。但除此之外,它将工作相同,并完全脱离代码库。它不会在页面加载时运行,但如果需要,您可以将其用作用户脚本(仍然是分离的),或者在dev / debug内的其他JS文件之前包含它

This is it minified (although I passed it through Babel first, to use ES5 minification) and still configurable, to an extent, as you can change the very end where you can pass the whitelist. But other than that, it will work the same and is completely decoupled from the codebase. It will not run at pageload but if that's needed you can either use this as a userscript (still decoupled) or include it before other JS files in dev/debug builds only.

这里有一个注释 - 这适用于Chrome,Edge和Firefox。它是所有最新的浏览器,因此我假设开发人员将至少使用其中一个。这个问题被标记为Chrome,但我决定扩大支持范围。仅限Chrome的解决方案可以稍微好一些,但实际上并没有太大的功能损失。

A note here - this will work in Chrome, Edge and Firefox. It's all the latest browsers, so I assume a developer will use at least one of them. The question is tagged as Chrome but I decided to widen the support. A Chrome only solution could work slightly better but it's not really a big loss of functionality.

这篇关于如何根据特定javascript源(方法,文件)或消息内容的条件禁用console.log消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆