npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

tud

v1.0.0-rc.2

Published

Asynchronous Stack Trace Debugging Framework for node with Two Underscore Debugging APIs

Downloads

10

Readme

tud ( Two Underscore Debugger )         is Asynchronous Stack Trace Framework to debug Node.js applications

01: var tud = require('tud')();
02: 
03: setTimeout(
04:     function helloWorld(){ console.log('Hello World') }, 3000
05: );

consoleOutput

Installation

Node.js 0.10 or higher is supported.

$ npm install tud

Features

You do not need to modify your code to use tud. Just by including tud, you can view the fully traced asynchronous function call stacks and track the flow of the application currently operating.

  • trace of asynchronous function call stacks
  • trace of node system objects derived from EventEmitter class
  • trace of process creation and termination
  • categorized logging of multiple processes' console output
  • debugging APIs which has no effect on user code
  • support for WebStorm run and debug console

Tud hooks the Node.js's child_process, events, timers module and process.nextTick function at the top of user's main application code, and it uses async_wrap binding and async_hooks module for the asynchronous io calls mainly raised by the modules like fs and net.

Tud provides logging for stdout and stderr but it is not intended for operating mode logger. And it can not be used with modules that use Error.prepareStackTrace() or other hooking techniques.

Usage

Stack View

There are two types of stacks. One is the stack of asynchronous function call or debugging API call called from user code. The other is the asynchronous function call stack called from node libraries or npm modules. And there are two types of options for each. One is nodeAsyncCallLog and userAsyncCallLog which determine what is logged. The other is nodeStackViewLvl and userStackViewLvl which determine whether it shows full stack or not.

For the support of the functionality to go directly to the source code by clicking on the stack call line in WebStorm console, there are two options: webstormConsoleSrcPath and webstormConsoleLibPath. Each changes application root path and node system modules' root path.

01: var tud = require('tud')({
02:     showProcessInitExitLog: false,
03:     nodeStackViewLvl: 'off',
04:     userStackViewLvl: { asyncCall: 'app', debugCall: 'sys' }
05: });
06: 
07: setTimeout(
08:     function helloWorld(){ console.log('Hello World') }, 3000
09: );

consoleOutput

back to top

Asynchronous Stack Tracing

Tud uses A ASYNC, N NTICK, T TIMER and E EVENT tags as asynchronous type specifiers in stack message.

01: var tud = require('tud')({
02:     showProcessInitExitLog: false,
03:     showProcessEventLog: false,
04:     nodeAsyncCallLog: true,
05:     userAsyncCallLog: true,
06:     nodeStackViewLvl: 'off',
07:     userStackViewLvl: 'app'
08: });
09: 
10: function httpOnCloseCallback() {
11:     process.nextTick(function nextTickCallback() {
12:         console.log('Server is closed.');
13:     });
14: }
15: function httpListenCallback() {
16:     console.log('Server is listening.');
17:     setTimeout(
18:         function setTimeoutCallback(){ server.close() }, 3000
19:     );
20: }
21: var server = require('http').createServer()
22:     .on('close', httpOnCloseCallback)
23:     .listen(8080, httpListenCallback)
24: ;

consoleOutput

Promise stack trace is supported by async_hooks module in Node.js versions greater than or equal to 8.0.0. You can use the bluebird instead in versions below.

01: var tud = require('tud')({
02:     showProcessInitExitLog: false,
03:     showProcessEventLog: false,
04:     nodeAsyncCallLog: true,
05:     userAsyncCallLog: true,
06:     nodeStackViewLvl: 'off',
07:     userStackViewLvl: 'app'
08: });
09: 
10: if (process.version[1] < 8) Promise = require("bluebird");
11: 
12: function lookupUrl(url) {
13:     return new Promise(
14:         function(resolve, reject) {
15:             require('dns').lookup(url,
16:                 function dnsLookupCallback(error, addresses) {
17:                     if (error) reject(error);
18:                     else resolve(addresses);
19:                 }
20:             );
21:         }
22:     ).then(
23:         function(addresses) {
24:             console.log(url, addresses);
25:         }
26:     );
27: }
28: lookupUrl('example.co').catch(
29:     function(error) {
30:         return lookupUrl('example.com');
31:     }
32: ).catch(
33:     function(error) {
34:         console.error('There is no available url.');
35:     }
36: );

consoleOutput

consoleOutput

back to top

Parallel Processes Tracing

Tud hooks process.stdout.write() and process.stderr.write() and all hooked data go with the tud log message. Use process.stdout.writeNative() or process.stderr.writeNative() as the original method before being hooked.

There are some exceptional cases associated with stdio in node.js 0.10.x and 0.12.x versions, especially stdin. useStdioWriteSync option changes the asynchronous socket write to the synchronous file write. Use untouchableStdin option when a parent process spawning a child process abruptly freezes or an abnormal case occurs by stdin.

01: var tud = require('tud')({ showProcessInitExitLog: { init: false } });
02: 
03: console.log('I am a grandpa.');
04: 
05: var child_process = require('child_process');
06: var child1 = child_process.spawn('node', ['dad.js'], {stdio: 'inherit'});
07: var child2 = child_process.spawn('node', ['mom.js'], {stdio: 'pipe'});
08: child2.stdout.on('data', function(chunk){ process.stdout.writeNative(chunk) });
09: child2.stderr.on('data', function(chunk){ process.stderr.writeNative(chunk) });
01: var tud = require('tud')({ showProcessInitExitLog: { init: false } });
02: 
03: console.log('I am a dad.');
04: 
05: var child = require('child_process').fork('honey.js');
06: if (child.connected) child.send('Good night, honey ~');
01: var tud = require('tud')({ showProcessInitExitLog: { init: false } });
02: 
03: console.log('I am a mom.');
01: var tud = require('tud')({ showProcessInitExitLog: { init: false } });
02: 
03: if (process.connected)
04:     process.on('message', function processOnMessageCallback(message) {
05:         console.log('received message : ' + message);
06:         process.disconnect();
07:     });

consoleOutput

back to top

Console Output Logging

There are two types of loggers: file and pipe. The file type logger is synchronously written, and the possible dest parameter values are the path string and file descriptor number of the file. On the other hand, the pipe type logger is asynchronously written, and the possible dest parameter values are the path string, file descriptor number and writable stream of the file. Tud does not check the closed state of any logger so you should explicitly call tud.removeLogger(dest[, type[, data]]) when you try to close the file descriptor or writable stream.

01: var pipeStream = new require('stream').PassThrough();
02: 
03: var tud = require('tud')({
04:     showProcessInitExitLog: false,
05:     userAsyncCallLog:  false,
06:     userStackViewLvl: 'off',
07:     logger : [
08:         { type: 'file', data: 'out', dest: 'stdout.log' },
09:         { type: 'file', data: 'err', dest: 'stderr.log' },
10:         { type: 'file', dest: 'stdall.log' },
11:         { dest: pipeStream }
12:     ]
13: });
14: 
15: process.on('exit', function() {
16:     require('fs').writeFileSync('stdallPipe.log', pipeStream.read());
17: });
18: console.log('stdout message');
19: console.error('stderr message');

consoleOutput

back to top

Debugging APIs

Debugging APIs provided by tud
tud.debug()
tud.debug( {string} message )  ->  message
tud.debug( {string} title, {any} value [, {number|null|object} inspectDepthOrInspectOptionsObject] )  ->  value

tud.messg( {string} ...args )  ->  args[0]
tud.value(    {any} ...args )  ->  args[0]

tud.proto( {object} value [, {number|null|object} inspectDepthOrInspectOptionsObject] )  ->  value

tud.error(  {Error} error [, {string} message] )  ->  error

tud.check( {boolean} value                 [, {boolean} noExitOnFail] )  ->  value
tud.check(     {any} value , {string} type [, {boolean} noExitOnFail] )  ->  value
Global API name aliases
tud() == tud.debug() == __debug() == __d() == __()
         tud.messg() == __messg() == __m()
         tud.value() == __value() == __v()
         tud.proto() == __proto() == __p()
         tud.error() == __error() == __e()
         tud.check() == __check() == __c()
01: var tud = require('tud')({
02:     showProcessInitExitLog: false,
03:     userStackViewLvl: 'off'
04: });
05: 
06: var map = {
07:     key: 'message 0', obj: {
08:         key: 'message 1', obj: {
09:             key: 'message 2', obj: {
10:                 key: 'message 3'
11: }}}};
12: 
13: process.nextTick(function whereIsHere(){
14:     __();
15: });
16: __('message');
17: __('default depth', map   );
18: __(      '2 depth', map, 2);
19: 
20: __m(   'message a' ,    'message b' ,    'message c');
21: __v({a:'message a'}, {b:'message b'}, {c:'message c'}, map);
22: 
23: function A(){ this.a = 123 }
24: A.prototype = { a: 999 };
25: __p(new A());

consoleOutput

01: var tud = require('tud')({
02:     showProcessInitExitLog: false,
03:     showProcessEventLog: false,
04:     nodeAsyncCallLog: true
05: });
06: 
07: var fs = require('fs');
08: fs.readFile('notExistPath', function(err, data) {
09:     if (err) {
10:         __e(err, 'Here is optional debugging message.');
11:         fs.readFile(__filename, function(err, data) {
12:             err ? __e(err) : __('data.length', data.length);
13:         });
14:     } else {
15:         __('data.length', data.length);
16:     }
17: });

consoleOutput

Check types
'u'  | 'undefined'
'nu' | 'null'     
'b'  | 'boolean'  
'n'  | 'number'   
's'  | 'string'   
'f'  | 'function' 
'o'  | 'object'   
'e'  | 'error'    
'a'  | 'array'    
'al' | 'arraylike'
01: var tud = require('tud')({
02:     showProcessInitExitLog: false,
03:     userStackViewLvl: 'off',
04:     showSucceededCheckLog: true
05: });
06: 
07: (function truthCheck(arg1, arg2) {
08:     __c(arg1);
09:     __c(arg2);
10: })('a');
11: 
12: (function arrayLikeCheck(arg) {
13:     __c(arg, 'a');
14:     __c(arg, 'al');
15:     __c(arguments, 'a');
16:     __c(arguments, 'al');
17: })(['a','b','c']);
18: 
19: process.nextTick(function objectCheck() {
20:     __c({}, 'o');
21:     __c(null, 'o');
22:     __c(null, 'nu');
23: });

consoleOutput

back to top

Default Options

{
    useStdioWriteSync : false,
    
    redirectStderrToStdout : process.platform === 'win32',
    
    // use 'ignore' or 'pipe' for childProcess.stdin
    untouchableStdin : !tty.isatty(0)
        && process.platform === 'win32'
        && semver.lt(semver.coerce(process.version), semver.coerce('4.0.0'))
    ,
    
    // logger [
    //     {      type : 'file' | <default> 'pipe'
    //          , data : 'out'  | 'err' | <default> 'all'
    //          , dest : {string} filePath | {number} fileDescriptor | {stream.Writable} writableStream
    //     },,,
    // ]
    logger : [],
    
    nodeAsyncCallLog : {
        async : {             run: false, init: false },             // == async : false
        ntick : { add: false, run: false },                          // == ntick : false
        timer : { add: false, run: false },                          // == timer : false
        event : { add: false, run: false, init: false, emit: false } // == event : false
    }, // == nodeAsyncCallLog : false
    
    userAsyncCallLog : {
        async : {            run: true, init: true },            // == async : true
        ntick : { add: true, run: true },                        // == ntick : true
        timer : { add: true, run: true },                        // == timer : true
        event : { add: true, run: true, init: true, emit: true } // == event : true
    }, // == userAsyncCallLog : true
    
    nodeStackViewLvl : 'off', // 'off' | 'app' | 'mod' | 'sys' | 'all'
    userStackViewLvl : { asyncCall: 'app', debugCall: 'app' },
    
    webstormConsoleSrcPath : '', // project app root directory ( use '.' for relative path )
    webstormConsoleLibPath : '', // node source's root lib directory
    
    defaultConsoleColumns : process.stdout.columns,
    defaultInspectOptions : {
        showHidden      : false,
        depth           : 0,
        colors          : true,
        customInspect   : true,
        showProxy       : false,
        maxArrayLength  : 32,
        breakLength     : 60
    },
    useConsoleAnsiColor : true,
    
    showConfigurationLog : false, // tud's startup console output which is printed before process init log
    
    showProcessInitExitLog : {
        init : true,
        exit : true
    },
    showProcessEventLog : true, // showProcessEventLog ? process.showTudEventLog() : process.hideTudEventLog()
    
    showSpawnLog : true,
    
    useGlobalTwoUnderscoreAPIs : true,
    
    showSucceededCheckLog : false,
    bypassFailedCheck : true,
    
    handleProcessUncaughtException : true // if true, tud adds the process uncaughtException event handler
}

back to top

License

MIT