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