-
Notifications
You must be signed in to change notification settings - Fork 157
/
Copy pathcapture.js
148 lines (116 loc) · 4.19 KB
/
capture.js
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/**
* Capture module.
* @module capture
*/
var contextUtils = require('./context_utils');
var logger = require('./logger');
/**
* Wrap to automatically capture information for the segment.
* @param {string} name - The name of the new subsegment.
* @param {function} fcn - The function context to wrap. Can take a single 'subsegment' argument.
* @param {Segment|Subsegment} [parent] - The parent for the new subsegment, for manual mode.
* @alias module:capture.captureFunc
* @return {*} - Returns the result if any by executing the provided function.
*/
var captureFunc = function captureFunc(name, fcn, parent) {
validate(name, fcn);
var current, executeFcn;
var parentSeg = contextUtils.resolveSegment(parent);
if (!parentSeg) {
logger.getLogger().warn('Failed to capture function.');
return fcn();
}
current = parentSeg.addNewSubsegment(name);
executeFcn = captureFcn(fcn, current);
try {
const response = executeFcn(current);
current.close();
return response;
} catch (e) {
current.close(e);
throw (e);
}
};
/**
* Wrap to automatically capture information for the sub/segment. You must close the segment
* manually from within the function.
* @param {string} name - The name of the new subsegment.
* @param {function} fcn - The function context to wrap. Must take a single 'subsegment' argument and call 'subsegment.close([optional error])' when the async function completes.
* @param {Segment|Subsegment} [parent] - The parent for the new subsegment, for manual mode.
* @alias module:capture.captureAsyncFunc
* @return {*} - Returns a promise by executing the provided async function.
*/
var captureAsyncFunc = function captureAsyncFunc(name, fcn, parent) {
validate(name, fcn);
var current, executeFcn;
var parentSeg = contextUtils.resolveSegment(parent);
if (!parentSeg) {
logger.getLogger().warn('Failed to capture async function.');
return fcn();
}
current = parentSeg.addNewSubsegment(name);
executeFcn = captureFcn(fcn, current);
try {
return executeFcn(current);
} catch (e) {
current.close(e);
throw (e);
}
};
/**
* Wrap to automatically capture information for the sub/segment. This wraps the callback and returns a function.
* when executed, all arguments are passed through accordingly. An additional argument is appended to gain access to the newly created subsegment.
* For this reason, always call the captured callback with the full list of arguments.
* @param {string} name - The name of the new subsegment.
* @param {function} fcn - The function context to wrap. Can take a single 'subsegment' argument.
* @param {Segment|Subsegment} [parent] - The parent for the new subsegment, for manual mode.
* @alias module:capture.captureCallbackFunc
*/
var captureCallbackFunc = function captureCallbackFunc(name, fcn, parent) {
validate(name, fcn);
var base = contextUtils.resolveSegment(parent);
if (!base) {
logger.getLogger().warn('Failed to capture callback function.');
return fcn;
}
base.incrementCounter();
return function() {
var parentSeg = contextUtils.resolveSegment(parent);
var args = Array.prototype.slice.call(arguments);
captureFunc(name, fcn.bind.apply(fcn, [null].concat(args)), parentSeg);
base.decrementCounter();
}.bind(this);
};
function captureFcn(fcn, current) {
var executeFcn;
if (contextUtils.isAutomaticMode()) {
var session = contextUtils.getNamespace();
var contextFcn = function() {
var value;
session.run(function() {
contextUtils.setSegment(current);
value = fcn(current);
});
return value;
};
executeFcn = contextFcn;
} else {
executeFcn = fcn;
}
return executeFcn;
}
function validate(name, fcn) {
var error;
if (!name || typeof name !== 'string') {
error = 'Param "name" must be a non-empty string.';
logger.getLogger().error(error);
throw new Error(error);
} else if (typeof fcn !== 'function') {
error = 'Param "fcn" must be a function.';
logger.getLogger().error(error);
throw new Error(error);
}
}
module.exports.captureFunc = captureFunc;
module.exports.captureAsyncFunc = captureAsyncFunc;
module.exports.captureCallbackFunc = captureCallbackFunc;