-
Notifications
You must be signed in to change notification settings - Fork 29.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make node-report part of core runtime because: 1. When enabled, node-report significantly helps root cause various types of problems, including support issues sent to the various repos of the Node.js organization. 2. The requirement of explicitly adding the dependency to node-report in user applications often represents a blocker to adoption. Major deviation from the module version of the node-report is that the report is generated in JSON format, as opposed to human readable text. No new functionalities have been added, changes that are required for melding it as a built-in capability has been affected on the module version of node-report (https://github.com/nodejs/node-report) Co-authored-by: Bidisha Pyne <bidipyne@in.ibm.com> Co-authored-by: Howard Hellyer <hhellyer@uk.ibm.com> Co-authored-by: Jeremiah Senkpiel <fishrock123@rocketmail.com> Co-authored-by: Julian Alimin <dmastag@yahoo.com> Co-authored-by: Lakshmi Swetha Gopireddy <lakshmigopireddy@in.ibm.com> Co-authored-by: Manusaporn Treerungroj <m.treerungroj@gmail.com> Co-authored-by: Michael Dawson <michael_dawson@ca.ibm.com> Co-authored-by: Richard Chamberlain <richard_chamberlain@uk.ibm.com> Co-authored-by: Richard Lau <riclau@uk.ibm.com> Co-authored-by: Sam Roberts <vieuxtech@gmail.com> Co-authored-by: Vipin Menon <vipinmv1@in.ibm.com> PR-URL: #22712 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Michael Dawson <Michael_Dawson@ca.ibm.com> Reviewed-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com>
- Loading branch information
1 parent
219b1b8
commit 549216a
Showing
16 changed files
with
1,995 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
'use strict'; | ||
|
||
const { emitExperimentalWarning } = require('internal/util'); | ||
const { | ||
ERR_INVALID_ARG_TYPE, | ||
ERR_SYNTHETIC } = require('internal/errors').codes; | ||
|
||
exports.setup = function() { | ||
const REPORTEVENTS = 1; | ||
const REPORTSIGNAL = 2; | ||
const REPORTFILENAME = 3; | ||
const REPORTPATH = 4; | ||
const REPORTVERBOSE = 5; | ||
if (internalBinding('config').hasReport) { | ||
// If report is enabled, extract the binding and | ||
// wrap the APIs with thin layers, with some error checks. | ||
// user options can come in from CLI / ENV / API. | ||
// CLI and ENV is intercepted in C++ and the API call here (JS). | ||
// So sync up with both sides as appropriate - initially from | ||
// C++ to JS and from JS to C++ whenever the API is called. | ||
// Some events are controlled purely from JS (signal | exception) | ||
// and some from C++ (fatalerror) so this sync-up is essential for | ||
// correct behavior and alignment with the supplied tunables. | ||
const nr = internalBinding('report'); | ||
|
||
// Keep it un-exposed; lest programs play with it | ||
// leaving us with a lot of unwanted sanity checks. | ||
let config = { | ||
events: [], | ||
signal: 'SIGUSR2', | ||
filename: '', | ||
path: '', | ||
verbose: false | ||
}; | ||
const report = { | ||
setDiagnosticReportOptions(options) { | ||
emitExperimentalWarning('report'); | ||
// Reuse the null and undefined checks. Save | ||
// space when dealing with large number of arguments. | ||
const list = parseOptions(options); | ||
|
||
// Flush the stale entries from report, as | ||
// we are refreshing it, items that the users did not | ||
// touch may be hanging around stale otherwise. | ||
config = {}; | ||
|
||
// The parseOption method returns an array that include | ||
// the indices at which valid params are present. | ||
list.forEach((i) => { | ||
switch (i) { | ||
case REPORTEVENTS: | ||
if (Array.isArray(options.events)) | ||
config.events = options.events; | ||
else | ||
throw new ERR_INVALID_ARG_TYPE('events', | ||
'Array', | ||
options.events); | ||
break; | ||
case REPORTSIGNAL: | ||
if (typeof options.signal !== 'string') { | ||
throw new ERR_INVALID_ARG_TYPE('signal', | ||
'String', | ||
options.signal); | ||
} | ||
process.removeListener(config.signal, handleSignal); | ||
if (config.events.includes('signal')) | ||
process.on(options.signal, handleSignal); | ||
config.signal = options.signal; | ||
break; | ||
case REPORTFILENAME: | ||
if (typeof options.filename !== 'string') { | ||
throw new ERR_INVALID_ARG_TYPE('filename', | ||
'String', | ||
options.filename); | ||
} | ||
config.filename = options.filename; | ||
break; | ||
case REPORTPATH: | ||
if (typeof options.path !== 'string') | ||
throw new ERR_INVALID_ARG_TYPE('path', 'String', options.path); | ||
config.path = options.path; | ||
break; | ||
case REPORTVERBOSE: | ||
if (typeof options.verbose !== 'string' && | ||
typeof options.verbose !== 'boolean') { | ||
throw new ERR_INVALID_ARG_TYPE('verbose', | ||
'Booelan | String' + | ||
' (true|false|yes|no)', | ||
options.verbose); | ||
} | ||
config.verbose = options.verbose; | ||
break; | ||
} | ||
}); | ||
// Upload this new config to C++ land | ||
nr.syncConfig(config, true); | ||
}, | ||
|
||
|
||
triggerReport(file, err) { | ||
emitExperimentalWarning('report'); | ||
if (err == null) { | ||
if (file == null) { | ||
return nr.triggerReport(new ERR_SYNTHETIC( | ||
'JavaScript Callstack').stack); | ||
} | ||
if (typeof file !== 'string') | ||
throw new ERR_INVALID_ARG_TYPE('file', 'String', file); | ||
return nr.triggerReport(file, new ERR_SYNTHETIC( | ||
'JavaScript Callstack').stack); | ||
} | ||
if (typeof err !== 'object') | ||
throw new ERR_INVALID_ARG_TYPE('err', 'Object', err); | ||
if (file == null) | ||
return nr.triggerReport(err.stack); | ||
if (typeof file !== 'string') | ||
throw new ERR_INVALID_ARG_TYPE('file', 'String', file); | ||
return nr.triggerReport(file, err.stack); | ||
}, | ||
getReport(err) { | ||
emitExperimentalWarning('report'); | ||
if (err == null) { | ||
return nr.getReport(new ERR_SYNTHETIC('JavaScript Callstack').stack); | ||
} else if (typeof err !== 'object') { | ||
throw new ERR_INVALID_ARG_TYPE('err', 'Objct', err); | ||
} else { | ||
return nr.getReport(err.stack); | ||
} | ||
} | ||
}; | ||
|
||
// Download the CLI / ENV config into JS land. | ||
nr.syncConfig(config, false); | ||
|
||
function handleSignal(signo) { | ||
if (typeof signo !== 'string') | ||
signo = config.signal; | ||
nr.onUserSignal(signo); | ||
} | ||
|
||
if (config.events.includes('signal')) { | ||
process.on(config.signal, handleSignal); | ||
} | ||
|
||
function parseOptions(obj) { | ||
const list = []; | ||
if (obj == null) | ||
return list; | ||
if (obj.events != null) | ||
list.push(REPORTEVENTS); | ||
if (obj.signal != null) | ||
list.push(REPORTSIGNAL); | ||
if (obj.filename != null) | ||
list.push(REPORTFILENAME); | ||
if (obj.path != null) | ||
list.push(REPORTPATH); | ||
if (obj.verbose != null) | ||
list.push(REPORTVERBOSE); | ||
return list; | ||
} | ||
process.report = report; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.