├── .gitignore ├── History.md ├── README.md ├── debug-trace-browser.js ├── debug-trace.js ├── package.json └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | 2.0.0 / 2016-10-04 2 | ================== 3 | 4 | * Added support for browser (V8 only) 5 | * Added `getDate()` method 6 | * Removed `date` property 7 | * Removed `moment` dependency 8 | * Fixed `false` options values 9 | * Fixed debug stack with checking `log` function 10 | 11 | 1.0.0 / 2016-10-03 12 | ================== 13 | 14 | * Fixed stack for debug 15 | 16 | 17 | 0.3.0 / 2013-07-23 18 | ================== 19 | 20 | * Fixed callsite version >= 1.0.0 21 | * Added console.format 22 | * Added stack for https://github.com/visionmedia/debug 23 | 24 | 0.2.1 / 2012-07-06 25 | ================== 26 | 27 | * Added Buffer support [kilianc] 28 | * Fixed missing default color for trace method [kilianc] 29 | * Fixed missing padding [kilianc] 30 | 31 | 0.2.0 / 2012-07-06 32 | ================== 33 | 34 | * Added custom colors 35 | * Fixed output redirection bug 36 | * Misc fixes and improvements [kilianc] 37 | * Added right alignment for callsite info [kilianc] 38 | * Added `console.traced`, removed `console.trace` 39 | 40 | 0.1.0 / 2012-03-26 41 | ================== 42 | 43 | * Initial release 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # debug-trace 2 | 3 | This fork of console-trace adds the following features: 4 | * work with callsite >= version 1.0.0 5 | * work with https://github.com/visionmedia/debug 6 | (and print the caller of debug instead of console) 7 | * provide an easy to override formatting function `console.format` e.g.: 8 | 9 | ```javascript 10 | // overridable console string prefix formatting function 11 | console.format = function (c) { 12 | return c.getDate() + ": [" + c.filename + ":" + c.getLineNumber() + "] " + c.functionName; 13 | }; 14 | ``` 15 | 16 | ## Available methods from [V8 JavaScript stack trace API](https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi) 17 | * getThis: returns the value of this 18 | * getTypeName: returns the type of this as a string. This is the name of the function stored in the constructor field of this, if available, otherwise the object's [[Class]] internal property. 19 | * getFunction: returns the current function 20 | * getFunctionName: returns the name of the current function, typically its name property. If a name property is not available an attempt will be made to try to infer a name from the function's context. 21 | * getMethodName: returns the name of the property of this or one of its prototypes that holds the current function 22 | * getFileName: if this function was defined in a script returns the name of the script 23 | * getLineNumber: if this function was defined in a script returns the current line number 24 | * getColumnNumber: if this function was defined in a script returns the current column number 25 | * getEvalOrigin: if this function was created using a call to eval returns a CallSite object representing the location where eval was called 26 | * isToplevel: is this a toplevel invocation, that is, is this the global object? 27 | * isEval: does this call take place in code defined by a call to eval? 28 | * isNative: is this call in native V8 code? 29 | * isConstructor: is this a constructor call? 30 | 31 | ## Additional method 32 | * getDate(): actual date formatted like this: "2016-10-04 07:18:46.719" 33 | 34 | ## Additional properties 35 | * filename: getFileName without the base path: console.traceOptions.cwd 36 | * method: console method name like `log`, `error` ect. 37 | * functionName: call.getFunctionName() || 'anonymous' 38 | 39 | 40 | Extends the native Node.JS `console` object to prefix logging functions 41 | with the [CallSite](http://github.com/visionmedia/callsite) information. 42 | 43 | To read more about runtime stack trace introspection you can refer to [this 44 | article](http://www.devthought.com/2011/12/22/a-string-is-not-an-error/#beyond). 45 | 46 | ![](http://f.cl.ly/items/1T2K0H0i2H2J0C3q3H2u/console-trace.png) 47 | 48 | ## Installation 49 | 50 | $ npm install debug-trace 51 | 52 | ### Syntax: 53 | 54 | ```javascript 55 | require('debug-trace')([options]) 56 | ``` 57 | 58 | ### Available Options: 59 | 60 | * __always__ - (`Boolean`: defaults to false) always print the callsite info even without accessing methods from the `t` or `traced` getters. 61 | * __cwd__ - (`String`: defaults to `process.cwd()`) the path that will be stripped from the callsite info 62 | * __colors__ - (`Boolean|Object`: defaults to `undefined`) terminal colors support flag or a custom color object 63 | * __right__ - (`Boolean`: defaults to false) callsite alignment flag, when true prints infos on the right 64 | * __overwriteDebugLog__ - (`Function`: defaults to `console.log`) overwrites `debug` module log function, can be turned off with `overwriteDebugLog: false` 65 | * __patchOutput__ - (`Boolean`: defaults to true) monkey patches `process.stdout.write` and `process.stderr.write` with `console.log` and `console.error` in case it is called from debug (function with the name `log`) 66 | 67 | ### Examples: 68 | 69 | ```javascript 70 | require('debug-trace') 71 | ``` 72 | 73 | You can add the `t` or `traced` getter to your calls to obtain a stacktrace: 74 | 75 | ```javascript 76 | console.t.log('a'); 77 | console.traced.log('a'); 78 | ``` 79 | 80 | You can also make every console call trace: 81 | 82 | ```javascript 83 | require('debug-trace')({ 84 | always: true, 85 | }) 86 | 87 | ... 88 | 89 | console.log('a'); // tracing 90 | console.error('a'); // tracing 91 | ``` 92 | 93 | You can align the callsite infos to the right 94 | 95 | ```javascript 96 | require('debug-trace')({ 97 | always: true, 98 | right: true 99 | }) 100 | 101 | ... 102 | 103 | console.log('a'); // tracing right 104 | console.error('a'); // tracing right 105 | ``` 106 | 107 | You can change defaults colors too 108 | 109 | ```javascript 110 | require('./debug-trace')({ 111 | always: true, 112 | colors: { 113 | warn: '35', 114 | info: '32' 115 | } 116 | }) 117 | 118 | ... 119 | 120 | console.warn('a'); // magenta 121 | console.info('a'); // green 122 | ``` 123 | 124 | To customize the string that's prefixed to the calls, override the 125 | `console.traceFormat` function. 126 | 127 | ## Beyond console 128 | If you have more sophisticated logging needs, or don't wish to extend 129 | `console`, I suggest you look at [tracer](https://github.com/baryon/tracer). 130 | 131 | ## Credits 132 | I only added some functionality to the original console-trace: 133 | 134 | * [Guillermo Rauch](https://github.com/guille) 135 | * [Kilian Ciuffolo](https://github.com/kilianc) 136 | * [Nicholas Manousos](https://github.com/nmanousos) 137 | 138 | ## License 139 | MIT License 140 | -------------------------------------------------------------------------------- /debug-trace-browser.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Store custom options 3 | * 4 | * @param {Object} options 5 | * @api public 6 | */ 7 | 8 | module.exports = function debugTrace(options) { 9 | options = options || {}; 10 | console.traceOptions = console.traceOptions || {}; 11 | console.traceOptions.always = typeof options.always !== 'undefined' ? options.always : true; 12 | } 13 | 14 | // only works with Chrome (V8) 15 | if (typeof Error.captureStackTrace === 'function') { 16 | 17 | var callsite = require('callsite'); 18 | 19 | /** 20 | * Overrides the console methods. 21 | */ 22 | 23 | ;['error', 'log', 'info', 'warn', 'trace'].forEach(function (name) { 24 | var fn = console[name]; 25 | console[name] = function () { 26 | var args = arguments; 27 | if (console._trace || console.traceOptions.always) { 28 | if (args.length === 1) args = ['', args[0]]; 29 | if (typeof args[0] === 'object') { 30 | args[0] = JSON.stringify(args[0], null, ' '); 31 | } 32 | // when using the debug module: dig one level deeper in the stack 33 | var stack = callsite(); 34 | var trace = stack[1]; 35 | if (stack.length > 2 && trace.getFunctionName() === 'log') { 36 | trace = stack[3]; 37 | trace.debug = true; 38 | } 39 | trace.debug = trace.debug || false; 40 | args[0] = console.traceFormat(trace, name) + args[0]; 41 | } 42 | console._trace = false; 43 | return fn.apply(this, args); 44 | } 45 | }); 46 | 47 | /** 48 | * Overridable formatting function. 49 | * 50 | * @param {CallSite} 51 | * @param {String} calling method 52 | * @api public 53 | */ 54 | 55 | console.traceFormat = function (call, method) { 56 | var options = {}; 57 | call.method = method; 58 | call.functionName = call.getFunctionName() || 'anonymous'; 59 | call.getDate = function getDate() { 60 | return new Date().toISOString().replace('T', ' ').replace('Z', ''); 61 | } 62 | return console.format(call); 63 | } 64 | 65 | 66 | /** 67 | * Overridable string formatting function. 68 | * 69 | * @param {CallSite} CallSite Object pimped with additional properties. 70 | * @api public 71 | */ 72 | console.format = function (c) { 73 | return "[" + c.getFileName() + ":" + c.getLineNumber() + "] " + c.functionName + " "; 74 | }; 75 | 76 | /** 77 | * Adds trace getter to the `console` object. 78 | * 79 | * @api public 80 | */ 81 | 82 | function getter() { 83 | this._trace = true; 84 | return this; 85 | } 86 | 87 | Object.defineProperty(console, 't', { get: getter }); 88 | Object.defineProperty(console, 'traced', { get: getter }); 89 | 90 | } 91 | -------------------------------------------------------------------------------- /debug-trace.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Module dependencies. 4 | */ 5 | 6 | var callsite = require('callsite') 7 | , tty = require('tty') 8 | , isatty = Boolean(tty.isatty(2) && process.stdout.getWindowSize) 9 | , defaultColors = { log: '90', error: '91', warn: '93', info: '96', trace: '90' } 10 | 11 | /** 12 | * Store custom options 13 | * 14 | * @param {Object} options 15 | * @api public 16 | */ 17 | 18 | module.exports = function debugTrace(options) { 19 | options = options || {}; 20 | console.traceOptions = console.traceOptions || {}; 21 | console.traceOptions.cwd = options.cwd || process.cwd() + '/'; 22 | console.traceOptions.colors = typeof options.colors !== 'undefined' ? options.colors : true; 23 | console.traceOptions.always = typeof options.always !== 'undefined' ? options.always : true; 24 | console.traceOptions.right = typeof options.right !== 'undefined' ? options.right : false; 25 | if (typeof options.overwriteDebugLog === 'undefined' || options.overwriteDebugLog) overwriteDebugLog(options.overwriteDebugLog) 26 | if (typeof options.patchOutput === 'undefined' || options.patchOutput) patchOutput() 27 | } 28 | 29 | function overwriteDebugLog(debugLog) { 30 | debugLog = typeof debugLog === 'function' ? debugLog : console.log; 31 | try { 32 | var Debug = require('debug'); 33 | Debug.log = function log() { 34 | return debugLog.apply(debugLog, arguments); 35 | }; 36 | } catch (error) { 37 | console.log('debug module is not installed'); 38 | } 39 | } 40 | 41 | function patchOutput() { 42 | var stdout = process.stdout.write; 43 | var stderr = process.stderr.write; 44 | process.stdout.write = function write() { 45 | var stack = callsite(); 46 | var trace = stack[1]; 47 | if (trace.getFunctionName() === 'log') { 48 | var args = [].slice.call(arguments); 49 | if (typeof args[args.length - 1] === 'string') args[args.length - 1] = args[args.length - 1].replace(/\n$/g, ''); 50 | return console.log.apply(console.log, args); 51 | } 52 | return stdout.apply(process.stdout, arguments) 53 | } 54 | process.stderr.write = function write() { 55 | var stack = callsite(); 56 | var trace = stack[1]; 57 | if (trace.getFunctionName() === 'log') { 58 | var args = [].slice.call(arguments); 59 | if (typeof args[args.length - 1] === 'string') args[args.length - 1] = args[args.length - 1].replace(/\n$/g, ''); 60 | return console.log.apply(console.log, args); 61 | } 62 | return stderr.apply(process.stderr, arguments) 63 | } 64 | } 65 | 66 | /** 67 | * Overrides the console methods. 68 | */ 69 | 70 | ;['error', 'log', 'info', 'warn', 'trace'].forEach(function (name) { 71 | var fn = console[name]; 72 | console[name] = function () { 73 | var args = arguments; 74 | if (console._trace || console.traceOptions.always) { 75 | if (args.length === 1) args = ['', args[0]]; 76 | if (Buffer.isBuffer(args[0])) { 77 | args[0] = args[0].inspect() 78 | } else if (typeof args[0] === 'object') { 79 | args[0] = JSON.stringify(args[0], null, ' '); 80 | } 81 | var pad = (args[0] && !console.traceOptions.right || !isatty ? ' ' : ''); 82 | // when using the debug module: dig one level deeper in the stack 83 | var stack = callsite(); 84 | var trace = stack[1]; 85 | if (stack.length > 2 && trace.getFunctionName() === 'log') { 86 | trace = stack[3]; 87 | trace.debug = true; 88 | } 89 | if (stack.length > 3 && trace.getFunctionName() === 'write') { 90 | trace = stack[4]; 91 | trace.debug = true; 92 | } 93 | trace.debug = trace.debug || false; 94 | args[0] = console.traceFormat(trace, name) + pad + args[0]; 95 | } 96 | console._trace = false; 97 | return fn.apply(this, args); 98 | } 99 | }); 100 | 101 | /** 102 | * Overridable formatting function. 103 | * 104 | * @param {CallSite} 105 | * @param {String} calling method 106 | * @api public 107 | */ 108 | 109 | console.traceFormat = function (call, method) { 110 | call.filename = call.getFileName().replace(console.traceOptions.cwd, ''); 111 | call.method = method; 112 | call.functionName = call.getFunctionName() || 'anonymous' 113 | call.getDate = function getDate() { 114 | return new Date().toISOString().replace('T', ' ').replace('Z', ''); 115 | } 116 | 117 | var str = console.format(call); 118 | var color = '99'; 119 | 120 | if (!isatty) { 121 | return str; 122 | } 123 | 124 | if (console.traceOptions.colors !== false) { 125 | if (console.traceOptions.colors === undefined || console.traceOptions.colors[method] === undefined) { 126 | color = defaultColors[method]; 127 | } else { 128 | color = console.traceOptions.colors[method]; 129 | } 130 | } 131 | 132 | if (console.traceOptions.right) { 133 | var rowWidth = process.stdout.getWindowSize()[0]; 134 | return '\033[s' + // save current position 135 | '\033[' + rowWidth + 'D' + // move to the start of the line 136 | '\033[' + (rowWidth - str.length) + 'C' + // align right 137 | '\033[' + color + 'm' + str + '\033[39m' + 138 | '\033[u'; // restore current position 139 | } else { 140 | return '\033[' + color + 'm' + str + '\033[39m'; 141 | } 142 | } 143 | 144 | 145 | /** 146 | * Overridable string formatting function. 147 | * 148 | * @param {CallSite} CallSite Object pimped with additional properties. 149 | * @api public 150 | */ 151 | console.format = function (c) { 152 | return c.getDate() + ": [" + c.filename + ":" + c.getLineNumber() + "] " + c.functionName; 153 | }; 154 | 155 | /** 156 | * Adds trace getter to the `console` object. 157 | * 158 | * @api public 159 | */ 160 | 161 | function getter() { 162 | this._trace = true; 163 | return this; 164 | } 165 | 166 | Object.defineProperty(console, 't', { get: getter }); 167 | Object.defineProperty(console, 'traced', { get: getter }); 168 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "debug-trace", 3 | "version": "2.2.3", 4 | "description": "Adds a handy `trace` flag to the console object to prepend the file and line number", 5 | "main": "./debug-trace", 6 | "browser": "./debug-trace-browser", 7 | "dependencies": { 8 | "callsite": "~1.0.0" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/intesso/debug-trace" 13 | }, 14 | "keywords": [ 15 | "debug", 16 | "trace", 17 | "callsite", 18 | "formatted console", 19 | "format console", 20 | "line number", 21 | "function name" 22 | ], 23 | "author": "Andi Neck", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/intesso/debug-trace/issues" 27 | }, 28 | "homepage": "https://github.com/intesso/debug-trace" 29 | } 30 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | require('./debug-trace') 2 | require('./debug-trace')({}) // should work even if I require it twice 3 | 4 | process.stdout.write('\n'); 5 | 6 | ;['error', 'log', 'info', 'warn'].forEach(function (name) { 7 | process.stdout.write(' '); 8 | console[name]('regular console.%s, no clue where it came from', name); 9 | }); 10 | 11 | process.stdout.write('\n---------------------------------------------------------\n\n'); 12 | 13 | ;['error', 'log', 'info', 'warn'].forEach(function (name) { 14 | process.stdout.write(' '); 15 | console.traced[name]('this is a traced console.%s', name); 16 | }); 17 | 18 | process.stdout.write('\n---------------------------------------------------------\n\n'); 19 | 20 | console.traceOptions.colors = false; 21 | 22 | ;['error', 'log', 'info', 'warn'].forEach(function (name) { 23 | process.stdout.write(' '); 24 | console.traced[name]('this is an uncolored traced console.%s', name); 25 | }); 26 | 27 | process.stdout.write('\n---------------------------------------------------------\n\n'); 28 | 29 | console.traceOptions.right = true; 30 | console.traceOptions.colors = true; 31 | 32 | ;['error', 'log', 'info', 'warn'].forEach(function (name) { 33 | process.stdout.write(' '); 34 | console.traced[name]('this is a colored right aligned traced console.%s', name); 35 | }); 36 | 37 | process.stdout.write('\n---------------------------------------------------------\n\n'); 38 | 39 | console.traceOptions.always = true; 40 | console.traceOptions.colors = false; 41 | 42 | ;['error', 'log', 'info', 'warn'].forEach(function (name) { 43 | process.stdout.write(' '); 44 | console[name]('this is an uncolored right aligned traced console.%s', name); 45 | }); 46 | 47 | process.stdout.write('\n---------------------------------------------------------\n\n'); 48 | 49 | require('./debug-trace')({ 50 | colors: { 51 | log: '35', 52 | warn: '35', 53 | error: '35', 54 | trace: '35', 55 | info: '35' 56 | } 57 | }) 58 | 59 | ;['error', 'log', 'info', 'warn', 'trace'].forEach(function (name) { 60 | process.stdout.write(' '); 61 | console.traced[name]('this is a magenta traced console.' + name); 62 | }); 63 | 64 | process.stdout.write('\n---------------------------------------------------------\n\n'); 65 | 66 | console.traceOptions.colors = true; 67 | 68 | process.stdout.write(' '); 69 | console.traced.log({ 1: 'works', 2: 'with', 3: 'Object' }); 70 | 71 | process.stdout.write(' '); 72 | console.traced.log(['Works', 'with', 'Array']); 73 | 74 | process.stdout.write(' '); 75 | console.traced.log('Works with Buffer', Buffer('FooBar')); --------------------------------------------------------------------------------