@report-toolkit/common
Version:
See docs at [https://ibm.github.io/report-toolkit](https://ibm.github.io/report-toolkit)
106 lines (93 loc) • 3.63 kB
JavaScript
import {NO_FILEPATH, REPORT_KNOWN_ROOT_PROPERTIES} from './constants.js';
import {createDebugger} from './debug.js';
import {createRTkError, RTKERR_INVALID_REPORT} from './error.js';
import {kReport, kReportFilepath} from './symbols.js';
import {_} from './util.js';
const debug = createDebugger('common', 'report');
/**
* Represents a [Diagnostic Report](https://nodejs.org/api/process.html#process_process_report_getreport_err).
*/
class Report {
/**
* Creates shallow copies of root props in `report`; assigns internally-used `Symbol`s.
* @param {import('../diagnostic-report').DiagnosticReport} report - Raw object
* @param {string?} filepath - Original filepath of report, if available. Defaults to {@link NO_FILEPATH}
*/
constructor(report, filepath = NO_FILEPATH) {
if (!Report.isReportLike(report)) {
throw createRTkError(RTKERR_INVALID_REPORT, `Invalid report!`);
}
this.header = {...report.header};
this.javascriptStack = {...report.javascriptStack};
this.nativeStack = [...report.nativeStack];
this.javascriptHeap = {...report.javascriptHeap};
this.resourceUsage = {...report.resourceUsage};
this.libuv = [...report.libuv];
this.workers = [...(report.workers || [])];
this.environmentVariables = {...report.environmentVariables};
this.userLimits = {...report.userLimits};
this.sharedObjects = [...report.sharedObjects];
this[kReportFilepath] = filepath;
this[kReport] = true;
debug(
`created Report generated on ${this.header.dumpEventTime} w/ filepath ${this[kReportFilepath]}`
);
}
/**
* Original filepath of report, if available. Defaults to {@link NO_FILEPATH}.
*/
get filepath() {
return /** @type {string} */ (this[kReportFilepath]);
}
/**
* Creates a read-only {@link Report} from a {@link ReportLike} value.
* Use this instead of `new Report()`!
* @param {ReportLike} rawReport
* @param {string} filepath
*/
static create(rawReport, filepath) {
return Object.freeze(new Report(rawReport, filepath));
}
/**
* Returns `true` if the value is an object having a property `report-toolkit-report` `Symbol` with value `true`.
* @param {any} value
*/
static isReport(value) {
// @ts-ignore
return _.isObject(value) && value[kReport] === true;
}
/**
* Returns `true` if `value` has all expected root properties of a Diagnostic Report (as returned by [process.report.getReport()](https://nodejs.org/api/process.html#process_process_report_getreport_err)), or is a {@link Report}.
* @param {any} value
*/
static isReportLike(value) {
if (Report.isReport(value)) {
return true;
}
if (_.isObject(value)) {
// win32 doesn't report 'userLimits'
let propsToCheck =
_.get('header.platform', value) === 'win32'
? _.pull('userLimits', REPORT_KNOWN_ROOT_PROPERTIES)
: REPORT_KNOWN_ROOT_PROPERTIES;
if (_.getOr(0, 'header.reportVersion', value) < 2) {
propsToCheck = _.pull('workers', propsToCheck);
}
return _.every(key => {
const hasValue = _.has(key, value);
if (!hasValue) {
debug(`report is missing prop "${key}"`);
}
return hasValue;
}, propsToCheck);
}
}
}
export const createReport = Report.create;
export const isReport = Report.isReport;
export const isReportLike = Report.isReportLike;
export {Report};
/**
* Either a {@link Report} or an object with all of the required props. See {@link Report.isReportLike}
* @typedef {import('../diagnostic-report').DiagnosticReport|Report} ReportLike
*/