1'use strict'; 2 3const { 4 FunctionPrototypeBind, 5 ObjectCreate, 6 ObjectDefineProperty, 7 RegExp, 8 RegExpPrototypeTest, 9 SafeArrayIterator, 10 StringPrototypeToUpperCase 11} = primordials; 12 13const { inspect, format, formatWithOptions } = require('internal/util/inspect'); 14 15// `debugs` is deliberately initialized to undefined so any call to 16// debuglog() before initializeDebugEnv() is called will throw. 17let debugImpls; 18 19let debugEnvRegex = /^$/; 20let testEnabled; 21 22// `debugEnv` is initial value of process.env.NODE_DEBUG 23function initializeDebugEnv(debugEnv) { 24 debugImpls = ObjectCreate(null); 25 if (debugEnv) { 26 debugEnv = debugEnv.replace(/[|\\{}()[\]^$+?.]/g, '\\$&') 27 .replace(/\*/g, '.*') 28 .replace(/,/g, '$|^') 29 .toUpperCase(); 30 debugEnvRegex = new RegExp(`^${debugEnv}$`, 'i'); 31 } 32 testEnabled = FunctionPrototypeBind(RegExpPrototypeTest, null, debugEnvRegex); 33} 34 35// Emits warning when user sets 36// NODE_DEBUG=http or NODE_DEBUG=http2. 37function emitWarningIfNeeded(set) { 38 if ('HTTP' === set || 'HTTP2' === set) { 39 process.emitWarning('Setting the NODE_DEBUG environment variable ' + 40 'to \'' + set.toLowerCase() + '\' can expose sensitive ' + 41 'data (such as passwords, tokens and authentication headers) ' + 42 'in the resulting log.'); 43 } 44} 45 46function noop() {} 47 48function debuglogImpl(enabled, set) { 49 if (debugImpls[set] === undefined) { 50 if (enabled) { 51 const pid = process.pid; 52 emitWarningIfNeeded(set); 53 debugImpls[set] = function debug(...args) { 54 const colors = process.stderr.hasColors && process.stderr.hasColors(); 55 const msg = formatWithOptions({ colors }, ...args); 56 const coloredPID = inspect(pid, { colors }); 57 process.stderr.write(format('%s %s: %s\n', set, coloredPID, msg)); 58 }; 59 } else { 60 debugImpls[set] = noop; 61 } 62 } 63 return debugImpls[set]; 64} 65 66// debuglogImpl depends on process.pid and process.env.NODE_DEBUG, 67// so it needs to be called lazily in top scopes of internal modules 68// that may be loaded before these run time states are allowed to 69// be accessed. 70function debuglog(set, cb) { 71 function init() { 72 set = StringPrototypeToUpperCase(set); 73 enabled = testEnabled(set); 74 } 75 let debug = (...args) => { 76 init(); 77 // Only invokes debuglogImpl() when the debug function is 78 // called for the first time. 79 debug = debuglogImpl(enabled, set); 80 if (typeof cb === 'function') 81 cb(debug); 82 debug(...new SafeArrayIterator(args)); 83 }; 84 let enabled; 85 let test = () => { 86 init(); 87 test = () => enabled; 88 return enabled; 89 }; 90 const logger = (...args) => debug(...new SafeArrayIterator(args)); 91 ObjectDefineProperty(logger, 'enabled', { 92 get() { 93 return test(); 94 }, 95 configurable: true, 96 enumerable: true 97 }); 98 return logger; 99} 100 101module.exports = { 102 debuglog, 103 initializeDebugEnv 104}; 105