How to programmatically detect debug mode in nodejs? - debugging

I've seen this question asked of other platform/languages - any ideas? I'd like to do something like:
if (detectDebug())
{
require('tty').setRawMode(true);
var stdin = process.openStdin();
stdin.on('keypress', function (chunk, key) {
DoWork();
}
}
else
{
DoWork();
}
I'd like to be able to toggle keyboard input as a start for the script when debugging so that I can have a moment to fire up chrome to listen to my node-inspector port.
***Quick update - I'm guessing I can actually use "process.argv" to detect if --debug was passed in. Is this the best/right way?

NodeJS creates a v8debug global object when running in debug mode: node debug script.js
So, a possible solution would be:
var debug = typeof v8debug === 'object';
For my use case, I use it because I want to avoid passing environment variables. My main node process starts child node processes and I want a node debug mainScript.js to trigger debug mode for children as well (again, without passing env variables to child processes)

I use this
var debug = typeof v8debug === 'object'
|| /--debug|--inspect/.test(process.execArgv.join(' '));
which supports, --debug, --debug-brk, --inspect and --inspect=1234

There is a node.js native support that using inspector.url() to check if there is active inspector, it just shows if process is debug mode or not currently. See doc for more.

The global v8debug variable mentioned in the other answers seem to be removed in Node v7.0.0 (see https://github.com/nodejs/node/issues/9617). Also, checking process arguments (i.e. process.execArgv) seem to be unreliable since Node can enter debug mode at runtime. VS Code, for example, doesn't always starts Node with the --inspect option even when debugging. (depend on your debug config)
The most reliable solution I could find is to use inspector.url() to check if Node is listening for debug connections.
const inspector = require('inspector');
function isInDebugMode() {
return inspector.url() !== undefined;
}
I have tested this method with Node versions v12.22.1, v14.16.1, and v16.1.0 and it worked for all of them.

I think there's a bunch of confusion in this question.
Based on your question, I think what you really want is the node --debug-brk command line flag. That will have node start v8 with a debugger running and automatically stop on a breakpoint before the first line of your .js program. You don't need to reinvent this. I use this for debugging mocha tests, express.js startup issues, etc. This will eliminate your need to detect this manually.
Secondly, NODE_ENV=production is nothing more than a convention that many programs use to indicate "you are running in production" and therefore certain things like really sending emails, using the real payment gateway, etc should be enabled. However what environment you are in when NODE_ENV is NOT production (or is unset) should definitely NOT be assumed to be debugging. The most sane assumption there is that the environment is a development environment, but even then this whole convention is pretty brittle in my opinion.
Thirdly, just FYI check out tty.isatty() which will accurately tell you if your program is being run on an interactive terminal (like from a command shell). This will be false when your program is being run by a process supervisor provided by your OS (upstart, sysvinit, etc). This check is commonly use to toggle command line programs between interactive and scripted modes. It's not entirely perfect or infallible, but it is widely adopted in the posix world.
Fourth, from some quick experimentation, the v8debug global #Gabriel Petrovay indicates seems to only be set when doing node debug script.js and not set when doing node --debug script.js. Not sure why that is. If such a thing was reliable, that would seem like the most correct approach to finding out "is this v8 instance in debug mode".

var detectDebug = function() {
return process.env.NODE_ENV !== 'production';
};
to run in debug mode:
$ node app.js
to run in production mode:
$ NODE_ENV=production node app.js
Some frameworks recognize the production mode this way. See express.js doc.

The global.v8debug object only seems to be created / exposed when the debug or --debug-brk command line option is set. It's strange and annoying it's not created when --debug is set.
A hacky way to do this would be to look at the process.execArgv array (not process.argv) for --debug, --debug-brk or debug.

process.debugPort appears to always be present and defaults to 5858. The only way to detect if the program was started explicitly with --debug is to check the process.execArgv array. --debug-brk is pretty obvious to detect: your program won't do anything and you'll get a message about a debugger listening, so that's trivial to figure out. v8debug appears to be present when the program is started with node debug file.js or when a debugger like node-inspector is currently attached.
Keeping all that in mind, this code will detect whether a debugger (of any kind) is currently attached.
var debug, withDebug;
debug = false;
if (typeof v8debug !== "undefined" && v8debug !== null) {
console.log("v8 debug detected");
debug = true;
}
withDebug = process.execArgv.indexOf('--debug') > -1 || process.execArgv.indexOf('--debug-brk') > -1;
if (withDebug) {
console.log("started with debug flag, port: " + process.debugPort);
debug = true;
}
if ((typeof v8debug === "undefined" || v8debug === null) && !withDebug) {
console.log("neither detected");
}

There is no v8debug in versions of nodejs >=7.
It seems that the most simple way is to check command line parameters. In debug mode there will be a word 'debug' or 'inspect'
const argv = process.execArgv.join();
const isDebug = argv.includes('inspect') || argv.includes('debug');

There simple solution is here.
But in general, detect debug mode is not easy - https://github.com/nodejs/node/issues/9617

Object.defineProperty(global, 'isDebugging', {
get: function () {
return typeof v8debug !== 'undefined';
}
});
This works well for webstorm

I had the same issue, how to check the app to see if it is running on --inspect.
I m on nodejs 14, and the solution with the v8debug that mentioned above, looks that it does not work any more, for clarity i post the message that i get when i try --debug.
node: [DEP0062]: node --debugandnode --debug-brkare invalid. Please usenode --inspectandnode --inspect-brk instead.
Solution
So how i tackle with this, is to query the process.execArgv which is exactly what you need too.
snipet:
const isInspect = process.execArgv.join() === '--inspect'
//or ....process.execArgv.toString() === ...
This execArgv, as the docs state:
The process.execArgv property returns the set of Node.js-specific command-line options passed when the Node.js process was launched. These options do not appear in the array returned by the process.argv property, and do not include the Node.js executable, the name of the script, or any options following the script name. These options are useful in order to spawn child processes with the same execution environment as the parent.
More in the docs: https://nodejs.org/docs/latest-v6.x/api/process.html#process_process_execargv

Related

Tips on solving 'DevTools was disconnected from the page' and Electron Helper dies

I've a problem with Electron where the app goes blank. i.e. It becomes a white screen. If I open the dev tools it displays the following message.
In ActivityMonitor I can see the number of Electron Helper processes drops from 3 to 2 when this happens. Plus it seems I'm not the only person to come across it. e.g.
Facing "Devtools was disconnected from the page. Once page is reloaded, Devtools will automatically reconnect."
Electron dying without any information, what now?
But I've yet to find an answer that helps. In scenarios where Electron crashes are there any good approaches to identifying the problem?
For context I'm loading an sdk into Electron. Originally I was using browserify to package it which worked fine. But I want to move to the SDKs npm release. This version seems to have introduced the problem (though the code should be the same).
A good bit of time has passed since I originally posted this question. I'll answer it myself in case my mistake can assist anyone.
I never got a "solution" to the original problem. At a much later date I switched across to the npm release of the sdk and it worked.
But before that time I'd hit this issue again. Luckily, by then, I'd added a logger that also wrote console to file. With it I noticed that a JavaScript syntax error caused the crash. e.g. Missing closing bracket, etc.
I suspect that's what caused my original problem. But the Chrome dev tools do the worst thing by blanking the console rather than preserve it when the tools crash.
Code I used to setup a logger
/*global window */
const winston = require('winston');
const prettyMs = require('pretty-ms');
/**
* Proxy the standard 'console' object and redirect it toward a logger.
*/
class Logger {
constructor() {
// Retain a reference to the original console
this.originalConsole = window.console;
this.timers = new Map([]);
// Configure a logger
this.logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.printf(({ level, message, timestamp }) => {
return `${timestamp} ${level}: ${message}`;
})
),
transports: [
new winston.transports.File(
{
filename: `${require('electron').remote.app.getPath('userData')}/logs/downloader.log`, // Note: require('electron').remote is undefined when I include it in the normal imports
handleExceptions: true, // Log unhandled exceptions
maxsize: 1048576, // 10 MB
maxFiles: 10
}
)
]
});
const _this = this;
// Switch out the console with a proxied version
window.console = new Proxy(this.originalConsole, {
// Override the console functions
get(target, property) {
// Leverage the identical logger functions
if (['debug', 'info', 'warn', 'error'].includes(property)) return (...parameters) => {
_this.logger[property](parameters);
// Simple approach to logging to console. Initially considered
// using a custom logger. But this is much easier to implement.
// Downside is that the format differs but I can live with that
_this.originalConsole[property](...parameters);
}
// The log function differs in logger so map it to info
if ('log' === property) return (...parameters) => {
_this.logger.info(parameters);
_this.originalConsole.info(...parameters);
}
// Re-implement the time and timeEnd functions
if ('time' === property) return (label) => _this.timers.set(label, window.performance.now());
if ('timeEnd' === property) return (label) => {
const now = window.performance.now();
if (!_this.timers.has(label)) {
_this.logger.warn(`console.timeEnd('${label}') called without preceding console.time('${label}')! Or console.timeEnd('${label}') has been called more than once.`)
}
const timeTaken = prettyMs(now - _this.timers.get(label));
_this.timers.delete(label);
const message = `${label} ${timeTaken}`;
_this.logger.info(message);
_this.originalConsole.info(message);
}
// Any non-overriden functions are passed to console
return target[property];
}
});
}
}
/**
* Calling this function switches the window.console for a proxied version.
* The proxy allows us to redirect the call to a logger.
*/
function switchConsoleToLogger() { new Logger(); } // eslint-disable-line no-unused-vars
Then in index.html I load this script first
<script src="js/logger.js"></script>
<script>switchConsoleToLogger()</script>
I had installed Google Chrome version 79.0.3945.130 (64 bit). My app was going to crash every time when I was in debug mode. I try all the solutions I found on the web but no one was useful. I downgrade to all the previous version:
78.x Crashed
77.x Crashed
75.x Not Crashed
I had to re-install the version 75.0.3770.80 (64 bit). Problem has been solved. It can be a new versions of Chrome problem. I sent feedback to Chrome assistence.
My problem was that I was not loading a page such as index.html. Once I loaded problem went away.
parentWindow = new BrowserWindow({
title: 'parent'
});
parentWindow.loadURL(`file://${__dirname}/index.html`);
parentWindow.webContents.openDevTools();
The trick to debugging a crash like this, is to enable logging, which is apparently disabled by default. This is done by setting the environment variable ELECTRON_ENABLE_LOGGING=1, as mentioned in this GitHub issue.
With that enabled, you should see something along the lines of this in the console:
You can download Google Chrome Canary. I was facing this problem on Google Chrome where DevTools was crashing every time on the same spot. On Chrome Canary the debugger doesn't crash.
I also faced the exact same problem
I was trying to require sqlite3 module from renderer side
which was causing a problem but once i removed the request it was working just fine
const {app , BrowserWindow , ipcMain, ipcRenderer } = require('electron')
const { event } = require('jquery')
const sqlite3 = require('sqlite3').verbose(); // <<== problem
I think the best way to solve this (if your code is really really small) just try to remove functions and run it over and over again eventually you can narrow it down to the core problem
It is a really tedious , dumb and not a smart way of doing it , but hey it worked
I encountered this issue, and couldn't figure out why the the DevTool was constantly disconnecting. So on a whim I launched Firefox Developer edition and identified the cause as an undefined variable with a string length property.
if ( args.length > 1 ) {
$( this ).find( "option" ).each(function () {
$( $( this ).attr( "s-group" ) ).hide();
});
$( args ).show();
}
TL;DR Firefox Developer edition can identify these kinds of problems when Chrome's DevTool fails.
After reading the comments above it is clear to me that there is a problem at least in Chrome that consists of not showing any indication of what the fault comes from. In Firefox, the program works but with a long delay.
But, as Shane Gannon said, the origin of the problem is certainly not in a browser but it is in the code: in my case, I had opened a while loop without adding the corresponding incremental, which made the loop infinite. As in the example below:
var a = 0;
while (a < 10) {
...
a ++ // this is the part I was missing;
}
Once this was corrected, the problem disappeared.
I found that upgrading to
react 17.0.2
react-dom 17.0.2
react-scripts 4.0.3
but also as react-scripts start is being used to run electron maybe its just react scripts that needs updating.
Well I nearly went crazy but with electron the main problem I realized I commented out the code to fetch (index.html)
// and load the index.html of the app.
mainWindow.loadFile('index.html');
check this side and make sure you have included it. without this the page will go black or wont load. so check your index.js to see if there's something to load your index.html file :) feel free to mail : profnird#gmail.com if you need additional help
Downgrade from Electron 11 to Electron 8.2 worked for me in Angular 11 - Electron - Typeorm -sqlite3 app.
It is not a solution as such, but it is an assumption of why the problem.
In the angular 'ngOnInit' lifecycle I put too many 'for' and 'while' loops, one inside the other, after cleaning the code and making it more compact, the problem disappeared, I think maybe because it didn't finish the processes within a time limit I hope someone finds this comment helpful. :)
I have stumbled upon the similar problem, My approach is comment out some line that I just added to see if it works. And if that is the case, those problem is at those lines of code.
for(var i = 0;i<objLen; i+3 ){
input_data.push(jsonObj[i].reading2);
input_label.push(jsonObj[i].dateTime);
}
The console works fine after i change the code to like this.
for(var i = 0;i<objLen; i=i+space ){
input_data.push(jsonObj[i].reading2);
input_label.push(jsonObj[i].dateTime);
}
Open your google dev console (Ctrl + shift + i). Then press (fn + F1) or just F1, then scroll down and click on the Restore defaults and reload.

Suppress REST Logging Calls from Supertest

I have started using MEAN stack and currently writing REST unit tests using Super Test
I want to have a little bit more clarity in my log file so that I can easily see my successful and failed tests.
I wish to suppress the console output for the actual rest API call which I think are coming out of SuperTest.
This image shows the logs I want to suppress.
I think it's actually coming from expressjs/morgan. I've gotten around it by setting the env to test and disabling morgan for the test env.
In my test files:
process.env.NODE_ENV = 'test';
In app.js:
if(app.get('env') !== 'test') app.use(logger('dev'));
You can setup morgan to accept a skip function.
Then, you can, say, toggle an env variable on/off - or define skipping logic of your own to temporarily mute the logging.
app.use(
logger('dev', {
skip: function(req, res) {
return process.env.MUTE_LOGGER === 'on';
},
}),
);

How to initialize terminal manually?

how may i log stuff into the terminal before the user focuses the terminal and presses enter key?
I cannot find a way to access the echo method of the terminal outside a call function scope.
The "greetings" option is good but it does not help, i am trying to use the terminal to show the logs of a background application that is constantly running.
Thank you.
Found it, by setting the "terminal" method to a variable it actually returns the created terminal (as a constructor).
Took me a while to find out, maybe because i don't have much experience with JScript and it has some different concepts about variable access, inheritance, etc.. than other languages.
Now i can store the created terminal and use it right after creation:
$(function () {
var terminal;
terminal = $('#consolediv').terminal(function(command, term) {
if (command !== '') {
interp.eval(command);
} else {
term.echo('');
}
}, { greetings: false });
terminal.echo("logging and using terminal right after creation");
});

How to Program xulrunner application to display output file or command line?

My question is in response to this article
https://developer.mozilla.org/En/How_to_check_the_security_state_of_an_XMLHTTPRequest_over_SSL
I have downloaded and configured the xulrunner the only problem I'm getting to run javascript given in the link to display it output. Using xulrunner i want to know how can i produce an output as a headerless command-line program not gui.
var httpRequest = Components.classes["#mozilla.org/xmlextr/xmlhttprequest;1"].createInstance();
// Disable alert popups on SSL error
httpRequest.mozBackgroundRequest = true;
httpRequest.open("GET", "https://developer.mozilla.org/", true);
httpRequest.onreadystatechange = function (aEvt) {
if (httpRequest.readyState == 4) {
// Print security state of request
dumpSecurityInfo(httpRequest.channel);
}
};
httpRequest.send(null);
In the above code taken from the same link i want to see the output of function on my command screen or even a writing the information to file would do.
Do i have to change something in *.xul file extension.? I'm new to using xulrunner some help would be very helpful for me.
To print something to the console you use the dump() function. If your code runs in the context of a window you will need to change browser.dom.window.dump.enabled preference to true. XPCOM components can simply call dump() without changing this preference.

Logging an onFailure inError in WebOS

An onFailure handler in webOS has an argument inError. I tried printing it using: console.log("error: " + inError);, but the result is only: error: [object Object]*** (app/assistants/main-assistant.js:26), which isn't much use. How can I log something more useful instead?
Update:
Ares generates: alarm1Failure: function(inSender, inError) {}. However, the error is contained as the errorText property of the first object and the second object is the request
I would use the interactive debugger at:
http://ares.palm.com/AresDebug/
Connect your device and run your app. Put your app name in the 'Script Filter' box and click get scripts.
Now use the 'Available Scripts' pull down to find your assembly.
You can set breakpoints (click on line numbers to the left) and inspect variables using the lower left pane and '>' prompt.
Be sure to use Chrome or Safari as it will not work with IE.
There is also a logger at:
http://ares.palm.com/AresLog/
if you don't want to use the debugger, then you probably should know something about the inError object getting returned to you. In this case I assume the onFailure comes from a Protocol function's callback, so try looking in the Protocol documentation to see what information the error object should contain.
Also for any logging purposes don't forget about the imensely useful function
JSON.stringify(obj)
It will take an object and return a JSON representation that you can log so you can see all the properties at once.

Resources