forked from nodejs/node
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathreport.js
More file actions
115 lines (101 loc) · 3.38 KB
/
report.js
File metadata and controls
115 lines (101 loc) · 3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
'use strict';
const {
convertToValidSignal,
emitExperimentalWarning
} = require('internal/util');
const {
ERR_INVALID_ARG_TYPE,
ERR_SYNTHETIC
} = require('internal/errors').codes;
// 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: ''
};
const report = {
setOptions(options) {
emitExperimentalWarning('report');
const previousConfig = config;
const newConfig = {};
if (options === null || typeof options !== 'object')
options = {};
if (Array.isArray(options.events))
newConfig.events = options.events.slice();
else if (options.events === undefined)
newConfig.events = [];
else
throw new ERR_INVALID_ARG_TYPE('events', 'Array', options.events);
if (typeof options.filename === 'string')
newConfig.filename = options.filename;
else if (options.filename === undefined)
newConfig.filename = '';
else
throw new ERR_INVALID_ARG_TYPE('filename', 'string', options.filename);
if (typeof options.path === 'string')
newConfig.path = options.path;
else if (options.path === undefined)
newConfig.path = '';
else
throw new ERR_INVALID_ARG_TYPE('path', 'string', options.path);
if (typeof options.signal === 'string')
newConfig.signal = convertToValidSignal(options.signal);
else if (options.signal === undefined)
newConfig.signal = 'SIGUSR2';
else
throw new ERR_INVALID_ARG_TYPE('signal', 'string', options.signal);
if (previousConfig.signal)
process.removeListener(previousConfig.signal, handleSignal);
if (newConfig.events.includes('signal'))
process.on(newConfig.signal, handleSignal);
config = newConfig;
nr.syncConfig(config, true);
},
triggerReport(file, err) {
emitExperimentalWarning('report');
if (typeof file === 'object' && file !== null) {
err = file;
file = undefined;
} else if (file !== undefined && typeof file !== 'string') {
throw new ERR_INVALID_ARG_TYPE('file', 'String', file);
} else if (err === undefined) {
err = new ERR_SYNTHETIC();
} else if (err === null || typeof err !== 'object') {
throw new ERR_INVALID_ARG_TYPE('err', 'Object', err);
}
return nr.triggerReport(file, err.stack);
},
getReport(err) {
emitExperimentalWarning('report');
if (err == null) {
return nr.getReport(new ERR_SYNTHETIC().stack);
} else if (typeof err !== 'object') {
throw new ERR_INVALID_ARG_TYPE('err', 'Object', err);
} else {
return nr.getReport(err.stack);
}
}
};
function handleSignal(signo) {
if (typeof signo !== 'string')
signo = config.signal;
nr.onUserSignal(signo);
}
module.exports = {
config,
handleSignal,
report,
syncConfig: nr.syncConfig
};