report: modify getReport() to return an Object
It's likely that anyone using `process.report.getReport()` will be processing the return value thereafter (e.g., filtering fields or redacting secrets). This change eliminates boilerplate by calling `JSON.parse()` on the return value. Also modified the `validateContent()` and `validate()` test helpers in `test/common/report.js` to be somewhat more obvious and helpful. Of note, a report failing validation will now be easier (though still not _easy_) to read when prepended to the stack trace. - Refs: https://github.com/nodejs/diagnostics/issues/315 PR-URL: https://github.com/nodejs/node/pull/28630 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Rich Trott <rtrott@gmail.com>
This commit is contained in:
parent
28e18cfff0
commit
bff7a46f31
@ -1726,14 +1726,19 @@ added: v11.8.0
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
* `err` {Error} A custom error used for reporting the JavaScript stack.
|
* `err` {Error} A custom error used for reporting the JavaScript stack.
|
||||||
* Returns: {string}
|
* Returns: {Object}
|
||||||
|
|
||||||
Returns a JSON-formatted diagnostic report for the running process. The report's
|
Returns a JavaScript Object representation of a diagnostic report for the
|
||||||
JavaScript stack trace is taken from `err`, if present.
|
running process. The report's JavaScript stack trace is taken from `err`, if
|
||||||
|
present.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const data = process.report.getReport();
|
const data = process.report.getReport();
|
||||||
console.log(data);
|
console.log(data.header.nodeJsVersion);
|
||||||
|
|
||||||
|
// Similar to process.report.writeReport()
|
||||||
|
const fs = require('fs');
|
||||||
|
fs.writeFileSync(util.inspect(data), 'my-report.log', 'utf8');
|
||||||
```
|
```
|
||||||
|
|
||||||
Additional documentation is available in the [report documentation][].
|
Additional documentation is available in the [report documentation][].
|
||||||
|
@ -463,12 +463,15 @@ try {
|
|||||||
// Any other code
|
// Any other code
|
||||||
```
|
```
|
||||||
|
|
||||||
The content of the diagnostic report can be returned as a JSON-compatible object
|
The content of the diagnostic report can be returned as a JavaScript Object
|
||||||
via an API call from a JavaScript application:
|
via an API call from a JavaScript application:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const report = process.report.getReport();
|
const report = process.report.getReport();
|
||||||
console.log(report);
|
console.log(typeof report === 'object'); // true
|
||||||
|
|
||||||
|
// Similar to process.report.writeReport() output
|
||||||
|
console.log(JSON.stringify(report, null, 2));
|
||||||
```
|
```
|
||||||
|
|
||||||
This function takes an optional additional argument `err` - an `Error` object
|
This function takes an optional additional argument `err` - an `Error` object
|
||||||
@ -476,7 +479,7 @@ that will be used as the context for the JavaScript stack printed in the report.
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
const report = process.report.getReport(new Error('custom error'));
|
const report = process.report.getReport(new Error('custom error'));
|
||||||
console.log(report);
|
console.log(typeof report === 'object'); // true
|
||||||
```
|
```
|
||||||
|
|
||||||
The API versions are useful when inspecting the runtime state from within
|
The API versions are useful when inspecting the runtime state from within
|
||||||
@ -498,7 +501,7 @@ Node.js report completed
|
|||||||
>
|
>
|
||||||
```
|
```
|
||||||
|
|
||||||
When a report is triggered, start and end messages are issued to stderr
|
When a report is written, start and end messages are issued to stderr
|
||||||
and the filename of the report is returned to the caller. The default filename
|
and the filename of the report is returned to the caller. The default filename
|
||||||
includes the date, time, PID and a sequence number. The sequence number helps
|
includes the date, time, PID and a sequence number. The sequence number helps
|
||||||
in associating the report dump with the runtime state if generated multiple
|
in associating the report dump with the runtime state if generated multiple
|
||||||
|
@ -5,6 +5,7 @@ const {
|
|||||||
} = require('internal/errors').codes;
|
} = require('internal/errors').codes;
|
||||||
const { validateSignalName, validateString } = require('internal/validators');
|
const { validateSignalName, validateString } = require('internal/validators');
|
||||||
const nr = internalBinding('report');
|
const nr = internalBinding('report');
|
||||||
|
const { JSON } = primordials;
|
||||||
const report = {
|
const report = {
|
||||||
writeReport(file, err) {
|
writeReport(file, err) {
|
||||||
if (typeof file === 'object' && file !== null) {
|
if (typeof file === 'object' && file !== null) {
|
||||||
@ -26,7 +27,7 @@ const report = {
|
|||||||
else if (err === null || typeof err !== 'object')
|
else if (err === null || typeof err !== 'object')
|
||||||
throw new ERR_INVALID_ARG_TYPE('err', 'Object', err);
|
throw new ERR_INVALID_ARG_TYPE('err', 'Object', err);
|
||||||
|
|
||||||
return nr.getReport(err.stack);
|
return JSON.parse(nr.getReport(err.stack));
|
||||||
},
|
},
|
||||||
get directory() {
|
get directory() {
|
||||||
return nr.getDirectory();
|
return nr.getDirectory();
|
||||||
|
@ -31,7 +31,7 @@ switch (process.argv[2]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use process.report to figure out if we might be running under musl libc.
|
// Use process.report to figure out if we might be running under musl libc.
|
||||||
const glibc = JSON.parse(process.report.getReport()).header.glibcVersionRuntime;
|
const glibc = process.report.getReport().header.glibcVersionRuntime;
|
||||||
assert(typeof glibc === 'string' || glibc === undefined, glibc);
|
assert(typeof glibc === 'string' || glibc === undefined, glibc);
|
||||||
|
|
||||||
const libcMayBeMusl = common.isLinux && glibc === undefined;
|
const libcMayBeMusl = common.isLinux && glibc === undefined;
|
||||||
|
@ -859,19 +859,20 @@ functionality.
|
|||||||
Returns an array of diagnotic report file names found in `dir`. The files should
|
Returns an array of diagnotic report file names found in `dir`. The files should
|
||||||
have been generated by a process whose PID matches `pid`.
|
have been generated by a process whose PID matches `pid`.
|
||||||
|
|
||||||
### validate(report)
|
### validate(filepath)
|
||||||
|
|
||||||
* `report` [<string>] Diagnostic report file name to validate.
|
* `filepath` [<string>] Diagnostic report filepath to validate.
|
||||||
|
|
||||||
Validates the schema of a diagnostic report file whose path is specified in
|
Validates the schema of a diagnostic report file whose path is specified in
|
||||||
`report`. If the report fails validation, an exception is thrown.
|
`filepath`. If the report fails validation, an exception is thrown.
|
||||||
|
|
||||||
### validateContent(data)
|
### validateContent(report)
|
||||||
|
|
||||||
* `data` [<string>] Contents of a diagnostic report file.
|
* `report` [<Object|string>] JSON contents of a diagnostic report file, the
|
||||||
|
parsed Object thereof, or the result of `process.report.getReport()`.
|
||||||
|
|
||||||
Validates the schema of a diagnostic report whose content is specified in
|
Validates the schema of a diagnostic report whose content is specified in
|
||||||
`data`. If the report fails validation, an exception is thrown.
|
`report`. If the report fails validation, an exception is thrown.
|
||||||
|
|
||||||
## tick Module
|
## tick Module
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ const assert = require('assert');
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const util = require('util');
|
||||||
|
|
||||||
function findReports(pid, dir) {
|
function findReports(pid, dir) {
|
||||||
// Default filenames are of the form
|
// Default filenames are of the form
|
||||||
@ -21,24 +22,31 @@ function findReports(pid, dir) {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
function validate(report) {
|
function validate(filepath) {
|
||||||
const data = fs.readFileSync(report, 'utf8');
|
validateContent(JSON.parse(fs.readFileSync(filepath, 'utf8')));
|
||||||
|
|
||||||
validateContent(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateContent(data) {
|
function validateContent(report) {
|
||||||
|
if (typeof report === 'string') {
|
||||||
|
try {
|
||||||
|
report = JSON.parse(report);
|
||||||
|
} catch {
|
||||||
|
throw new TypeError(
|
||||||
|
'validateContent() expects a JSON string or JavaScript Object');
|
||||||
|
}
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
_validateContent(data);
|
_validateContent(report);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
err.stack += `\n------\nFailing Report:\n${data}`;
|
try {
|
||||||
|
err.stack += util.format('\n------\nFailing Report:\n%O', report);
|
||||||
|
} catch {}
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _validateContent(data) {
|
function _validateContent(report) {
|
||||||
const isWindows = process.platform === 'win32';
|
const isWindows = process.platform === 'win32';
|
||||||
const report = JSON.parse(data);
|
|
||||||
|
|
||||||
// Verify that all sections are present as own properties of the report.
|
// Verify that all sections are present as own properties of the report.
|
||||||
const sections = ['header', 'javascriptStack', 'nativeStack',
|
const sections = ['header', 'javascriptStack', 'nativeStack',
|
||||||
|
@ -43,7 +43,7 @@ if (process.argv[2] === 'child') {
|
|||||||
const server = http.createServer((req, res) => {
|
const server = http.createServer((req, res) => {
|
||||||
req.on('end', () => {
|
req.on('end', () => {
|
||||||
// Generate the report while the connection is active.
|
// Generate the report while the connection is active.
|
||||||
console.log(process.report.getReport());
|
console.log(JSON.stringify(process.report.getReport(), null, 2));
|
||||||
child_process.kill();
|
child_process.kill();
|
||||||
|
|
||||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||||
|
Loading…
x
Reference in New Issue
Block a user