after some time, the code is filled with quite some require('utilities').debug('abc').
how to turn it off during the production since it will slow down my app a lot. I expect it is watching some global environment, but cannot find any doc.
/Eric
I don't think that there is a proper way of disabling util.debug output.
The best advice I can get you is to switch to debug module, written by TJ Holowaychuk.
Meanwhile, you may disable util.debug output in production simply by redefining it with an empty function, e.g.:
if (process.env.NODE_ENV === 'production') {
require('util').debug = function() {};
}
I would still recommend to put additional conditions into code for each debug output statement. Like
if (config.debug) { /* do debug output */ }
Overriding built-in function (as Leonid Beschastny suggested), in my opinion, is very bad idea and can lead to conflicts in third party modules.
Related
I'd like to add an important functionality that I can use at work without using require() every time. So, I thought modifying built-in objects can make this happen but I could not locate the locations of those objects to do the modification.
Are those objects in NodeJS binary? Would that mean I have to fork the whole NodeJS repo to make this happen?
Please, I don't want to use prototype editing etc which are same as require. I need to have native feeling.
First off, I agree with an earlier comment that this sounds like a bit of an XY problem where we could better help you if you describe what problem you're really trying to solve. Portable node.js programs that work anywhere or work with any future versions of node.js don't rely on some sort of custom configured environment in order to run. They use the built-in capabilities of node.js and they require/import in external things they want to add to the environment.
Are those objects in NodeJS binary?
Yes, they are in the executable.
Would that mean I have to fork the whole NodeJS repo to make this happen?
Yes.
Please, I don't want to use prototype editing etc which are same as require. I need to have native feeling.
"Native feeling"? This sounds like you haven't really bought into the node.js module architecture. It is different than many other environments. It's easy to get used to over time. IMO, it would really be better to go with the flow and architecture of the platform rather than make some custom version of node.js just to save one line of typing in your startup code.
And, the whole concept of adding a number of globals you can use anywhere pretty much shows that you haven't fully understood the design, architectural, code reuse and testability advantages of the module design baked into node.js. If you had, you wouldn't be trying to write a lot of code that can't be reused in other ways that you don't anticipate now.
That said, in searching through the node.js source code on Github, I found this source file node.js which is where lots of things are added to the node.js global object such as setTimeout(), clearTimeout(), setImmediate(), clearImmediate() and so on. So, that source file seems to be where node.js is setting up the global object. If you wanted to add your own things there, that's one place where it would be done.
To provide a sample of that code (you can see the link above for the complete code):
if (!config.noBrowserGlobals) {
// Override global console from the one provided by the VM
// to the one implemented by Node.js
// https://console.spec.whatwg.org/#console-namespace
exposeNamespace(global, 'console', createGlobalConsole(global.console));
const { URL, URLSearchParams } = require('internal/url');
// https://url.spec.whatwg.org/#url
exposeInterface(global, 'URL', URL);
// https://url.spec.whatwg.org/#urlsearchparams
exposeInterface(global, 'URLSearchParams', URLSearchParams);
const {
TextEncoder, TextDecoder
} = require('internal/encoding');
// https://encoding.spec.whatwg.org/#textencoder
exposeInterface(global, 'TextEncoder', TextEncoder);
// https://encoding.spec.whatwg.org/#textdecoder
exposeInterface(global, 'TextDecoder', TextDecoder);
// https://html.spec.whatwg.org/multipage/webappapis.html#windoworworkerglobalscope
const timers = require('timers');
defineOperation(global, 'clearInterval', timers.clearInterval);
defineOperation(global, 'clearTimeout', timers.clearTimeout);
defineOperation(global, 'setInterval', timers.setInterval);
defineOperation(global, 'setTimeout', timers.setTimeout);
defineOperation(global, 'queueMicrotask', queueMicrotask);
// Non-standard extensions:
defineOperation(global, 'clearImmediate', timers.clearImmediate);
defineOperation(global, 'setImmediate', timers.setImmediate);
}
This code is built into the node.js executable so the only way I know of to directly modify it (without hackish patching of the executable itself) would be to modify the file and then rebuild node.js for your platform into a custom build.
On a little more practical note, you can also use the -r module command line argument to tell node.js to run require(module) before starting your main script. So, you could make a different way of starting node.js from a shell file that always passes the -r fullPathToYourModule argument to node.js so it will always run your startup module that adds things to the global object.
Again, you'd be doing this just to save one line of typing in your startup file. It is really worth doing that?
I use debug strings for debugging Loopback 2.0 application. Loopback documentation says:
The LoopBack framework has a number of built-in debug strings to help
with debugging. Specify a string on the command-line via an
environment variable as follows:
MacOS and Linux
$ DEBUG=<pattern>[,<pattern>...] node .
Is it possible to change patterns dynamically in runtime? Or is it possible to use environment-specific configuration?
Before I get deeper note that this debug logging facility uses visionmedia's debug module which handles almost all of the logic.
Is it possible to change patterns dynamically in runtime?
Well before any module is loaded, safest and best way I believe is to just manipulate the environmental variables:
if (process.env.NODE_ENV === 'development') {
process.env.DEBUG = process.env.DEBUG + ',loopback:*';
}
Another way would be to load debug and use it's .enable method:
require('debug').enable('loopabck:*');
But note that it only works if you do this before Loopback is required since it only allows changes before it's instances are created, which is in this case before loopback is loaded. Another thing is that, there might be multiple debug modules installed depending on the dependencies and your package manager(npm#3, npm#2 and yarn behave differently). debug might be in your node_modules directory, or it might be in loopback each module, node_modules directory. So make sure you require all instances of it and enable, if you want to do it this way.
Now if don't want to do it on the startup, well API doesn't allow changes in the runtime. You can view the discussion regarding this here. Though there are some dirty ways to go around it, but these might possibly break in the future so be careful.
Firstly, there's a module called hot-debug which supposedly makes require('debug').enable work on previously created instances also, but when I tried it, it didn't work perfectly and it was buggy, but it's possible it might work fine for you.
If that doesn't work for you another way is to override require('debug').log method. If this is defined, debug will call this method instead of console.log with the formatted the arguments. You can set DEBUG=* and then filter it yourself:
require('debug').log = function (string) {
if (string.contains('loopback:security')) {
console.log(string);
}
};
This way will be slow in production though as all the debug output will be formatted before being filtered even though nothing might be outputted to console.
Another thing to override the require('debug').init method. This is called everytime a new debug instance is created. Since every debug instance uses an enabled property to check if it's enabled we can toggle that.
const debug = require('debug');
const { init } = debug;
const instances = [];
debug.init = function(debugInstance) {
init(debugInstance);
instances.push(debugInstance);
};
// You can call this function later to enable a given namespace like loopback.security.acl
function enableNamespace(namespace) {
instances.forEach(instance => {
instance.enabled = instance.namespace === namespace;
});
}
Though there's a lot of improvement can be done on this, but you get the idea.
I can change debug namespace dynamically with the hot-debug module.
In my app, I've just created a function for this :
require('hot-debug')
const debug = require('debug')
function forceDebugNamespaces (namespaces) {
debug.enable(namespaces)
}
// Usage
forceDebugNamespaces('*,-express:*,-nodemon:*,-nodemon')
In my case, I have a config file which allow me to set process.env.DEBUG but I needed to find a way to update debug namespaces without restarting my app (the config file is watched for changed by my app).
I'm wondering is there a capability, in any programming language, that I can choose to compile only a certain part of code. See example below.
This is a block of pseudocode:
function foo() {
if (isDebug) {
checkSomethingForDebugging();
print(some debug info);
}
toSomeFooThings();
}
This block is for debugging purpose, I want to ignore them (even the if statement) in production.
if (isDebug) {
checkSomethingForDebugging();
print(some debug info);
}
One thing I can do is to comment out these lines,
function foo() {
//if (isDebug) {
// checkSomethingForDebugging();
// print(some debug info);
//}
toSomeFooThings();
}
But what if I have thousands of places like this? It will be good if there is a way (a flag) that I can choose to compile a certain part of the code or not. It's like a debugging build. Is there anything for this in any programming language? I did search online but was no luck.
Most languages don't have this, but you could certainly write a script which processed the source code somewhere in your build/deploy pipeline and deleted the debug only parts. An advanced way would be to properly parse the source code and delete the appropriate if blocks. For Python this would be quite easy using either the ast module or just looking for lines saying if is_debug: and then watching the indentation level. For other languages it might be harder. A simpler way in terms of the preprocessing script would be to use delimiting comments:
// DEBUGONLY
checkSomethingForDebugging();
print(some debug info);
// ENDDEBUGONLY
In this case the if statement is optional depending on how exactly you want to do things.
Well, that depends on the compiler you are using. For example, in GCC for the C programming language, you have a whole set of preprocessor instructions that could be used for that.
For example:
#ifdef DEBUG
// Your code here...
#endif /* DEBUG */
And, when you are compiling the debug version, you just have to include an extra header that defines the DEBUG macro. There's no need of setting any value, just define it.
#define DEBUG
And that's it.
There are languages (including C, C++ and C#) that can do this using preprocessor directives like #if or #ifdef:
#if DEBUG
checkSomethingForDebugging();
print(some debug info);
#endif
When the code is compiled, if the DEBUG symbol is not set, the code between the two directives is not compiled at all (and doesn't even have to be valid code).
But more importantly, why are you asking? If you're worried about performance, then such checks are very cheap (since they are easily predicted). And if the checks are written right (e.g. if isDebug is a global constant) and compiled using a good compiler, they can even be eliminated as dead code, which makes them completely free.
In compiling languages like C we have a preprocessor that can be used to skip parts of program without compiling them, effectively just excluding them from the source code:
#ifdef SHOULD_RUN_THIS
/* this code not always runs */
#endif
So that if SHOULD_RUN_THIS is not defined, then the code will never be run.
In node.js we don't have a direct equivalent of this, so the first thing I can imagine is
if (config.SHOULD_RUN_THIS) {
/* this code not always runs */
}
However in node there is no way to guarantee that config.SHOULD_RUN_THIS will never change, so if (...) check will be performed each time in vain.
What would be the most performant way to rewrite it? I can think of
a) create a separate function to allow v8-optimizations:
function f(args) {
if (config.SHOULD_RUN_THIS) {
/* this code not always runs */
}
}
// ...
f(args);
b) create a variable to store the function and set it to an empty function when not needed:
var f;
if (config.SHOULD_RUN_THIS) {
f = (args) => {
/* this code not always runs */
}
}
else {
f = function () {} // does nothing
}
// ...
f(args);
c) do not create a separate function, just leave it in place:
if (config.SHOULD_RUN_THIS) {
/* this code not always runs */
}
What is the most performant way? Maybe some other way...
i personally would adopt ...
if (config.SHOULD_RUN_THIS) {
require('/path/for/conditional/module');
}
the module code is only required where needed, otherwise it is not even loaded in memory let alone executed.
the only downside is that it is not readily clear which modules are being required since your require statements are not all positioned at the top of the file.
es6 modularity adopts this dynamic module request approach.
PS use of config like this is great since, you can for example, use an environment variable to determine your code path. Great when spinning up, for example, a bunch of docker containers that you want to behave differently depending on the env vars passed to the docker run statements.
apologies for this insight if you are not a docker fan :) apologies i am waffling now!
if you're looking for a preprocessor for your Javascript, why not use a preprocessor for your Javascript? It's node-compatible and appears to do what you need. You could also look into writing a plugin for Babel or some other JS mangling tool (or v8 itself!)
If you're looking for a way to do this inside the language itself, I'd avoid any optimizations which target a single engine like v8 unless you're sure that's the only place your code will ever run. Otherwise, as has been mentioned, try breaking out conditional code into a separate module so it's only loaded if necessary for it to run.
When I do for..in, can I dispense with the if (obj.hasOwnProperty(key)) {...} check in Node.js if I am careful never to modify Object.prototype myself?
Or if I require() some third party package that happens to modify Object.prototype, does that screw up the Object.prototype for my module too?
Can I dispense with the if (obj.hasOwnProperty(key)) {...} check in Node.js if I am careful never to modify Object.prototype myself?
No, because Object is global. Anyone that messes with it in any module you use (or, any module they use by proxy) and they've broken it for your code regardless of what you do. The property check is damage control. It's a check on the nature of someone mucking with you're implicitly inheriting from.
node_modules/breakit.js
Object.prototype.foobar = () => "borked";
module.exports = true;
run node..
> require('breakit');
true
> let a = {};
> for ( let k in a ) { console.log(k) }
foobar
> a.foobar();
borked
It's important that while the .hasOwnProperty is necessary for the for .. in loop, the loop itself is probably not necessary and better avoided in most cases. The air-bnb eslint style guide for instance bans looping over an object all together.
There is nothing specific in node that would warrant not having this check. If you are already using lodash you can use _.forOwn() https://lodash.com/docs#forOwn
Another option is:
Object.getOwnPropertyNames(yourObj)
.forEach(function(keyName) {
yourObj[keyName] // do stuff
});
Or continue doing the 'if' check, there's a few options, but I would definitely keep one of the checks in, your choice which.