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.
@@ -1,7 +1,7 @@
1
1
  {
2
- "version": "24.10.0.0",
3
- "sha": "",
2
+ "version": "24.12.0.0",
3
+ "sha": "9ace834212bd2d285a9d19f2e69af5f771a8acc6",
4
4
  "nodeVersion": "",
5
- "buildName": "10391",
5
+ "buildName": "10453",
6
6
  "compatibilityVersion": "4.4.1.0"
7
7
  }
@@ -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
- finalizeTransaction(null, profiler, time, transaction, req, res, span);
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.finalizeTransaction(e, profiler, time, transaction, req, res, span);
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[requestId]) {
310
- newOpQueue[requestId] = {
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[requestId];
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[requestId];
337
+ var requestId = event.requestId, newRequest = newOpQueue.get(requestId);
338
338
  if (newRequest) {
339
339
  self.addExitCall(newRequest.time, newRequest.exitCall);
340
- newOpQueue[requestId] = undefined;
340
+ newOpQueue.delete(requestId);
341
341
  }
342
342
  });
343
343
 
344
344
  obj.on('commandFailed', function (event) {
345
- var requestId = event.requestId, newRequest = newOpQueue[requestId];
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[requestId] = undefined;
348
+ newOpQueue.delete(requestId);
349
349
  }
350
350
  });
351
351
  });
@@ -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.10.0",
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.10.0.0/appdynamics-libagent-napi-node.tgz",
55
- "appdynamics-native": "https://cdn.appdynamics.com/packages/nodejs/24.10.0.0/appdynamics-native-node.tgz",
56
- "appdynamics-protobuf": "https://cdn.appdynamics.com/packages/nodejs/24.10.0.0/appdynamics-protobuf-node.tgz"
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.10.0",
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.10.0.0/appdynamics-libagent-napi-node.tgz",
55
- "appdynamics-native": "https://cdn.appdynamics.com/packages/nodejs/24.10.0.0/appdynamics-native-node.tgz",
56
- "appdynamics-protobuf": "https://cdn.appdynamics.com/packages/nodejs/24.10.0.0/appdynamics-protobuf-node.tgz"
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"