appdynamics 24.10.0 → 24.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/appdynamics_version.json +3 -3
- package/lib/libagent/libagent-connector.js +33 -0
- package/lib/libagent/transaction-sender.js +26 -3
- package/lib/probes/http-common.js +29 -5
- package/lib/probes/http-entry-probe.js +4 -3
- package/lib/probes/mongodb-probe.js +9 -9
- package/lib/profiler/profiler.js +55 -0
- package/package.json +4 -4
- package/packageBck.json +4 -4
package/appdynamics_version.json
CHANGED
|
@@ -174,6 +174,12 @@ LibagentConnector.prototype.init = function () {
|
|
|
174
174
|
|
|
175
175
|
self.agent.transactionSender.isEnabled = true;
|
|
176
176
|
});
|
|
177
|
+
|
|
178
|
+
self.libagent.delegate.on('sepDropped', function (guid) {
|
|
179
|
+
var profiler = self.agent.profiler;
|
|
180
|
+
profiler.sepDropped(guid);
|
|
181
|
+
});
|
|
182
|
+
|
|
177
183
|
self.libagent.delegate.on('transactionDropped', function (guid) {
|
|
178
184
|
var profiler = self.agent.profiler;
|
|
179
185
|
profiler.transactionDropped(guid);
|
|
@@ -229,6 +235,33 @@ LibagentConnector.prototype.stopBusinessTransaction = function (transaction) {
|
|
|
229
235
|
self.libagent.stopBusinessTransaction(transaction.btGuid);
|
|
230
236
|
};
|
|
231
237
|
|
|
238
|
+
LibagentConnector.prototype.startServiceEndpoint = function (entryPointType, request) {
|
|
239
|
+
var self = this;
|
|
240
|
+
return self.libagent.startServiceEndpoint(entryPointType, request);
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
LibagentConnector.prototype.stopServiceEndpoint = function (sep) {
|
|
244
|
+
var self = this;
|
|
245
|
+
|
|
246
|
+
if(!self.agent.profiler.isValidSepThreadId(sep.threadId)) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (sep.error) {
|
|
251
|
+
var name = self.protobufModel.extractErrorName(sep.error);
|
|
252
|
+
if (!name) {
|
|
253
|
+
name = "";
|
|
254
|
+
}
|
|
255
|
+
var message = self.protobufModel.extractErrorMessage(sep.error);
|
|
256
|
+
if (!message) {
|
|
257
|
+
message = "";
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
self.libagent.addErrorToEndpoint(sep.sepGuid, name, message);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
self.libagent.stopServiceEndpoint(sep.sepGuid);
|
|
264
|
+
};
|
|
232
265
|
|
|
233
266
|
LibagentConnector.prototype.startExitCall = function (transaction, exitCall) {
|
|
234
267
|
var self = this;
|
|
@@ -22,6 +22,29 @@ TransactionSender.prototype.init = function() {
|
|
|
22
22
|
self.isEnabled = true;
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
+
self.agent.on("serviceEndpointStart", function(sep, req) {
|
|
26
|
+
if (!self.isEnabled) {
|
|
27
|
+
self.agent.logger.warn('serviceEndpointStart sent without enabled sender');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
var sepData = libagentConnector.startServiceEndpoint('NODEJS_WEB', utility.createBtNamingWrapper(req));
|
|
31
|
+
|
|
32
|
+
if (sepData === undefined || sepData.isExcluded) {
|
|
33
|
+
sep.skip = true;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
sep.skip = false;
|
|
38
|
+
sep.name = sepData.name;
|
|
39
|
+
sep.sepGuid = sepData.sepGuid;
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
self.agent.on("serviceEndpointStop", function(sep) {
|
|
43
|
+
if (!self.isEnabled || sep.skip) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
libagentConnector.stopServiceEndpoint(sep);
|
|
47
|
+
});
|
|
25
48
|
|
|
26
49
|
self.agent.on("transactionStarted", function(transaction, req) {
|
|
27
50
|
if (!self.isEnabled) {
|
|
@@ -47,15 +70,15 @@ TransactionSender.prototype.init = function() {
|
|
|
47
70
|
if('singularityheader' in req.headers) {
|
|
48
71
|
corrHeader = req.headers.singularityheader || "";
|
|
49
72
|
} else if(self.agent.tracer && transaction.baggageCorrHeader) {
|
|
50
|
-
/*
|
|
51
|
-
* 1: We append the doNotResolveSubHeader when the upstream is a pure OT service to
|
|
73
|
+
/*
|
|
74
|
+
* 1: We append the doNotResolveSubHeader when the upstream is a pure OT service to
|
|
52
75
|
* prevent resolution to the preceding APPD service
|
|
53
76
|
2: The noTxDetectHeader is treated specially by libagent, so do not append the doNotResolveSubHeader
|
|
54
77
|
in this case
|
|
55
78
|
*/
|
|
56
79
|
const noTxDetectHeader = self.agent.correlation.DISABLE_TRANSACTION_DETECTION + '=true';
|
|
57
80
|
const doNotResolveSubHeader = self.agent.correlation.DONOTRESOLVE + '=true';
|
|
58
|
-
corrHeader = transaction.baggageCorrHeader != noTxDetectHeader ? transaction.baggageCorrHeader + '*' +
|
|
81
|
+
corrHeader = transaction.baggageCorrHeader != noTxDetectHeader ? transaction.baggageCorrHeader + '*' +
|
|
59
82
|
doNotResolveSubHeader : transaction.baggageCorrHeader;
|
|
60
83
|
self.agent.logger.debug(`Using Singularity Header from Opentelemetry Baggage ${corrHeader}`);
|
|
61
84
|
}
|
|
@@ -10,6 +10,7 @@ module.exports.getHttpStatusCodeConfig = getHttpStatusCodeConfig;
|
|
|
10
10
|
module.exports.generateError = generateError;
|
|
11
11
|
module.exports.getHttpExitCallError = getHttpExitCallError;
|
|
12
12
|
module.exports.finalizeTransaction = finalizeTransaction;
|
|
13
|
+
module.exports.finalizeRequest = finalizeRequest;
|
|
13
14
|
module.exports.startTransactionHandler = startTransactionHandler;
|
|
14
15
|
|
|
15
16
|
|
|
@@ -66,10 +67,30 @@ function getHttpExitCallError(statusCode, stack, locals) {
|
|
|
66
67
|
return error;
|
|
67
68
|
}
|
|
68
69
|
|
|
69
|
-
|
|
70
|
-
function finalizeTransaction (err, profiler, time, transaction, req, res, span) {
|
|
70
|
+
function finalizeRequest(err, profiler, time, transaction, req, res, span, sep) {
|
|
71
71
|
if (!time.done()) return;
|
|
72
|
+
finalizeTransaction(err, profiler, time, transaction, req, res, span);
|
|
73
|
+
finalizeServiceEndpoint(err, profiler, time, sep, res);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function finalizeServiceEndpoint (err, profiler, time, sep, res) {
|
|
77
|
+
if(!sep) return;
|
|
78
|
+
sep.error = sep.error || res.error || err;
|
|
79
|
+
sep.statusCode = sep.statusCode ||
|
|
80
|
+
(sep.error && sep.error.statusCode) ||
|
|
81
|
+
(res && res.statusCode) ||
|
|
82
|
+
500;
|
|
83
|
+
sep.stackTrace = sep.stackTrace || profiler.formatStackTrace(sep.error);
|
|
84
|
+
|
|
85
|
+
var error = generateError(sep.error, sep.statusCode);
|
|
86
|
+
if (error) {
|
|
87
|
+
sep.error = error;
|
|
88
|
+
}
|
|
89
|
+
profiler.endServiceEndpoint(time, sep);
|
|
90
|
+
}
|
|
91
|
+
|
|
72
92
|
|
|
93
|
+
function finalizeTransaction (err, profiler, time, transaction, req, res, span) {
|
|
73
94
|
transaction.error = transaction.error || res.error || err;
|
|
74
95
|
transaction.statusCode = transaction.statusCode ||
|
|
75
96
|
(transaction.error && transaction.error.statusCode) ||
|
|
@@ -108,7 +129,7 @@ function startTransactionHandler(req, res, agent, isHTTPs, tracer, ot_api) {
|
|
|
108
129
|
var span = undefined;
|
|
109
130
|
var baggageCorrHeader = undefined;
|
|
110
131
|
var otContext = undefined;
|
|
111
|
-
|
|
132
|
+
|
|
112
133
|
if (tracer) {
|
|
113
134
|
otContext = ot_api.propagation.extract(agent.TracerProvider.ot_api.ROOT_CONTEXT, req.headers);
|
|
114
135
|
var baggage = ot_api.propagation.getBaggage(otContext);
|
|
@@ -151,10 +172,13 @@ function startTransactionHandler(req, res, agent, isHTTPs, tracer, ot_api) {
|
|
|
151
172
|
});
|
|
152
173
|
}
|
|
153
174
|
|
|
175
|
+
var serviceEndpoint = profiler.startServiceEndpoint(time, req, 'NODEJS_WEB');
|
|
176
|
+
|
|
154
177
|
proxy.after(res, "end", function () {
|
|
155
|
-
|
|
178
|
+
finalizeRequest(null, profiler, time, transaction, req, res, span, serviceEndpoint);
|
|
156
179
|
transaction = null;
|
|
180
|
+
serviceEndpoint = null;
|
|
157
181
|
});
|
|
158
182
|
|
|
159
|
-
return { transaction, span, otContext };
|
|
183
|
+
return { transaction, span, otContext, serviceEndpoint };
|
|
160
184
|
}
|
|
@@ -115,7 +115,7 @@ HttpEntryProbe.prototype.__createRequestHandler = function (callback, isHTTPs) {
|
|
|
115
115
|
|
|
116
116
|
self.agent.metricsManager.addMetric(self.agent.metricsManager.HTTP_INCOMING_COUNT, 1);
|
|
117
117
|
|
|
118
|
-
let { transaction, span, otContext } = HttpCommon.startTransactionHandler(req, res, self.agent, isHTTPs, self.tracer, self.ot_api);
|
|
118
|
+
let { transaction, span, otContext, serviceEndpoint } = HttpCommon.startTransactionHandler(req, res, self.agent, isHTTPs, self.tracer, self.ot_api);
|
|
119
119
|
|
|
120
120
|
var threadId = transaction.threadId;
|
|
121
121
|
self.agent.context.run(() => {
|
|
@@ -127,7 +127,8 @@ HttpEntryProbe.prototype.__createRequestHandler = function (callback, isHTTPs) {
|
|
|
127
127
|
let threadProxyWrappedCb = self.agent.proxy.wrapWithThreadProxyIfEnabled(callback);
|
|
128
128
|
return invokeOriginal(threadProxyWrappedCb, this, arguments, self.ot_api, span, otContext, req, res);
|
|
129
129
|
} catch (e) {
|
|
130
|
-
HttpCommon.
|
|
130
|
+
HttpCommon.finalizeRequest(e, profiler, time, transaction, req, res, span, serviceEndpoint);
|
|
131
|
+
serviceEndpoint = null;
|
|
131
132
|
transaction = null;
|
|
132
133
|
throw e;
|
|
133
134
|
} finally {
|
|
@@ -140,6 +141,6 @@ HttpEntryProbe.prototype.__createRequestHandler = function (callback, isHTTPs) {
|
|
|
140
141
|
// This is needed as Express attaches a bunch of extra properties and
|
|
141
142
|
// functionality, which may need to be accessed by other modules down stream.
|
|
142
143
|
handler.__proto__ = callback;
|
|
143
|
-
|
|
144
|
+
|
|
144
145
|
return handler;
|
|
145
146
|
};
|
|
@@ -283,7 +283,7 @@ MongodbProbe.prototype.attach = function (obj) {
|
|
|
283
283
|
proxy.before(obj.MongoClient.prototype, 'connect', function(obj){
|
|
284
284
|
obj.monitorCommands = true;
|
|
285
285
|
var newServerPool;
|
|
286
|
-
var newOpQueue =
|
|
286
|
+
var newOpQueue = new Map();
|
|
287
287
|
var newApmCollectionEvents = ['create', 'drop'];
|
|
288
288
|
var newCollectionCommandMap = {
|
|
289
289
|
'create': 'createCollection',
|
|
@@ -306,13 +306,13 @@ MongodbProbe.prototype.attach = function (obj) {
|
|
|
306
306
|
newServerPool = [event.address];
|
|
307
307
|
}
|
|
308
308
|
if (newServerPool) {
|
|
309
|
-
if (!newOpQueue
|
|
310
|
-
newOpQueue
|
|
309
|
+
if (!newOpQueue.has(requestId)) {
|
|
310
|
+
newOpQueue.set(requestId, {
|
|
311
311
|
time: profiler.time(),
|
|
312
312
|
serverPool: newServerPool
|
|
313
|
-
};
|
|
313
|
+
});
|
|
314
314
|
}
|
|
315
|
-
newRequest = newOpQueue
|
|
315
|
+
newRequest = newOpQueue.get(requestId);
|
|
316
316
|
newCommandQuery = event.command.filter;
|
|
317
317
|
if (event.command.filter && Object.prototype.toString.call(event.command.filter) == "[object Object]") {
|
|
318
318
|
newCommandQuery = utility.filterSensitiveDataFromObject(utility.deepCopy(event.command.filter));
|
|
@@ -334,18 +334,18 @@ MongodbProbe.prototype.attach = function (obj) {
|
|
|
334
334
|
});
|
|
335
335
|
|
|
336
336
|
obj.on('commandSucceeded', function (event) {
|
|
337
|
-
var requestId = event.requestId, newRequest = newOpQueue
|
|
337
|
+
var requestId = event.requestId, newRequest = newOpQueue.get(requestId);
|
|
338
338
|
if (newRequest) {
|
|
339
339
|
self.addExitCall(newRequest.time, newRequest.exitCall);
|
|
340
|
-
newOpQueue
|
|
340
|
+
newOpQueue.delete(requestId);
|
|
341
341
|
}
|
|
342
342
|
});
|
|
343
343
|
|
|
344
344
|
obj.on('commandFailed', function (event) {
|
|
345
|
-
var requestId = event.requestId, newRequest = newOpQueue
|
|
345
|
+
var requestId = event.requestId, newRequest = newOpQueue.get(requestId);
|
|
346
346
|
if (newRequest) {
|
|
347
347
|
self.addExitCall(event.time, event.exitCall, event.failure);
|
|
348
|
-
newOpQueue
|
|
348
|
+
newOpQueue.delete(requestId);
|
|
349
349
|
}
|
|
350
350
|
});
|
|
351
351
|
});
|
package/lib/profiler/profiler.js
CHANGED
|
@@ -19,6 +19,7 @@ function Profiler(agent) {
|
|
|
19
19
|
this.agent = agent;
|
|
20
20
|
|
|
21
21
|
this.transactions = {};
|
|
22
|
+
this.serviceEndpoints = {};
|
|
22
23
|
this.stackTraceFilter = /appdynamics/;
|
|
23
24
|
}
|
|
24
25
|
exports.Profiler = Profiler;
|
|
@@ -83,6 +84,43 @@ Profiler.prototype.formatStackTrace = function (err) {
|
|
|
83
84
|
return undefined;
|
|
84
85
|
};
|
|
85
86
|
|
|
87
|
+
Profiler.prototype.startServiceEndpoint = function(time, req, entryType) {
|
|
88
|
+
var self = this;
|
|
89
|
+
var sep = {};
|
|
90
|
+
sep.time = time;
|
|
91
|
+
sep.id = time.id;
|
|
92
|
+
sep.threadId = time.threadId;
|
|
93
|
+
sep.entryType = entryType;
|
|
94
|
+
|
|
95
|
+
self.serviceEndpoints[time.threadId] = sep;
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
self.agent.emit('serviceEndpointStart', sep, req);
|
|
99
|
+
} catch (err) {
|
|
100
|
+
self.agent.logger.warn(err);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return sep;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
Profiler.prototype.endServiceEndpoint = function (time, sep) {
|
|
107
|
+
var self = this;
|
|
108
|
+
|
|
109
|
+
if (sep.isFinished) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
sep.isFinished = true;
|
|
114
|
+
sep.ms = time.ms;
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
self.agent.emit('serviceEndpointStop', sep);
|
|
118
|
+
} catch (err) {
|
|
119
|
+
self.agent.logger.warn(err);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
delete self.serviceEndpoints[time.threadId];
|
|
123
|
+
};
|
|
86
124
|
|
|
87
125
|
Profiler.prototype.startTransaction = function(time, req, entryType, baggageCorrHeader) {
|
|
88
126
|
var self = this;
|
|
@@ -184,6 +222,11 @@ Profiler.prototype.isValidThreadId = function(threadId) {
|
|
|
184
222
|
return (threadId && self.transactions[threadId]);
|
|
185
223
|
};
|
|
186
224
|
|
|
225
|
+
Profiler.prototype.isValidSepThreadId = function(threadId) {
|
|
226
|
+
var self = this;
|
|
227
|
+
return (threadId && self.serviceEndpoints[threadId]);
|
|
228
|
+
};
|
|
229
|
+
|
|
187
230
|
Profiler.prototype._endTransaction = function (time, transaction) {
|
|
188
231
|
var self = this;
|
|
189
232
|
|
|
@@ -217,6 +260,18 @@ Profiler.prototype.transactionDropped = function (guid) {
|
|
|
217
260
|
}
|
|
218
261
|
};
|
|
219
262
|
|
|
263
|
+
Profiler.prototype.sepDropped = function (guid) {
|
|
264
|
+
var self = this;
|
|
265
|
+
|
|
266
|
+
for (var threadId in self.serviceEndpoints) {
|
|
267
|
+
if (self.serviceEndpoints[threadId].sepGuid === guid) {
|
|
268
|
+
self.agent.logger.info('SEP ' + self.serviceEndpoints[threadId].id + ' dropped');
|
|
269
|
+
delete self.serviceEndpoints[threadId];
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
|
|
220
275
|
Profiler.prototype.__getNextSequenceInfo = function (transaction) {
|
|
221
276
|
var self = this;
|
|
222
277
|
transaction.exitCallCounter++;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "appdynamics",
|
|
3
|
-
"version": "24.
|
|
3
|
+
"version": "24.12.0",
|
|
4
4
|
"description": "Performance Profiler and Monitor",
|
|
5
5
|
"author": "AppDynamics, Inc.",
|
|
6
6
|
"homepage": "https://www.appdynamics.com",
|
|
@@ -51,9 +51,9 @@
|
|
|
51
51
|
"https-proxy-agent": "^5.0.1",
|
|
52
52
|
"uuid": "^8.3.2",
|
|
53
53
|
"y18n": "^5.0.8",
|
|
54
|
-
"appdynamics-libagent-napi": "https://cdn.appdynamics.com/packages/nodejs/24.
|
|
55
|
-
"appdynamics-native": "https://cdn.appdynamics.com/packages/nodejs/24.
|
|
56
|
-
"appdynamics-protobuf": "https://cdn.appdynamics.com/packages/nodejs/24.
|
|
54
|
+
"appdynamics-libagent-napi": "https://cdn.appdynamics.com/packages/nodejs/24.12.0.0/appdynamics-libagent-napi-node.tgz",
|
|
55
|
+
"appdynamics-native": "https://cdn.appdynamics.com/packages/nodejs/24.12.0.0/appdynamics-native-node.tgz",
|
|
56
|
+
"appdynamics-protobuf": "https://cdn.appdynamics.com/packages/nodejs/24.12.0.0/appdynamics-protobuf-node.tgz"
|
|
57
57
|
},
|
|
58
58
|
"overrides": {
|
|
59
59
|
"semver": "7.5.4"
|
package/packageBck.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "appdynamics",
|
|
3
|
-
"version": "24.
|
|
3
|
+
"version": "24.12.0",
|
|
4
4
|
"description": "Performance Profiler and Monitor",
|
|
5
5
|
"author": "AppDynamics, Inc.",
|
|
6
6
|
"homepage": "https://www.appdynamics.com",
|
|
@@ -51,9 +51,9 @@
|
|
|
51
51
|
"https-proxy-agent": "^5.0.1",
|
|
52
52
|
"uuid": "^8.3.2",
|
|
53
53
|
"y18n": "^5.0.8",
|
|
54
|
-
"appdynamics-libagent-napi": "https://cdn.appdynamics.com/packages/nodejs/24.
|
|
55
|
-
"appdynamics-native": "https://cdn.appdynamics.com/packages/nodejs/24.
|
|
56
|
-
"appdynamics-protobuf": "https://cdn.appdynamics.com/packages/nodejs/24.
|
|
54
|
+
"appdynamics-libagent-napi": "https://cdn.appdynamics.com/packages/nodejs/24.12.0.0/appdynamics-libagent-napi-node.tgz",
|
|
55
|
+
"appdynamics-native": "https://cdn.appdynamics.com/packages/nodejs/24.12.0.0/appdynamics-native-node.tgz",
|
|
56
|
+
"appdynamics-protobuf": "https://cdn.appdynamics.com/packages/nodejs/24.12.0.0/appdynamics-protobuf-node.tgz"
|
|
57
57
|
},
|
|
58
58
|
"overrides": {
|
|
59
59
|
"semver": "7.5.4"
|