All files / lib/internal/util debuglog.js

100% Statements 117/117
93.75% Branches 30/32
92.85% Functions 13/14
100% Lines 117/117

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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