appdynamics 24.10.0 → 25.5.7

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.
Files changed (38) hide show
  1. package/README.md +0 -1
  2. package/appdynamics_version.json +3 -3
  3. package/lib/core/agent.js +18 -12
  4. package/lib/core/opentelemetry-tracer.js +3 -2
  5. package/lib/libagent/libagent-connector.js +33 -0
  6. package/lib/libagent/transaction-sender.js +30 -3
  7. package/lib/probes/apollo-entry-probe.js +8 -4
  8. package/lib/probes/cassandra-probe.js +4 -0
  9. package/lib/probes/cluster-probe.js +4 -0
  10. package/lib/probes/couchbase-probe.js +12 -3
  11. package/lib/probes/disk-probe.js +4 -0
  12. package/lib/probes/dynamodb-probe.js +4 -0
  13. package/lib/probes/express-probe.js +4 -0
  14. package/lib/probes/http-common.js +29 -5
  15. package/lib/probes/http-entry-probe.js +4 -3
  16. package/lib/probes/http-exit-probe.js +110 -9
  17. package/lib/probes/http-probe.js +11 -3
  18. package/lib/probes/http2-entry-probe.js +1 -1
  19. package/lib/probes/ioredis-probe.js +4 -0
  20. package/lib/probes/memcached-probe.js +4 -0
  21. package/lib/probes/mongodb-probe.js +14 -10
  22. package/lib/probes/mssql-probe.js +4 -0
  23. package/lib/probes/mysql-probe.js +4 -0
  24. package/lib/probes/net-probe.js +4 -0
  25. package/lib/probes/nsolid-probe.js +4 -0
  26. package/lib/probes/pg-probe.js +4 -0
  27. package/lib/probes/process-probe.js +4 -0
  28. package/lib/probes/redis-probe.js +5 -0
  29. package/lib/probes/socket.io-probe.js +4 -0
  30. package/lib/probes/tedious-probe.js +4 -0
  31. package/lib/probes/winston-probe.js +5 -0
  32. package/lib/profiler/profiler.js +55 -0
  33. package/lib/transactions/cookie-util.js +1 -1
  34. package/lib/v8/cpu-profiler.js +4 -0
  35. package/lib/v8/gc-stats.js +2 -0
  36. package/lib/v8/heap-profiler.js +4 -0
  37. package/package.json +9 -15
  38. package/packageBck.json +9 -15
package/README.md CHANGED
@@ -70,4 +70,3 @@ For more information, see [Install the Node.js Agent](https://docs.appdynamics.c
70
70
  <br />
71
71
 
72
72
  Copyright (c) AppDynamics, Inc. 2021 CA. All rights reserved.
73
-
@@ -1,7 +1,7 @@
1
1
  {
2
- "version": "24.10.0.0",
3
- "sha": "",
2
+ "version": "25.5.7.0",
3
+ "sha": "4e3e6665d263d6f1679912c607978c830fbf6ac3",
4
4
  "nodeVersion": "",
5
- "buildName": "10391",
5
+ "buildName": "10836",
6
6
  "compatibilityVersion": "4.4.1.0"
7
7
  }
package/lib/core/agent.js CHANGED
@@ -55,7 +55,7 @@ function Agent() {
55
55
  this.initialized = false;
56
56
  this.version = agentVersion.version;
57
57
  this.compatibilityVersion = agentVersion.compatibilityVersion;
58
- this.nextId = Math.round(Math.random() * Math.pow(10, 6));
58
+ this.nextId = parseInt(crypto.randomBytes(4).toString('hex'), 16) % 1e6;
59
59
  this.appdNative = undefined;
60
60
  this.meta = [];
61
61
 
@@ -124,8 +124,7 @@ Agent.prototype.recursiveMkDir = function (dir) {
124
124
  var dirsToMake = [];
125
125
  var currDir = path.normalize(dir);
126
126
  var parentDir = path.dirname(currDir);
127
- var controlVar = true;
128
- while (controlVar) {
127
+ while (currDir !== parentDir) {
129
128
  if (fs.existsSync(currDir))
130
129
  break;
131
130
  dirsToMake.push(currDir);
@@ -229,17 +228,25 @@ Agent.prototype.init = function (opts) {
229
228
 
230
229
  self.backendConnector = new LibAgent(this);
231
230
 
232
- if (opts.openTelemetry && opts.openTelemetry.enabled) {
233
- var TracerProvider = require('./opentelemetry-tracer');
234
- self.TracerProvider = new TracerProvider(self.logger);
235
- if (!self.TracerProvider.register(opts)) {
236
- self.logger.error('AppDynamics agent cannot be started: Tracer Provider registration has failed');
237
- return;
231
+ // agent_deployment_mode = 'appd' || 'dual' || 'hybrid'
232
+ let agent_deployment_mode = opts.agent_deployment_mode || process.env.agent_deployment_mode;
233
+ if(agent_deployment_mode == 'dual' || opts.openTelemetry && opts.openTelemetry.enabled) {
234
+ const url = require('url');
235
+ let collectorEndpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT || "http://localhost:4318";
236
+ let collectorEndpointUrl = url.parse(collectorEndpoint);
237
+ self.opts.dualModeConfig = {
238
+ collectorHost: collectorEndpointUrl.hostname,
239
+ collectorPort: collectorEndpointUrl.port,
240
+ };
241
+ try {
242
+ const { start } = require('@splunk/otel');
243
+ start();
244
+ }
245
+ catch (err) {
246
+ self.logger.error('AppDynamics dual mode could not be started ' + err);
238
247
  }
239
- self.tracer = self.TracerProvider.getTracer('appdynamics-tracer');
240
248
  }
241
249
 
242
-
243
250
  self.libagentConnector.subscribeToIsEnabled((isEnabled) => setMetadataFile(self, isEnabled));
244
251
 
245
252
  self.precompiled = opts.precompiled === undefined || opts.precompiled;
@@ -734,4 +741,3 @@ exports = module.exports = new AppDynamics();
734
741
 
735
742
  // export for testing
736
743
  exports._setMetadataFile = setMetadataFile;
737
-
@@ -17,7 +17,8 @@ module.exports = TracerProvider;
17
17
  function TracerProvider(logger) {
18
18
  this.host = 'localhost';
19
19
  this.port = '4318';
20
- this.url = `http://${this.host}:${this.port}/v1/traces`;
20
+ this.url = process.env.OTEL_EXPORTER_OTLP_ENDPOINT ? process.env.OTEL_EXPORTER_OTLP_ENDPOINT + '/v1/traces'
21
+ : `http://${this.host}:${this.port}/v1/traces`;
21
22
  this.ot_api = opentelemetry_api;
22
23
  this.ROOT_CONTEXT = ROOT_CONTEXT;
23
24
  this.logger = logger;
@@ -42,7 +43,7 @@ TracerProvider.prototype.register = function(config) {
42
43
  [SemanticResourceAttributes.SERVICE_NAMESPACE]: config.applicationName,
43
44
  [SemanticResourceAttributes.CONTAINER_ID]: ""
44
45
  };
45
-
46
+
46
47
  const mergedResource = new Resource(configResourceAttributes)
47
48
  .merge(envResource)
48
49
  .merge(processResource)
@@ -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
  }
@@ -79,6 +102,7 @@ TransactionSender.prototype.init = function() {
79
102
  transaction.eumEnabled = txData.eumEnabled;
80
103
  transaction.isHttpRequest = isHttpRequest;
81
104
 
105
+ self.agent.logger.debug('Started Txn with TxnGuid: ' + transaction.guid + ' id: ' + transaction.id);
82
106
  if (libagentConnector.isSnapshotRequired(transaction)) {
83
107
  libagentConnector.emit("autoProcessSnapshot");
84
108
  }
@@ -99,6 +123,7 @@ TransactionSender.prototype.init = function() {
99
123
  }
100
124
  }
101
125
 
126
+ self.agent.logger.debug('Stopped Txn with TxnGuid: ' + transaction.guid + ' id: ' + transaction.id);
102
127
  libagentConnector.stopBusinessTransaction(transaction);
103
128
  });
104
129
 
@@ -108,6 +133,7 @@ TransactionSender.prototype.init = function() {
108
133
  return;
109
134
  }
110
135
 
136
+ self.agent.logger.debug('Started Exitcall with TxnGuid: ' + transaction.guid + ' id: ' + transaction.id);
111
137
  libagentConnector.startExitCall(transaction, exitCall);
112
138
  });
113
139
 
@@ -117,6 +143,7 @@ TransactionSender.prototype.init = function() {
117
143
  return;
118
144
  }
119
145
 
146
+ self.agent.logger.debug('Stopped Exitcall with TxnGuid: ' + transaction.guid + ' id: ' + transaction.id);
120
147
  libagentConnector.stopExitCall(exitCall, error);
121
148
  });
122
149
  };
@@ -1,5 +1,5 @@
1
1
  /*
2
- This is for apollo-server entry probe
2
+ This is for apollo-server entry probe
3
3
  */
4
4
 
5
5
  let HttpCommon = require("./http-common");
@@ -16,6 +16,10 @@ ApolloEntryProbe.prototype.attach = function (obj, moduleName) {
16
16
 
17
17
  let self = this;
18
18
 
19
+ if(process.env.APPDYNAMICS_APOLLO_PROBE_DISABLE == true || process.env.APPDYNAMICS_APOLLO_PROBE_DISABLE == 'true') {
20
+ return;
21
+ }
22
+
19
23
  if(moduleName == 'apollo-server') {
20
24
  self.agent.proxy.before(
21
25
  obj.ApolloServer.prototype,
@@ -29,7 +33,7 @@ ApolloEntryProbe.prototype.attach = function (obj, moduleName) {
29
33
 
30
34
  overriddenObject.ApolloServer = proxyApolloServer(self, originalObject);
31
35
  return overriddenObject;
32
-
36
+
33
37
  } else if(moduleName === '@apollo/server/express4') {
34
38
  const originalObject = obj;
35
39
  const overriddenObject = {};
@@ -40,7 +44,7 @@ ApolloEntryProbe.prototype.attach = function (obj, moduleName) {
40
44
  } else if(moduleName === '@apollo/server/standalone'){
41
45
  const originalObject = obj;
42
46
  const overriddenObject = {};
43
-
47
+
44
48
  overriddenObject.startStandaloneServer = proxyStartStandaloneServer(self, originalObject);
45
49
  overriddenObject.__proto__ = originalObject;
46
50
  return overriddenObject;
@@ -106,7 +110,7 @@ function appDynamicsApolloServerPlugin(self) {
106
110
  }
107
111
  requestContext.contextValue.gqlReq.graphqlop = requestContext.operationName;
108
112
  requestContext.contextValue.gqlReq.transactionStarted = true;
109
-
113
+
110
114
  HttpCommon.startTransactionHandler(
111
115
  requestContext.contextValue.gqlReq,
112
116
  requestContext.contextValue.gqlRes,
@@ -20,6 +20,10 @@ CassandraProbe.prototype.attach = function(obj) {
20
20
  var proxy = self.agent.proxy;
21
21
  var profiler = self.agent.profiler;
22
22
 
23
+ if(process.env.APPDYNAMICS_CASSANDRA_PROBE_DISABLE == true || process.env.APPDYNAMICS_CASSANDRA_PROBE_DISABLE == 'true') {
24
+ return;
25
+ }
26
+
23
27
  if(obj.__appdynamicsProbeAttached__) return;
24
28
  obj.__appdynamicsProbeAttached__ = true;
25
29
  self.agent.on('destroy', function() {
@@ -20,6 +20,10 @@ exports.ClusterProbe = ClusterProbe;
20
20
  ClusterProbe.prototype.attach = function(obj) {
21
21
  var self = this;
22
22
 
23
+ if(process.env.APPDYNAMICS_CLUSTER_PROBE_DISABLE == true || process.env.APPDYNAMICS_CLUSTER_PROBE_DISABLE == 'true') {
24
+ return;
25
+ }
26
+
23
27
  if(obj.__appdynamicsProbeAttached__) return;
24
28
  obj.__appdynamicsProbeAttached__ = true;
25
29
  self.agent.on('destroy', function() {
@@ -18,6 +18,10 @@ exports.CouchBaseProbe = CouchBaseProbe;
18
18
  CouchBaseProbe.prototype.attach = function(obj) {
19
19
  var self = this;
20
20
 
21
+ if(process.env.APPDYNAMICS_COUCHBASE_PROBE_DISABLE == true || process.env.APPDYNAMICS_COUCHBASE_PROBE_DISABLE == 'true') {
22
+ return;
23
+ }
24
+
21
25
  if(obj.__appdynamicsProbeAttached__) return;
22
26
  obj.__appdynamicsProbeAttached__ = true;
23
27
  self.agent.on('destroy', function() {
@@ -49,12 +53,15 @@ CouchBaseProbe.prototype.attach = function(obj) {
49
53
  function(obj, args, locals) {
50
54
  locals.time = self.agent.profiler.time();
51
55
  locals.methodHasCb = proxy.callback(args, -1, function() {}, null, self.agent.thread.current());
52
-
56
+
53
57
  var bucketName, addresses;
54
58
  var couchBaseBucket = obj._scope._bucket; // ???
55
59
  bucketName = couchBaseBucket.name;
56
60
  addresses = couchBaseBucket._cluster._connStr || '';
57
- addresses = (addresses.match(/(?:.*:\/\/)?([^/?]+)/)[1] || '').split(',');
61
+
62
+ var matches = addresses.match(/^(?:https?:\/\/)?([^/?]+)/);
63
+ var domain = matches ? matches[1] : '';
64
+ addresses = domain.split(',');
58
65
 
59
66
  var command = cmd;
60
67
  var commandArgs = args;
@@ -74,7 +81,9 @@ CouchBaseProbe.prototype.attach = function(obj) {
74
81
  var addresses;
75
82
  var bucketName = Object.keys(obj._conns);
76
83
  addresses = obj._connStr || '';
77
- addresses = (addresses.match(/(?:.*:\/\/)?([^/?]+)/)[1] || '').split(',');
84
+ var matches = addresses.match(/^(?:https?:\/\/)?([^/?]+)/);
85
+ var domain = matches ? matches[1] : '';
86
+ addresses = domain.split(',');
78
87
 
79
88
  var command = 'query';
80
89
  var commandArgs = args;
@@ -18,6 +18,10 @@ exports.DiskProbe = DiskProbe;
18
18
  DiskProbe.prototype.attach = function(obj) {
19
19
  var self = this;
20
20
 
21
+ if(process.env.APPDYNAMICS_DISK_PROBE_DISABLE == true || process.env.APPDYNAMICS_DISK_PROBE_DISABLE == 'true') {
22
+ return;
23
+ }
24
+
21
25
  if(obj.__appdynamicsProbeAttached__) return;
22
26
  obj.__appdynamicsProbeAttached__ = true;
23
27
  self.agent.on('destroy', function() {
@@ -16,6 +16,10 @@ exports.DynamoDbProbe = DynamoDbProbe;
16
16
  DynamoDbProbe.prototype.attach = function(obj) {
17
17
  var self = this;
18
18
 
19
+ if(process.env.APPDYNAMICS_DYNAMODB_PROBE_DISABLE == true || process.env.APPDYNAMICS_DYNAMODB_PROBE_DISABLE == 'true') {
20
+ return;
21
+ }
22
+
19
23
  if(obj.__appdynamicsProbeAttached__) return;
20
24
  obj.__appdynamicsProbeAttached__ = true;
21
25
  self.agent.on('destroy', function() {
@@ -28,6 +28,10 @@ ExpressProbe.prototype.attach = function(obj) {
28
28
  var self = this,
29
29
  proxy = self.agent.proxy;
30
30
 
31
+ if(process.env.APPDYNAMICS_EXPRESS_PROBE_DISABLE == true || process.env.APPDYNAMICS_EXPRESS_PROBE_DISABLE == 'true') {
32
+ return;
33
+ }
34
+
31
35
  if(obj.__appdynamicsProbeAttached__) {
32
36
  return obj.__appdynamicsWrapperFn;
33
37
  }
@@ -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
  };
@@ -42,6 +42,10 @@ HttpExitProbe.prototype.attach = function (obj, moduleName) {
42
42
  obj = obj.globalAgent;
43
43
  }
44
44
 
45
+ if (typeof global.fetch === 'function' && !global.fetch.__appdynamicsProxyInfo__) {
46
+ self.instrumentFetch();
47
+ }
48
+
45
49
  function clientCallback(locals) {
46
50
  if (!locals.time.done()) return;
47
51
 
@@ -70,7 +74,7 @@ HttpExitProbe.prototype.attach = function (obj, moduleName) {
70
74
 
71
75
  var [input, options] = args;
72
76
 
73
- if (typeof(input) != 'string' && !(input instanceof url.URL)) {
77
+ if (typeof (input) != 'string' && !(input instanceof url.URL)) {
74
78
  options = input;
75
79
  input = null;
76
80
  } else if (!options) {
@@ -78,7 +82,7 @@ HttpExitProbe.prototype.attach = function (obj, moduleName) {
78
82
  args[1] = options;
79
83
  }
80
84
 
81
- if(typeof(options) == 'function') {
85
+ if (typeof (options) == 'function') {
82
86
  args[2] = options;
83
87
  options = {};
84
88
  args[1] = options;
@@ -110,15 +114,17 @@ HttpExitProbe.prototype.attach = function (obj, moduleName) {
110
114
  }
111
115
 
112
116
  var isOtPath = self.agent.TracerProvider && locals.opts.hostname == self.agent.TracerProvider.host
113
- && locals.opts.port == self.agent.TracerProvider.port;
117
+ && locals.opts.port == self.agent.TracerProvider.port;
118
+ var isDualMode = self.agent.opts.dualModeConfig && self.agent.opts.dualModeConfig.collectorHost == locals.opts.hostname;
114
119
  var isDynamoDBReq = options.headers && options.headers['X-Amz-Target'] && options.headers['X-Amz-Target'].indexOf('DynamoDB') > -1;
115
- if (options.appdIgnore || isDynamoDBReq || isRepeatForHttps || isOtPath) {
120
+ if (options.appdIgnore || isDynamoDBReq || isRepeatForHttps || isOtPath || isDualMode) {
116
121
  // (ignore internal HTTP calls, e.g. to Analytics Agent, DynamoDB calls)
117
122
  self.agent.logger.debug('Skipping HTTP exit call for the transaction.' +
118
123
  'AppdIgnore is: ' + options.appdIgnore + ' ' +
119
124
  'DynamoDB call is:' + isDynamoDBReq + ' ' +
120
125
  'HTTPS call is:' + isRepeatForHttps + ' ' +
121
- 'isOtPath is :' + isOtPath);
126
+ 'isOtPath is :' + isOtPath + ' ' +
127
+ 'isDualMode is :' + isDualMode);
122
128
  } else {
123
129
  self.agent.logger.debug('Gatheing HTTP exit call information.');
124
130
  var threadId = self.agent.thread.current();
@@ -144,8 +150,8 @@ HttpExitProbe.prototype.attach = function (obj, moduleName) {
144
150
  var span = {};
145
151
  if (self.tracer) {
146
152
  const currentSpan = self.ot_api.trace.getSpan(self.ot_api.context.active());
147
- if(currentSpan) {
148
- var method = locals.opts.method ? locals.opts.method : 'GET';
153
+ if (currentSpan) {
154
+ var method = locals.opts.method ? locals.opts.method : 'GET';
149
155
  span = self.tracer.startSpan(method + ' ' + path, {
150
156
  kind: self.ot_api.SpanKind.CLIENT,
151
157
  attributes: HttpOTUtils.getOutgoingRequestAttributes(locals.opts, args[0].headers)
@@ -211,7 +217,7 @@ HttpExitProbe.prototype.attach = function (obj, moduleName) {
211
217
  function (obj, args, ret, locals) {
212
218
  var [input, options] = args;
213
219
 
214
- if (typeof(input) != 'string' && !(input instanceof url.URL)) {
220
+ if (typeof (input) != 'string' && !(input instanceof url.URL)) {
215
221
  options = input;
216
222
  input = null;
217
223
  }
@@ -245,7 +251,7 @@ HttpExitProbe.prototype.attach = function (obj, moduleName) {
245
251
  var ot_context = self.ot_api.context.active();
246
252
  if (correlationHeaderValue) {
247
253
  var baggage = self.ot_api.propagation.getBaggage(ot_context) || {};
248
- baggage[self.agent.correlation.HEADER_NAME] = {value: correlationHeaderValue};
254
+ baggage[self.agent.correlation.HEADER_NAME] = { value: correlationHeaderValue };
249
255
  ot_context = self.ot_api.propagation.setBaggage(ot_context, self.ot_api.propagation.createBaggage(baggage));
250
256
  }
251
257
 
@@ -321,3 +327,98 @@ HttpExitProbe.prototype.setHttpDefaults = function (locals, spec, opts, protocol
321
327
  || ((protocol === 'https') ? 443 : 80);
322
328
  locals.opts.path = locals.opts.path || '/';
323
329
  };
330
+
331
+
332
+ HttpExitProbe.prototype.instrumentFetch = function () {
333
+ const self = this;
334
+
335
+ const profiler = self.agent.profiler;
336
+ const proxy = self.agent.proxy;
337
+
338
+ proxy.around(
339
+ global,
340
+ ['fetch'],
341
+ function beforeFetch(_, args, locals) {
342
+ let [input, options = {}] = args;
343
+ const parsedUrl = typeof input === 'string' ? new url.URL(input) : input instanceof url.URL ? input : new url.URL(input.url);
344
+ const method = (options.method || 'GET').toUpperCase();
345
+
346
+ self.setHttpDefaults(locals, parsedUrl, args[1], parsedUrl.protocol === 'https:' ? 'https' : 'http');
347
+
348
+ locals.time = profiler.time();
349
+
350
+ self.agent.logger.debug('Instrumenting fetch request for endpoint: ' +
351
+ `${method} ${parsedUrl.hostname}:${parsedUrl.port || (parsedUrl.protocol === 'https:' ? 443 : 80)}${parsedUrl.pathname}`);
352
+ self.agent.metricsManager.addMetric(self.agent.metricsManager.HTTP_OUTGOING_COUNT, 1);
353
+
354
+ locals.exitCall = profiler.createExitCall(locals.time, {
355
+ exitType: 'EXIT_HTTP',
356
+ supportedProperties: {
357
+ 'HOST': locals.opts.hostname,
358
+ 'PORT': locals.opts.port,
359
+ 'URL': locals.opts.path,
360
+ },
361
+ stackTrace: profiler.stackTrace(),
362
+ group: method,
363
+ method,
364
+ command: `${locals.opts.hostname}:${locals.opts.port}${locals.opts.path}`,
365
+ category: ['POST', 'PUT'].includes(method) ? 'write' : 'read',
366
+ protocol: parsedUrl.protocol,
367
+ });
368
+
369
+ if (!locals.exitCall) return;
370
+
371
+ Error.captureStackTrace(locals.exitCall);
372
+
373
+ let correlationHeaderValue = undefined;
374
+ if (locals.exitCall) {
375
+ correlationHeaderValue = self.agent.backendConnector.getCorrelationHeader(locals.exitCall);
376
+ }
377
+
378
+ if ((typeof options === 'object' && options.headers == undefined)) {
379
+ options.headers = {};
380
+ }
381
+
382
+ if (correlationHeaderValue) {
383
+ args[1].headers = Object.assign(args[1].headers, {
384
+ [self.agent.correlation.HEADER_NAME]: correlationHeaderValue
385
+ });
386
+ }
387
+
388
+ return args;
389
+ },
390
+ function afterFetch(_, args, response, locals) {
391
+ if (!response || !response.data) {
392
+ return;
393
+ }
394
+
395
+ const res = response.data;
396
+ locals.res = res;
397
+
398
+ if (res.status < 200 || res.status >= 400) {
399
+ locals.error = new Error(`HTTP error! Status: ${res.status} - ${res.statusText}`);
400
+ }
401
+ self.finalizeClientCallback(profiler, locals);
402
+ return;
403
+ }
404
+ );
405
+ };
406
+
407
+ //replace the original function with this in the next commit after 24.12 release
408
+ HttpExitProbe.prototype.finalizeClientCallback = function (profiler, locals) {
409
+ if (!locals.time.done()) return;
410
+
411
+ var exitCall = locals.exitCall;
412
+ var error = locals.error;
413
+
414
+ if (exitCall) {
415
+ if (locals.res) {
416
+ exitCall.responseHeaders = locals.res.headers;
417
+ exitCall.statusCode = ~~locals.res.status || ~~locals.res.statusCode;
418
+ if ((!error) && ((exitCall.statusCode < 200) || (exitCall.statusCode >= 400))) {
419
+ error = HttpCommon.getHttpExitCallError(exitCall.statusCode, exitCall.stack, locals);
420
+ }
421
+ }
422
+ profiler.addExitCall(locals.time, exitCall, error);
423
+ }
424
+ };
@@ -33,6 +33,10 @@ HttpProbe.prototype.attach = function (obj, moduleName) {
33
33
  var self = this;
34
34
  var proxy = this.agent.proxy;
35
35
 
36
+ if(process.env.APPDYNAMICS_HTTP_PROBE_DISABLE == 'true' || process.env.APPDYNAMICS_HTTP_PROBE_DISABLE == true) {
37
+ return;
38
+ }
39
+
36
40
  if (obj.__appdynamicsProbeAttached__) return;
37
41
  obj.__appdynamicsProbeAttached__ = true;
38
42
 
@@ -47,7 +51,7 @@ HttpProbe.prototype.attach = function (obj, moduleName) {
47
51
  }
48
52
  });
49
53
  }
50
-
54
+
51
55
  if (moduleName === 'express-graphql') {
52
56
  if (self.agent.opts.enableGraphQL) {
53
57
  this.entryProbe.enableGraphQL(obj);
@@ -77,7 +81,11 @@ HttpProbe.prototype.attach = function (obj, moduleName) {
77
81
  this.entryProbe.enableGraphQLHttp(obj);
78
82
  }
79
83
  } else {
80
- this.entryProbe.attach(obj, moduleName);
81
- this.exitProbe.attach(obj, moduleName);
84
+ if(process.env.APPDYNAMICS_HTTP_ENTRY_PROBE_DISABLE != 'true' && process.env.APPDYNAMICS_HTTP_ENTRY_PROBE_DISABLE != true) {
85
+ this.entryProbe.attach(obj, moduleName);
86
+ }
87
+ if(process.env.APPDYNAMICS_HTTP_EXIT_PROBE_DISABLE != 'true' && process.env.APPDYNAMICS_HTTP_EXIT_PROBE_DISABLE != true) {
88
+ this.exitProbe.attach(obj, moduleName);
89
+ }
82
90
  }
83
91
  };
@@ -69,7 +69,7 @@ function buildEumCookie(agent, transaction, responseHeaders, request)
69
69
  {
70
70
  var response = {headers: responseHeaders,
71
71
  setHeader: function(key, value) { this.headers[key] = value; },
72
- getHeader: function(key) { this.headers[key]; }};
72
+ getHeader: function(key) { return this.headers[key]; }};
73
73
  var eumCookie = agent.eum.newEumCookie(transaction, request, response, request.headers[":scheme"] == 'https');
74
74
  eumCookie.build();
75
75
  }
@@ -33,6 +33,10 @@ exports.IoredisProbe = IoredisProbe;
33
33
  IoredisProbe.prototype.attach = function(obj) {
34
34
  var self = this;
35
35
 
36
+ if(process.env.APPDYNAMICS_IOREDIS_PROBE_DISABLE == true || process.env.APPDYNAMICS_IOREDIS_PROBE_DISABLE == 'true') {
37
+ return;
38
+ }
39
+
36
40
  if(obj.__appdynamicsProbeAttached__) return;
37
41
  obj.__appdynamicsProbeAttached__ = true;
38
42
  self.agent.on('destroy', function() {
@@ -47,6 +47,10 @@ exports.MemcachedProbe = MemcachedProbe;
47
47
  MemcachedProbe.prototype.attach = function(obj) {
48
48
  var self = this;
49
49
 
50
+ if(process.env.APPDYNAMICS_MEMCACHED_PROBE_DISABLE == true || process.env.APPDYNAMICS_MEMCACHED_PROBE_DISABLE == 'true') {
51
+ return;
52
+ }
53
+
50
54
  if(obj.__appdynamicsProbeAttached__) return;
51
55
  obj.__appdynamicsProbeAttached__ = true;
52
56
  self.agent.on('destroy', function() {
@@ -21,6 +21,10 @@ MongodbProbe.prototype.attach = function (obj) {
21
21
  var profiler = self.agent.profiler;
22
22
  var mongoObj = obj;
23
23
 
24
+ if(process.env.APPDYNAMICS_MONGODB_PROBE_DISABLE == true || process.env.APPDYNAMICS_MONGODB_PROBE_DISABLE == 'true') {
25
+ return;
26
+ }
27
+
24
28
  if (obj.__appdynamicsProbeAttached__) return;
25
29
  obj.__appdynamicsProbeAttached__ = true;
26
30
 
@@ -148,7 +152,7 @@ MongodbProbe.prototype.attach = function (obj) {
148
152
  });
149
153
 
150
154
  supportedCommands.forEach(function (command) {
151
- proxy.before(obj.Collection.prototype, command, withAPMBeforeHandler);
155
+ proxy.before(obj.Collection.prototype, command, withAPMBeforeHandler);
152
156
  proxy.before(obj.Server.prototype, command, withAPMBeforeHandler);
153
157
  proxy.before(obj.ReplSet.prototype, command, withAPMBeforeHandler);
154
158
  });
@@ -283,7 +287,7 @@ MongodbProbe.prototype.attach = function (obj) {
283
287
  proxy.before(obj.MongoClient.prototype, 'connect', function(obj){
284
288
  obj.monitorCommands = true;
285
289
  var newServerPool;
286
- var newOpQueue = {};
290
+ var newOpQueue = new Map();
287
291
  var newApmCollectionEvents = ['create', 'drop'];
288
292
  var newCollectionCommandMap = {
289
293
  'create': 'createCollection',
@@ -306,13 +310,13 @@ MongodbProbe.prototype.attach = function (obj) {
306
310
  newServerPool = [event.address];
307
311
  }
308
312
  if (newServerPool) {
309
- if (!newOpQueue[requestId]) {
310
- newOpQueue[requestId] = {
313
+ if (!newOpQueue.has(requestId)) {
314
+ newOpQueue.set(requestId, {
311
315
  time: profiler.time(),
312
316
  serverPool: newServerPool
313
- };
317
+ });
314
318
  }
315
- newRequest = newOpQueue[requestId];
319
+ newRequest = newOpQueue.get(requestId);
316
320
  newCommandQuery = event.command.filter;
317
321
  if (event.command.filter && Object.prototype.toString.call(event.command.filter) == "[object Object]") {
318
322
  newCommandQuery = utility.filterSensitiveDataFromObject(utility.deepCopy(event.command.filter));
@@ -334,18 +338,18 @@ MongodbProbe.prototype.attach = function (obj) {
334
338
  });
335
339
 
336
340
  obj.on('commandSucceeded', function (event) {
337
- var requestId = event.requestId, newRequest = newOpQueue[requestId];
341
+ var requestId = event.requestId, newRequest = newOpQueue.get(requestId);
338
342
  if (newRequest) {
339
343
  self.addExitCall(newRequest.time, newRequest.exitCall);
340
- newOpQueue[requestId] = undefined;
344
+ newOpQueue.delete(requestId);
341
345
  }
342
346
  });
343
347
 
344
348
  obj.on('commandFailed', function (event) {
345
- var requestId = event.requestId, newRequest = newOpQueue[requestId];
349
+ var requestId = event.requestId, newRequest = newOpQueue.get(requestId);
346
350
  if (newRequest) {
347
351
  self.addExitCall(event.time, event.exitCall, event.failure);
348
- newOpQueue[requestId] = undefined;
352
+ newOpQueue.delete(requestId);
349
353
  }
350
354
  });
351
355
  });
@@ -18,6 +18,10 @@ MssqlProbe.prototype.attach = function(obj) {
18
18
  var proxy = self.agent.proxy;
19
19
  var profiler = self.agent.profiler;
20
20
 
21
+ if(process.env.APPDYNAMICS_MSSQL_PROBE_DISABLE == true || process.env.APPDYNAMICS_MSSQL_PROBE_DISABLE == 'true') {
22
+ return;
23
+ }
24
+
21
25
  if(obj.__appdynamicsProbeAttached__) return;
22
26
  obj.__appdynamicsProbeAttached__ = true;
23
27
  self.agent.on('destroy', function() {
@@ -102,6 +102,10 @@ MysqlProbe.prototype.attach = function(obj, name) {
102
102
  var cmds = ['createClient', 'createConnection', 'createPool'];
103
103
  var mysqlConnection;
104
104
 
105
+ if(process.env.APPDYNAMICS_MYSQL_PROBE_DISABLE == true || process.env.APPDYNAMICS_MYSQL_PROBE_DISABLE == 'true') {
106
+ return;
107
+ }
108
+
105
109
  if(obj.__appdynamicsProbeAttached__) return;
106
110
  obj.__appdynamicsProbeAttached__ = true;
107
111
  self.agent.on('destroy', function() {
@@ -19,6 +19,10 @@ exports.NetProbe = NetProbe;
19
19
  NetProbe.prototype.attach = function(obj) {
20
20
  var self = this;
21
21
 
22
+ if(process.env.APPDYNAMICS_NET_PROBE_DISABLE == true || process.env.APPDYNAMICS_NET_PROBE_DISABLE == 'true') {
23
+ return;
24
+ }
25
+
22
26
  if(obj.__appdynamicsProbeAttached__) return;
23
27
  obj.__appdynamicsProbeAttached__ = true;
24
28
  self.agent.on('destroy', function() {
@@ -20,6 +20,10 @@ NSolidProbe.prototype.attach = function(obj) {
20
20
  var agent = self.agent;
21
21
  self.nsolid = obj;
22
22
 
23
+ if(process.env.APPDYNAMICS_NSOLID_PROBE_DISABLE == true || process.env.APPDYNAMICS_NSOLID_PROBE_DISABLE == 'true') {
24
+ return;
25
+ }
26
+
23
27
  if (!agent.nsolidEnabled) return;
24
28
 
25
29
  if(obj.__appdynamicsProbeAttached__) return;
@@ -18,6 +18,10 @@ exports.PgProbe = PgProbe;
18
18
  PgProbe.prototype.attach = function(obj) {
19
19
  var self = this;
20
20
 
21
+ if(process.env.APPDYNAMICS_PG_PROBE_DISABLE == true || process.env.APPDYNAMICS_PG_PROBE_DISABLE == 'true') {
22
+ return;
23
+ }
24
+
21
25
  if(obj.__appdynamicsProbeAttached__) return;
22
26
  obj.__appdynamicsProbeAttached__ = true;
23
27
  self.agent.on('destroy', function() {
@@ -17,6 +17,10 @@ ProcessProbe.prototype.attach = function(obj) {
17
17
  var proxy = this.agent.proxy;
18
18
  var thread = this.agent.thread;
19
19
 
20
+ if(process.env.APPDYNAMICS_PROCESS_PROBE_DISABLE == true || process.env.APPDYNAMICS_PROCESS_PROBE_DISABLE == 'true') {
21
+ return;
22
+ }
23
+
20
24
  if(obj.__appdynamicsProbeAttached__) return;
21
25
  obj.__appdynamicsProbeAttached__ = true;
22
26
  this.agent.on('destroy', function() {
@@ -46,6 +46,11 @@ function proxyAttachCommands(self, originalObject) {
46
46
 
47
47
  RedisProbe.prototype.attachRelative = function(mod, args, obj) {
48
48
  var self = this;
49
+
50
+ if(process.env.APPDYNAMICS_REDIS_PROBE_DISABLE == true || process.env.APPDYNAMICS_REDIS_PROBE_DISABLE == 'true') {
51
+ return;
52
+ }
53
+
49
54
  if (args[0] == '../commander') {
50
55
  var parentMod = mod.filename.split('@');
51
56
  if (parentMod.length < 2
@@ -20,6 +20,10 @@ SocketioProbe.prototype.attach = function(obj) {
20
20
  var self = this;
21
21
  var socketIOServer;
22
22
 
23
+ if(process.env.APPDYNAMICS_SOCKETIO_PROBE_DISABLE == true || process.env.APPDYNAMICS_SOCKETIO_PROBE_DISABLE == 'true') {
24
+ return;
25
+ }
26
+
23
27
  if(obj.__appdynamicsProbeAttached__) return;
24
28
  obj.__appdynamicsProbeAttached__ = true;
25
29
  self.agent.on('destroy', function() {
@@ -11,6 +11,10 @@ TediousProbe.prototype.attach = function (obj) {
11
11
  if(obj.__appdynamicsProbeAttached__) return;
12
12
  obj.__appdynamicsProbeAttached__ = true;
13
13
 
14
+ if(process.env.APPDYNAMICS_TEDIOUS_PROBE_DISABLE == true || process.env.APPDYNAMICS_TEDIOUS_PROBE_DISABLE == 'true') {
15
+ return;
16
+ }
17
+
14
18
  let self = this;
15
19
  self.agent.on('destroy', function() {
16
20
  if(obj.__appdynamicsProbeAttached__) {
@@ -8,6 +8,11 @@ function WinstonProbe(agent) {
8
8
  WinstonProbe.prototype.init = function () {};
9
9
 
10
10
  WinstonProbe.prototype.attach = function (obj) {
11
+
12
+ if(process.env.APPDYNAMICS_WINSTON_PROBE_DISABLE == true || process.env.APPDYNAMICS_WINSTON_PROBE_DISABLE == 'true') {
13
+ return;
14
+ }
15
+
11
16
  if(obj.__appdynamicsProbeAttached__) return;
12
17
  obj.__appdynamicsProbeAttached__ = true;
13
18
  let self = this;
@@ -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++;
@@ -4,7 +4,7 @@ Copyright (c) AppDynamics, Inc., and its affiliates
4
4
  All Rights Reserved
5
5
  */
6
6
  function trim(str) {
7
- return str.replace(/^\s+|\s+$/g, '');
7
+ return str.trim();
8
8
  }
9
9
 
10
10
  function parseCookies(req) {
@@ -47,6 +47,10 @@ CpuProfiler.prototype.onAgentDestroy = function () {
47
47
  CpuProfiler.prototype.startCpuProfiler = function(seconds, callback, threadId) {
48
48
  var self = this;
49
49
 
50
+ if(process.env.APPDYNAMICS_CPU_PROFILER_DISABLED == 'true' || process.env.APPDYNAMICS_CPU_PROFILER_DISABLED == true) {
51
+ return callback("CPU Profiling Disabled.");
52
+ }
53
+
50
54
  if(!self.agent.appdNative) {
51
55
  return callback("V8 tools are not loaded.");
52
56
  }
@@ -15,6 +15,8 @@ exports.GCStats = GCStats;
15
15
 
16
16
  GCStats.prototype.init = function() {
17
17
  /* istanbul ignore next */
18
+ if(process.env.APPDYNAMICS_GC_STATS_DISABLED == 'true' || process.env.APPDYNAMICS_GC_STATS_DISABLED == true) return;
19
+
18
20
  if (!this.agent.appdNative) return;
19
21
 
20
22
  var mm = this.agent.metricsManager;
@@ -32,6 +32,10 @@ HeapProfiler.prototype.isObjectTrackingSupported = function() {
32
32
  HeapProfiler.prototype.trackAllocations = function(duration, callback) {
33
33
  var self = this;
34
34
 
35
+ if(process.env.APPDYNAMICS_HEAP_PROFILER_DISABLED == 'true' || process.env.APPDYNAMICS_HEAP_PROFILER_DISABLED == true) {
36
+ return callback("Heap Profiling Disabled.");
37
+ }
38
+
35
39
  if(!self.agent.appdNative) {
36
40
  return callback("V8 tools are not loaded.");
37
41
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appdynamics",
3
- "version": "24.10.0",
3
+ "version": "25.5.7",
4
4
  "description": "Performance Profiler and Monitor",
5
5
  "author": "AppDynamics, Inc.",
6
6
  "homepage": "https://www.appdynamics.com",
@@ -34,26 +34,20 @@
34
34
  "n": "^6.8.0"
35
35
  },
36
36
  "dependencies": {
37
- "@opentelemetry/api": "~1.4.1",
38
- "@opentelemetry/api-logs": "^0.45.1",
39
- "@opentelemetry/context-async-hooks": "~1.10.1",
40
- "@opentelemetry/core": "~1.10.1",
41
- "@opentelemetry/exporter-logs-otlp-grpc": "^0.45.1",
42
- "@opentelemetry/exporter-logs-otlp-proto": "^0.45.1",
43
- "@opentelemetry/exporter-trace-otlp-proto": "^0.36.1",
44
- "@opentelemetry/resources": "~1.10.1",
45
- "@opentelemetry/sdk-logs": "^0.45.1",
46
- "@opentelemetry/sdk-trace-base": "~1.10.1",
47
- "@opentelemetry/semantic-conventions": "~1.10.1",
37
+ "@opentelemetry/api": "^1.8.0",
38
+ "@opentelemetry/core": "^1.3.0",
39
+ "@opentelemetry/exporter-logs-otlp-http": "^0.57.0",
40
+ "@opentelemetry/exporter-logs-otlp-proto": "^0.57.0",
41
+ "@opentelemetry/api-logs": "^0.57.0",
48
42
  "@yarnpkg/lockfile": "^1.1.0",
49
43
  "body-parser": "^1.20.3",
50
44
  "cls-hooked": "4.2.2",
51
45
  "https-proxy-agent": "^5.0.1",
52
46
  "uuid": "^8.3.2",
53
47
  "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"
48
+ "appdynamics-libagent-napi": "https://cdn.appdynamics.com/packages/nodejs/25.5.7.0/appdynamics-libagent-napi-node.tgz",
49
+ "appdynamics-native": "https://cdn.appdynamics.com/packages/nodejs/25.5.7.0/appdynamics-native-node.tgz",
50
+ "appdynamics-protobuf": "https://cdn.appdynamics.com/packages/nodejs/25.5.7.0/appdynamics-protobuf-node.tgz"
57
51
  },
58
52
  "overrides": {
59
53
  "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": "25.5.7",
4
4
  "description": "Performance Profiler and Monitor",
5
5
  "author": "AppDynamics, Inc.",
6
6
  "homepage": "https://www.appdynamics.com",
@@ -34,26 +34,20 @@
34
34
  "n": "^6.8.0"
35
35
  },
36
36
  "dependencies": {
37
- "@opentelemetry/api": "~1.4.1",
38
- "@opentelemetry/api-logs": "^0.45.1",
39
- "@opentelemetry/context-async-hooks": "~1.10.1",
40
- "@opentelemetry/core": "~1.10.1",
41
- "@opentelemetry/exporter-logs-otlp-grpc": "^0.45.1",
42
- "@opentelemetry/exporter-logs-otlp-proto": "^0.45.1",
43
- "@opentelemetry/exporter-trace-otlp-proto": "^0.36.1",
44
- "@opentelemetry/resources": "~1.10.1",
45
- "@opentelemetry/sdk-logs": "^0.45.1",
46
- "@opentelemetry/sdk-trace-base": "~1.10.1",
47
- "@opentelemetry/semantic-conventions": "~1.10.1",
37
+ "@opentelemetry/api": "^1.8.0",
38
+ "@opentelemetry/core": "^1.3.0",
39
+ "@opentelemetry/exporter-logs-otlp-http": "^0.57.0",
40
+ "@opentelemetry/exporter-logs-otlp-proto": "^0.57.0",
41
+ "@opentelemetry/api-logs": "^0.57.0",
48
42
  "@yarnpkg/lockfile": "^1.1.0",
49
43
  "body-parser": "^1.20.3",
50
44
  "cls-hooked": "4.2.2",
51
45
  "https-proxy-agent": "^5.0.1",
52
46
  "uuid": "^8.3.2",
53
47
  "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"
48
+ "appdynamics-libagent-napi": "https://cdn.appdynamics.com/packages/nodejs/25.5.7.0/appdynamics-libagent-napi-node.tgz",
49
+ "appdynamics-native": "https://cdn.appdynamics.com/packages/nodejs/25.5.7.0/appdynamics-native-node.tgz",
50
+ "appdynamics-protobuf": "https://cdn.appdynamics.com/packages/nodejs/25.5.7.0/appdynamics-protobuf-node.tgz"
57
51
  },
58
52
  "overrides": {
59
53
  "semver": "7.5.4"