GeezerVison is showing github.com — process: add --redirect-warnings command line argument · nodejs/node@03e89b3
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: doc/api/cli.md +21Lines changed: 21 additions & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -121,6 +121,16 @@ added: v6.0.0 | 121 | 121 |
| 122 | 122 | Print stack traces for process warnings (including deprecations). | 123 | 123 |
| | 124 | +### `--redirect-warnings=file` | | 125 | +<!-- YAML | | 126 | +added: REPLACEME | | 127 | +--> | | 128 | + | | 129 | +Write process warnings to the given file instead of printing to stderr. The | | 130 | +file will be created if it does not exist, and will be appended to if it does. | | 131 | +If an error occurs while attempting to write the warning to the file, the | | 132 | +warning will be written to stderr instead. | | 133 | + | 124 | 134 | ### `--trace-sync-io` | 125 | 135 | <!-- YAML | 126 | 136 | added: v2.1.0 | @@ -395,6 +405,17 @@ Note: Be aware that unless the child environment is explicitly set, this | 395 | 405 | evironment variable will be inherited by any child processes, and if they use | 396 | 406 | OpenSSL, it may cause them to trust the same CAs as node. | 397 | 407 |
| | 408 | +### `NODE_REDIRECT_WARNINGS=file` | | 409 | +<!-- YAML | | 410 | +added: REPLACEME | | 411 | +--> | | 412 | + | | 413 | +When set, process warnings will be emitted to the given file instead of | | 414 | +printing to stderr. The file will be created if it does not exist, and will be | | 415 | +appended to if it does. If an error occurs while attempting to write the | | 416 | +warning to the file, the warning will be written to stderr instead. This is | | 417 | +equivalent to using the `--redirect-warnings=file` command-line flag. | | 418 | + | 398 | 419 | [emit_warning]: process.html#process_process_emitwarning_warning_name_ctor | 399 | 420 | [Buffer]: buffer.html#buffer_buffer | 400 | 421 | [debugger]: debugger.html | |
Collapse file Copy file name to clipboardExpand all lines: doc/node.1 +10Lines changed: 10 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -112,6 +112,10 @@ Silence all process warnings (including deprecations). | 112 | 112 | .BR \-\-trace\-warnings | 113 | 113 | Print stack traces for process warnings (including deprecations). | 114 | 114 |
| | 115 | +.TP | | 116 | +.BR \-\-redirect\-warnings=\fIfile\fR | | 117 | +Write process warnings to the given file instead of printing to stderr. | | 118 | + | 115 | 119 | .TP | 116 | 120 | .BR \-\-trace\-sync\-io | 117 | 121 | Print a stack trace whenever synchronous I/O is detected after the first turn | @@ -262,6 +266,12 @@ containing trusted certificates. | 262 | 266 | If \fB\-\-use\-openssl\-ca\fR is enabled, this overrides and sets OpenSSL's | 263 | 267 | file containing trusted certificates. | 264 | 268 |
| | 269 | +.TP | | 270 | +.BR NODE_REDIRECT_WARNINGS=\fIfile\fR | | 271 | +Write process warnings to the given file instead of printing to stderr. | | 272 | +(equivalent to using the \-\-redirect\-warnings=\fIfile\fR command-line | | 273 | +argument). | | 274 | + | 265 | 275 | .SH BUGS | 266 | 276 | Bugs are tracked in GitHub Issues: | 267 | 277 | .ur https://github.com/nodejs/node/issues | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/process/warning.js +76-6Lines changed: 76 additions & 6 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 1 | 1 | 'use strict'; | 2 | 2 |
| | 3 | +const config = process.binding('config'); | 3 | 4 | const prefix = `(${process.release.name}:${process.pid}) `; | 4 | 5 |
| 5 | 6 | exports.setup = setupProcessWarnings; | 6 | 7 |
| | 8 | +var fs; | | 9 | +var cachedFd; | | 10 | +var acquiringFd = false; | | 11 | +function nop() {} | | 12 | + | | 13 | +function lazyFs() { | | 14 | + if (!fs) | | 15 | + fs = require('fs'); | | 16 | + return fs; | | 17 | +} | | 18 | + | | 19 | +function writeOut(message) { | | 20 | + if (console && typeof console.error === 'function') | | 21 | + return console.error(message); | | 22 | + process._rawDebug(message); | | 23 | +} | | 24 | + | | 25 | +function onClose(fd) { | | 26 | + return function() { | | 27 | + lazyFs().close(fd, nop); | | 28 | + }; | | 29 | +} | | 30 | + | | 31 | +function onOpen(cb) { | | 32 | + return function(err, fd) { | | 33 | + acquiringFd = false; | | 34 | + if (fd !== undefined) { | | 35 | + cachedFd = fd; | | 36 | + process.on('exit', onClose(fd)); | | 37 | + } | | 38 | + cb(err, fd); | | 39 | + process.emit('_node_warning_fd_acquired', err, fd); | | 40 | + }; | | 41 | +} | | 42 | + | | 43 | +function onAcquired(message) { | | 44 | + // make a best effort attempt at writing the message | | 45 | + // to the fd. Errors are ignored at this point. | | 46 | + return function(err, fd) { | | 47 | + if (err) | | 48 | + return writeOut(message); | | 49 | + lazyFs().appendFile(fd, `${message}\n`, nop); | | 50 | + }; | | 51 | +} | | 52 | + | | 53 | +function acquireFd(cb) { | | 54 | + if (cachedFd === undefined && !acquiringFd) { | | 55 | + acquiringFd = true; | | 56 | + lazyFs().open(config.warningFile, 'a', onOpen(cb)); | | 57 | + } else if (cachedFd !== undefined && !acquiringFd) { | | 58 | + cb(null, cachedFd); | | 59 | + } else { | | 60 | + process.once('_node_warning_fd_acquired', cb); | | 61 | + } | | 62 | +} | | 63 | + | | 64 | +function output(message) { | | 65 | + if (typeof config.warningFile === 'string') { | | 66 | + acquireFd(onAcquired(message)); | | 67 | + return; | | 68 | + } | | 69 | + writeOut(message); | | 70 | +} | | 71 | + | | 72 | +function doEmitWarning(warning) { | | 73 | + return function() { | | 74 | + process.emit('warning', warning); | | 75 | + }; | | 76 | +} | | 77 | + | 7 | 78 | function setupProcessWarnings() { | 8 | 79 | if (!process.noProcessWarnings && process.env.NODE_NO_WARNINGS !== '1') { | 9 | 80 | process.on('warning', (warning) => { | @@ -14,19 +85,18 @@ function setupProcessWarnings() { | 14 | 85 | (isDeprecation && process.traceDeprecation); | 15 | 86 | if (trace && warning.stack) { | 16 | 87 | if (warning.code) { | 17 | | - console.error(`${prefix}[${warning.code}] ${warning.stack}`); | | 88 | + output(`${prefix}[${warning.code}] ${warning.stack}`); | 18 | 89 | } else { | 19 | | - console.error(`${prefix}${warning.stack}`); | | 90 | + output(`${prefix}${warning.stack}`); | 20 | 91 | } | 21 | 92 | } else { | 22 | 93 | const toString = | 23 | 94 | typeof warning.toString === 'function' ? | 24 | 95 | warning.toString : Error.prototype.toString; | 25 | 96 | if (warning.code) { | 26 | | - console.error( | 27 | | - `${prefix}[${warning.code}] ${toString.apply(warning)}`); | | 97 | + output(`${prefix}[${warning.code}] ${toString.apply(warning)}`); | 28 | 98 | } else { | 29 | | - console.error(`${prefix}${toString.apply(warning)}`); | | 99 | + output(`${prefix}${toString.apply(warning)}`); | 30 | 100 | } | 31 | 101 | } | 32 | 102 | }); | @@ -63,6 +133,6 @@ function setupProcessWarnings() { | 63 | 133 | if (process.throwDeprecation) | 64 | 134 | throw warning; | 65 | 135 | } | 66 | | - process.nextTick(() => process.emit('warning', warning)); | | 136 | + process.nextTick(doEmitWarning(warning)); | 67 | 137 | }; | 68 | 138 | } |
Collapse file Copy file name to clipboardExpand all lines: src/node.cc +14Lines changed: 14 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -188,6 +188,9 @@ bool trace_warnings = false; | 188 | 188 | // that is used by lib/module.js | 189 | 189 | bool config_preserve_symlinks = false; | 190 | 190 |
| | 191 | +// Set in node.cc by ParseArgs when --redirect-warnings= is used. | | 192 | +const char* config_warning_file; | | 193 | + | 191 | 194 | bool v8_initialized = false; | 192 | 195 |
| 193 | 196 | // process-relative uptime base, initialized at start-up | @@ -3499,6 +3502,9 @@ static void PrintHelp() { | 3499 | 3502 | " --throw-deprecation throw an exception on deprecations\n" | 3500 | 3503 | " --no-warnings silence all process warnings\n" | 3501 | 3504 | " --trace-warnings show stack traces on process warnings\n" | | 3505 | + " --redirect-warnings=path\n" | | 3506 | + " write warnings to path instead of\n" | | 3507 | + " stderr\n" | 3502 | 3508 | " --trace-sync-io show stack trace when use of sync IO\n" | 3503 | 3509 | " is detected after the first tick\n" | 3504 | 3510 | " --trace-events-enabled track trace events\n" | @@ -3564,6 +3570,8 @@ static void PrintHelp() { | 3564 | 3570 | " prefixed to the module search path\n" | 3565 | 3571 | "NODE_REPL_HISTORY path to the persistent REPL history\n" | 3566 | 3572 | " file\n" | | 3573 | + "NODE_REDIRECT_WARNINGS write warnings to path instead of\n" | | 3574 | + " stderr\n" | 3567 | 3575 | "Documentation can be found at https://nodejs.org/\n"); | 3568 | 3576 | } | 3569 | 3577 |
| @@ -3664,6 +3672,8 @@ static void ParseArgs(int* argc, | 3664 | 3672 | no_process_warnings = true; | 3665 | 3673 | } else if (strcmp(arg, "--trace-warnings") == 0) { | 3666 | 3674 | trace_warnings = true; | | 3675 | + } else if (strncmp(arg, "--redirect-warnings=", 20) == 0) { | | 3676 | + config_warning_file = arg + 20; | 3667 | 3677 | } else if (strcmp(arg, "--trace-deprecation") == 0) { | 3668 | 3678 | trace_deprecation = true; | 3669 | 3679 | } else if (strcmp(arg, "--trace-sync-io") == 0) { | @@ -4206,6 +4216,10 @@ void Init(int* argc, | 4206 | 4216 | config_preserve_symlinks = (*preserve_symlinks == '1'); | 4207 | 4217 | } | 4208 | 4218 |
| | 4219 | + if (auto redirect_warnings = secure_getenv("NODE_REDIRECT_WARNINGS")) { | | 4220 | + config_warning_file = redirect_warnings; | | 4221 | + } | | 4222 | + | 4209 | 4223 | // Parse a few arguments which are specific to Node. | 4210 | 4224 | int v8_argc; | 4211 | 4225 | const char** v8_argv; | |
Collapse file Copy file name to clipboardExpand all lines: src/node_config.cc +10Lines changed: 10 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -12,6 +12,7 @@ using v8::Context; | 12 | 12 | using v8::Local; | 13 | 13 | using v8::Object; | 14 | 14 | using v8::ReadOnly; | | 15 | +using v8::String; | 15 | 16 | using v8::Value; | 16 | 17 |
| 17 | 18 | // The config binding is used to provide an internal view of compile or runtime | @@ -44,6 +45,15 @@ void InitConfig(Local<Object> target, | 44 | 45 |
| 45 | 46 | if (config_preserve_symlinks) | 46 | 47 | READONLY_BOOLEAN_PROPERTY("preserveSymlinks"); | | 48 | + | | 49 | + if (config_warning_file != nullptr) { | | 50 | + Local<String> name = OneByteString(env->isolate(), "warningFile"); | | 51 | + Local<String> value = String::NewFromUtf8(env->isolate(), | | 52 | + config_warning_file, | | 53 | + v8::NewStringType::kNormal) | | 54 | + .ToLocalChecked(); | | 55 | + target->DefineOwnProperty(env->context(), name, value).FromJust(); | | 56 | + } | 47 | 57 | } // InitConfig | 48 | 58 |
| 49 | 59 | } // namespace node | |
Collapse file Copy file name to clipboardExpand all lines: src/node_internals.h +5Lines changed: 5 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -42,6 +42,11 @@ extern const char* openssl_config; | 42 | 42 | // that is used by lib/module.js | 43 | 43 | extern bool config_preserve_symlinks; | 44 | 44 |
| | 45 | +// Set in node.cc by ParseArgs when --redirect-warnings= is used. | | 46 | +// Used to redirect warning output to a file rather than sending | | 47 | +// it to stderr. | | 48 | +extern const char* config_warning_file; | | 49 | + | 45 | 50 | // Tells whether it is safe to call v8::Isolate::GetCurrent(). | 46 | 51 | extern bool v8_initialized; | 47 | 52 |
| |
Collapse file Copy file name to clipboard +25Lines changed: 25 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +// Tests the NODE_REDIRECT_WARNINGS environment variable by spawning | | 4 | +// a new child node process that emits a warning into a temporary | | 5 | +// warnings file. Once the process completes, the warning file is | | 6 | +// opened and the contents are validated | | 7 | + | | 8 | +const common = require('../common'); | | 9 | +const fs = require('fs'); | | 10 | +const fork = require('child_process').fork; | | 11 | +const path = require('path'); | | 12 | +const assert = require('assert'); | | 13 | + | | 14 | +common.refreshTmpDir(); | | 15 | + | | 16 | +const warnmod = require.resolve(common.fixturesDir + '/warnings.js'); | | 17 | +const warnpath = path.join(common.tmpDir, 'warnings.txt'); | | 18 | + | | 19 | +fork(warnmod, {env: {NODE_REDIRECT_WARNINGS: warnpath}}) | | 20 | + .on('exit', common.mustCall(() => { | | 21 | + fs.readFile(warnpath, 'utf8', common.mustCall((err, data) => { | | 22 | + assert.ifError(err); | | 23 | + assert(/\(node:\d+\) Warning: a bad practice warning/.test(data)); | | 24 | + })); | | 25 | + })); |
Collapse file Copy file name to clipboard +25Lines changed: 25 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +// Tests the --redirect-warnings command line flag by spawning | | 4 | +// a new child node process that emits a warning into a temporary | | 5 | +// warnings file. Once the process completes, the warning file is | | 6 | +// opened and the contents are validated | | 7 | + | | 8 | +const common = require('../common'); | | 9 | +const fs = require('fs'); | | 10 | +const fork = require('child_process').fork; | | 11 | +const path = require('path'); | | 12 | +const assert = require('assert'); | | 13 | + | | 14 | +common.refreshTmpDir(); | | 15 | + | | 16 | +const warnmod = require.resolve(common.fixturesDir + '/warnings.js'); | | 17 | +const warnpath = path.join(common.tmpDir, 'warnings.txt'); | | 18 | + | | 19 | +fork(warnmod, {execArgv: [`--redirect-warnings=${warnpath}`]}) | | 20 | + .on('exit', common.mustCall(() => { | | 21 | + fs.readFile(warnpath, 'utf8', common.mustCall((err, data) => { | | 22 | + assert.ifError(err); | | 23 | + assert(/\(node:\d+\) Warning: a bad practice warning/.test(data)); | | 24 | + })); | | 25 | + })); |
|