3

I have a large google app script writing lots of log line to the log explorer. I want to be able to disable or enable logging if needed.

Here's a code that seems to work as expected on a browser. Here allowlog is set in code, but it will retrieved from external source. This is not important for the purpose of this post.

The self extracting function overrides console.log and blocks logging if needed.

let allowLog = false; 

function func1(){
  console.log("func1 log msg");
}

(function(){
  //test log 1
  console.log("self extracting");

  //keep ref to global console.log
  const _consolelog = console.log;

  //test log 2 - verify it works
  _consolelog("self extracting2");


//override global console.log
  console.log = function(val){
    if (allowLog){
      _consolelog(val);
      _consolelog("allowing");
    }else{
      _consolelog("log disabled");
    }

  }

})();

This code does not work on google app script, and logs keep on writing.

In app script I can see console.log("self extracting"); and _consolelog("self extracting2"); log messages when module is loaded. However when func1 is called log is written even though allowLog = false. _consolelog("allowing"); nor _consolelog("log disabled"); is NOT logged. the global console.log is not overridden.

Why is that, and how (if at all) it is possible to fix it?

The expected log for the above code is (allowLog=false):

  • self extracting
  • self extracting2
  • log disabled

For the case where allowLog=true:

  • self extracting
  • self extracting2
  • func1 log msg
  • allowing

The first two lines self extracting and self extracting2 should be printed only once, when the anonymous self invoking function is executed. The other should come from the internal function which overides the global one

TheMaster
  • 45,448
  • 6
  • 62
  • 85
OJNSim
  • 736
  • 1
  • 6
  • 22
  • When testing this code as-is, running `func`()` prints `self extracting`, `self extracting2` and `func1 log msg` as I would expect. What do you see that is different and why do you expect something different? Also, you can't override Apps Script classes simply like that, check out [this answer](https://stackoverflow.com/a/65538462/11551468) for more information – Rafa Guillermo Jan 18 '22 at 15:13
  • @Ihopethisishelpfultoyou please see my update for your question – OJNSim Jan 18 '22 at 15:36

2 Answers2

5

This is because the log property of console is not writable. You can check that using Object.getOwnPropertyDescriptors. However, it is still configurable. So, you can delete the log property and set a new value.

let allowLog = false; 
(function(){
  //test log 1
  console.log("self extracting");

  //keep ref to global console.log
  const _consolelog = console.log;

  //test log 2 - verify it works
  _consolelog("self extracting2");


//override global console.log
//console.log(Object.getOwnPropertyDescriptors(console));
/*{ toString: 
   { value: [Function],
     writable: true,
     enumerable: true,
     configurable: true },
  time: 
   { value: [Function],
     writable: true,
     enumerable: true,
     configurable: true },
  timeEnd: 
   { value: [Function],
     writable: true,
     enumerable: true,
     configurable: true },
  error: 
   { value: [Function],
     writable: false,
     enumerable: true,
     configurable: true },
  info: 
   { value: [Function],
     writable: false,
     enumerable: true,
     configurable: true },
  log: 
   { value: [Function],
     writable: false,
     enumerable: true,
     configurable: true },
  warn: 
   { value: [Function],
     writable: false,
     enumerable: true,
     configurable: true } }*/
  delete console.log;
  console.log = function (val){
    if (allowLog){
      _consolelog(val);
      _consolelog("allowing");
    }else{
      _consolelog("log disabled");
    }
  }
})();

function func1(){
  console.log("func1 log msg");
}
TheMaster
  • 45,448
  • 6
  • 62
  • 85
1

Do you mean this?

Logger.log('Test1');  // it will print as usual

var _log = Logger.log
Logger.log = function(_){};

Logger.log('Test2'); // <-- it will not print since we disabled the 'log()' method

Logger.log = _log;   // restore the method 'log()' back
Logger.log('Test3'); // it will print again

Output:

Test1
Test3

enter image description here

Yuri Khristich
  • 13,448
  • 2
  • 8
  • 23
  • Conceptually this is what I want. It seems to work with `Logger` but not with `console`. console class provides better interface (like severity , `console.log()` `console.error()` etc) allowing filtering log messages in the cloud log explorer. Is it possible with class `console` somehow? – OJNSim Jan 18 '22 at 16:14
  • Well. It looks like it's impossible. I can be wrong, though. Perhaps there might be the barbarian solution just to replace all `console.` with `if (allowLog) console.` (Don't forget to make a copy of the code :) ) – Yuri Khristich Jan 18 '22 at 16:31
  • you say barbarian - so I guess I have a cleaner solution. just replace all the very many `console.xxx()` calls to something like `_console.xxx()` where `_console` is a wrapper object. with the help of the _Visual Studio Code_ find and replace is it not that hard. Barbaric as I am, I'm actually not sure I understand your solution.. are you suggesting to enclose all `console` calls with an `if` statement ? – OJNSim Jan 18 '22 at 16:40
  • Yep. I meant `if (allowLog) console.log(...);`. Your solution is less barbarian. I think I'd go with it. – Yuri Khristich Jan 18 '22 at 16:49
  • :) maybe I will. I'll wait to see whether someone else will provide a better solution – OJNSim Jan 18 '22 at 16:51
  • 1
    See _TheMaster_ solution. clear and beautiful – OJNSim Jan 19 '22 at 10:02
  • Beautiful as hell I'd say. ) – Yuri Khristich Jan 19 '22 at 14:46
  • very much indeed – OJNSim Jan 19 '22 at 19:15
  • 1
    This might not be the answer but still is commendable I say. +1 – NightEye Jan 20 '22 at 11:59