appdynamics 21.6.0 → 22.2.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.
Files changed (53) hide show
  1. package/README.md +1 -1
  2. package/appdynamics_version.json +2 -2
  3. package/lib/core/agent.js +21 -44
  4. package/lib/core/appDProxy.js +12 -12
  5. package/lib/core/logger.js +27 -79
  6. package/lib/core/opentelemetry-tracer.js +70 -0
  7. package/lib/libagent/libagent-connector.js +5 -47
  8. package/lib/libagent/libagent.js +2 -3
  9. package/lib/libagent/transaction-sender.js +15 -16
  10. package/lib/libagent/transactions/transaction-reporter.js +0 -5
  11. package/lib/{libagent/metrics → metrics}/metric.js +4 -1
  12. package/lib/metrics/metrics-manager.js +4 -3
  13. package/lib/probes/apollo-entry-probe.js +69 -0
  14. package/lib/probes/cluster-probe.js +1 -1
  15. package/lib/probes/couchbase-probe.js +19 -0
  16. package/lib/probes/grpc-exit-probe.js +1 -1
  17. package/lib/probes/http-common.js +97 -0
  18. package/lib/probes/http-entry-probe.js +42 -122
  19. package/lib/probes/http-exit-probe.js +112 -48
  20. package/lib/probes/http-ot-utils.js +113 -0
  21. package/lib/probes/http-probe.js +14 -7
  22. package/lib/probes/http2-entry-probe.js +1 -7
  23. package/lib/probes/http2-exit-probe.js +4 -7
  24. package/lib/probes/ioredis-probe.js +2 -2
  25. package/lib/probes/mongodb-probe.js +199 -112
  26. package/lib/probes/rabbitmq-entry-probe.js +184 -0
  27. package/lib/probes/rabbitmq-exit-probe.js +108 -0
  28. package/lib/probes/rabbitmq-probe.js +76 -0
  29. package/lib/process/process-scanner.js +2 -2
  30. package/lib/profiler/profiler.js +6 -2
  31. package/lib/profiler/time-promise.js +0 -3
  32. package/lib/proxy/protobuf-model.js +0 -264
  33. package/lib/transactions/correlation.js +1 -20
  34. package/lib/transactions/eum.js +2 -34
  35. package/lib/utility.js +20 -1
  36. package/package.json +13 -12
  37. package/packageBck.json +13 -12
  38. package/lib/libproxy/instance-info-sender.js +0 -41
  39. package/lib/libproxy/libproxy.js +0 -204
  40. package/lib/libproxy/metric.js +0 -109
  41. package/lib/libproxy/proxy-launcher.js +0 -308
  42. package/lib/libproxy/proxy-transport.js +0 -634
  43. package/lib/libproxy/transaction-reporter.js +0 -168
  44. package/lib/proxy/backend-config.js +0 -488
  45. package/lib/transactions/analytics-reporter.js +0 -187
  46. package/lib/transactions/config-manager.js +0 -87
  47. package/lib/transactions/correlation-header.js +0 -495
  48. package/lib/transactions/data-collectors.js +0 -95
  49. package/lib/transactions/sep-config.js +0 -66
  50. package/lib/transactions/transaction-naming.js +0 -231
  51. package/lib/transactions/transaction-registry.js +0 -156
  52. package/lib/transactions/transaction-rules.js +0 -173
  53. package/postInstallScript.js +0 -33
@@ -6,6 +6,7 @@ All Rights Reserved
6
6
  'use strict';
7
7
 
8
8
  var EventLoopMetrics = require('./eventloop').EventLoopMetrics;
9
+ var Metric = require('./metric').Metric;
9
10
 
10
11
  /*
11
12
  * MetricsManager manages metric lifecycle, i.e. keeps list
@@ -476,16 +477,16 @@ MetricsManager.prototype.createMetric = function (definition, isCustom) {
476
477
 
477
478
  if (this.metrics.length == 5000) {
478
479
  self.agent.logger.warn('too many metrics, ignoring metric');
479
- return new self.agent.Metric(self.agent, definition, isCustom);
480
+ return new Metric(self.agent, definition, isCustom);
480
481
  }
481
482
 
482
483
  var path = definition.path;
483
484
  if (!self.validatePath(path)) {
484
485
  self.agent.logger.warn('metric parameter(s) missing or invalid, ignoring metric');
485
- return new self.agent.Metric(self.agent, definition, isCustom); // dummy metric
486
+ return new Metric(self.agent, definition, isCustom); // dummy metric
486
487
  }
487
488
 
488
- metric = new self.agent.Metric(self.agent, definition, isCustom);
489
+ metric = new Metric(self.agent, definition, isCustom);
489
490
  self.metrics.push(metric);
490
491
  self.metricMap[definition.path] = metric;
491
492
 
@@ -0,0 +1,69 @@
1
+ /*
2
+ This is for apollo-server entry probe
3
+ */
4
+
5
+ let HttpCommon = require("./http-common");
6
+
7
+ exports.ApolloEntryProbe = ApolloEntryProbe;
8
+
9
+ function ApolloEntryProbe(agent) {
10
+ this.agent = agent;
11
+ }
12
+
13
+ ApolloEntryProbe.prototype.init = function () {};
14
+
15
+ ApolloEntryProbe.prototype.attach = function (obj) {
16
+ let self = this;
17
+ self.agent.proxy.before(
18
+ obj.ApolloServer.prototype,
19
+ "createServerInfo",
20
+ (args) => this.addLifeCycleHooks(args)
21
+ );
22
+ };
23
+
24
+ ApolloEntryProbe.prototype.addLifeCycleHooks = function (obj) {
25
+ let self = this;
26
+ let userDefinedContext = obj.context;
27
+ obj.context = function ({ req, res }) {
28
+ let userCtx;
29
+ if (userDefinedContext instanceof Function) {
30
+ userCtx = userDefinedContext.call(this, ...arguments);
31
+ } else if (userDefinedContext instanceof Object) {
32
+ userDefinedContext.gqlReq = req;
33
+ userDefinedContext.gqlRes = res;
34
+ return userDefinedContext;
35
+ }
36
+ return Object.assign({ gqlReq: req, gqlRes: res }, userCtx);
37
+ };
38
+
39
+ obj.plugins = [
40
+ {
41
+ requestDidStart() {
42
+ return {
43
+ didResolveOperation(response) {
44
+ response.context.gqlReq.graphqlop = response.operationName;
45
+ response.context.gqlReq.transactionStarted = true;
46
+ HttpCommon.startTransactionHandler(
47
+ response.context.gqlReq,
48
+ response.context.gqlRes,
49
+ self.agent
50
+ );
51
+ },
52
+
53
+ didEncounterErrors(response) {
54
+ response.context.gqlRes.error = response.errors[0];
55
+ if(response.context.gqlReq.transactionStarted) {
56
+ return;
57
+ }
58
+ HttpCommon.startTransactionHandler(
59
+ response.context.gqlReq,
60
+ response.context.gqlRes,
61
+ self.agent
62
+ );
63
+ },
64
+ };
65
+ },
66
+ },
67
+ ...obj.plugins,
68
+ ];
69
+ };
@@ -77,7 +77,7 @@ ClusterProbe.prototype.attach = function(obj) {
77
77
  }
78
78
 
79
79
  function writeIndexPid() {
80
- fs.writeFile(indexDir + '/' + freeIndex + '.pid', ret.process.pid, function(err) {
80
+ fs.writeFile(indexDir + '/' + freeIndex + '.pid', String(ret.process.pid), function(err) {
81
81
  if(err) return self.agent.logger.error(err);
82
82
  });
83
83
  }
@@ -64,6 +64,25 @@ CouchBaseProbe.prototype.attach = function(obj) {
64
64
  after
65
65
  );
66
66
  }
67
+
68
+ // driver 3.x Cluster prototype
69
+ proxy.around(obj.Cluster.prototype, 'query',
70
+ function(obj, args, locals) {
71
+ locals.time = self.agent.profiler.time();
72
+ locals.methodHasCb = proxy.callback(args, -1, function() {}, null, self.agent.thread.current());
73
+
74
+ var addresses;
75
+ var bucketName = Object.keys(obj._conns);
76
+ addresses = obj._connStr || '';
77
+ addresses = (addresses.match(/(?:.*:\/\/)?([^/?]+)/)[1] || '').split(',');
78
+
79
+ var command = 'query';
80
+ var commandArgs = args;
81
+
82
+ self.createExitCall(bucketName, addresses, command, commandArgs, locals);
83
+ },
84
+ after
85
+ );
67
86
  } else {
68
87
  // driver 2.x
69
88
  proxy.around(obj.Cluster.prototype, 'openBucket', function(obj, args, locals) {
@@ -121,7 +121,7 @@ GrpcExitProbe.prototype.injectCorrelationHeader = function(args, type, corrHeade
121
121
  var metadataIndex = args.findIndex((arg) => {
122
122
  return (arg &&
123
123
  typeof arg === 'object' &&
124
- arg._internal_repr &&
124
+ arg.internalRepr &&
125
125
  typeof arg.getMap === 'function'
126
126
  );
127
127
  });
@@ -4,10 +4,14 @@ Copyright (c) AppDynamics, Inc., and its affiliates
4
4
  All Rights Reserved
5
5
  */
6
6
  'use strict';
7
+ var HttpOTUtils = require('./http-ot-utils.js');
7
8
 
8
9
  module.exports.getHttpStatusCodeConfig = getHttpStatusCodeConfig;
9
10
  module.exports.generateError = generateError;
10
11
  module.exports.getHttpExitCallError = getHttpExitCallError;
12
+ module.exports.finalizeTransaction = finalizeTransaction;
13
+ module.exports.startTransactionHandler = startTransactionHandler;
14
+
11
15
 
12
16
  function getHttpStatusCodeConfig(statusCode, statusCodesConfig) {
13
17
  if (!statusCodesConfig) {
@@ -61,3 +65,96 @@ function getHttpExitCallError(statusCode, stack, locals) {
61
65
  stack: stack};
62
66
  return error;
63
67
  }
68
+
69
+
70
+ function finalizeTransaction (err, profiler, time, transaction, req, res, span) {
71
+ if (!time.done()) return;
72
+
73
+ transaction.error = transaction.error || res.error || err;
74
+ transaction.statusCode = transaction.statusCode ||
75
+ (transaction.error && transaction.error.statusCode) ||
76
+ (res && res.statusCode) ||
77
+ 500;
78
+ transaction.stackTrace = transaction.stackTrace || profiler.formatStackTrace(transaction.error);
79
+
80
+ var error = generateError(transaction.error, transaction.statusCode);
81
+ if (error) {
82
+ transaction.error = error;
83
+ }
84
+
85
+ if (transaction.api && transaction.api.onResponseComplete) {
86
+ transaction.api.onResponseComplete.apply(transaction.api, [req, res]);
87
+ }
88
+
89
+ if (span) {
90
+ span.setAttributes(HttpOTUtils.getIncomingRequestAttributesOnResponse(res));
91
+ span.setStatus(HttpOTUtils.parseResponseStatus(res));
92
+ span.end();
93
+ }
94
+
95
+ profiler.endTransaction(time, transaction);
96
+ }
97
+
98
+ function startTransactionHandler(req, res, agent, isHTTPs, tracer, ot_api) {
99
+ var profiler = agent.profiler;
100
+ var proxy = agent.proxy;
101
+ var time = profiler.time(true);
102
+
103
+ agent.metricsManager.addMetric(
104
+ agent.metricsManager.HTTP_INCOMING_COUNT,
105
+ 1
106
+ );
107
+
108
+ var span = undefined;
109
+ var baggageCorrHeader = undefined;
110
+ var otContext = undefined;
111
+
112
+ if (tracer) {
113
+ otContext = ot_api.propagation.extract(agent.TracerProvider.ot_api.ROOT_CONTEXT, req.headers);
114
+ var baggage = ot_api.propagation.getBaggage(otContext);
115
+ if (baggage && baggage.getEntry(agent.correlation.HEADER_NAME)) {
116
+ baggageCorrHeader = baggage.getEntry(agent.correlation.HEADER_NAME).value;
117
+ }
118
+ }
119
+
120
+ var transaction = profiler.startTransaction(time, req, "NODEJS_WEB", baggageCorrHeader);
121
+
122
+ if (tracer) {
123
+ ot_api.context.with(otContext, () => {
124
+ span = tracer.startSpan(transaction.name, {
125
+ kind: ot_api.SpanKind.SERVER,
126
+ attributes: HttpOTUtils.getIncomingRequestAttributes(req)
127
+ });
128
+ });
129
+ }
130
+
131
+ agent.context.set("threadId", transaction.threadId);
132
+ req.__appdThreadId = transaction.threadId;
133
+
134
+ transaction.url = req.url;
135
+ transaction.method = req.method;
136
+ transaction.requestHeaders = req.headers;
137
+
138
+ var eumEnabled = transaction.eumEnabled && !transaction.skip;
139
+
140
+ if (!transaction.corrHeader && eumEnabled) {
141
+ proxy.before(res, "writeHead", function (obj) {
142
+ if (!transaction.isFinished) {
143
+ var eumCookie = agent.eum.newEumCookie(
144
+ transaction,
145
+ req,
146
+ obj,
147
+ isHTTPs
148
+ );
149
+ eumCookie.build();
150
+ }
151
+ });
152
+ }
153
+
154
+ proxy.after(res, "end", function () {
155
+ finalizeTransaction(null, profiler, time, transaction, req, res, span);
156
+ transaction = null;
157
+ });
158
+
159
+ return { transaction, span, otContext };
160
+ }
@@ -3,27 +3,19 @@ Copyright (c) AppDynamics, Inc., and its affiliates
3
3
  2015
4
4
  All Rights Reserved
5
5
  */
6
- 'use strict';
6
+ "use strict";
7
7
 
8
- var HttpCommon = require('./http-common');
8
+ var utility = require("../utility");
9
+ var HttpCommon = require("./http-common");
9
10
  var getGraphQLParams;
10
11
 
11
12
  function HttpEntryProbe(agent) {
12
13
  this.agent = agent;
13
-
14
- this.statusCodesConfig = undefined;
15
- this.delayedCallbackQueue = [];
16
14
  }
17
15
 
18
16
  exports.HttpEntryProbe = HttpEntryProbe;
19
17
 
20
- HttpEntryProbe.prototype.init = function () {
21
- var self = this;
22
-
23
- self.agent.on('configUpdated', function () {
24
- self.statusCodesConfig = self.agent.configManager.getConfigValue('errorConfig.httpStatusCodes');
25
- });
26
- };
18
+ HttpEntryProbe.prototype.init = function () {};
27
19
 
28
20
  HttpEntryProbe.prototype.enableGraphQL = function (egql) {
29
21
  getGraphQLParams = egql.getGraphQLParams;
@@ -32,18 +24,12 @@ HttpEntryProbe.prototype.enableGraphQL = function (egql) {
32
24
  HttpEntryProbe.prototype.attach = function (obj, moduleName) {
33
25
  var self = this;
34
26
 
35
- self.agent.timers.startTimer(100, true, function () {
36
- var now = Date.now();
27
+ self.agent.timers.startTimer(100, true, function () {});
37
28
 
38
- while (self.delayedCallbackQueue.length > 0) {
39
- if (self.delayedCallbackQueue[0].ts < now - 10) {
40
- var delayedCallbackInfo = self.delayedCallbackQueue.shift();
41
- delayedCallbackInfo.func.call(this);
42
- } else {
43
- break;
44
- }
45
- }
46
- });
29
+ if (self.agent.tracer) {
30
+ self.ot_api = self.agent.TracerProvider.ot_api;
31
+ self.tracer = self.agent.tracer;
32
+ }
47
33
 
48
34
  self.isHTTPs = obj.Agent && (obj.Agent.prototype.defaultPort == 443);
49
35
 
@@ -60,59 +46,16 @@ HttpEntryProbe.prototype.attach = function (obj, moduleName) {
60
46
  });
61
47
  };
62
48
 
63
- HttpEntryProbe.prototype.finalizeTransaction = function (err, profiler, time, transaction, req, res) {
64
- if (!time.done()) return;
65
-
66
- transaction.error = transaction.error || res.error || err;
67
- transaction.statusCode = transaction.statusCode ||
68
- (transaction.error && transaction.error.statusCode) ||
69
- (res && res.statusCode) ||
70
- 500;
71
- transaction.stackTrace = transaction.stackTrace || profiler.formatStackTrace(transaction.error);
72
-
73
- var error = HttpCommon.generateError(transaction.error, transaction.statusCode, this.statusCodesConfig);
74
- if (error) {
75
- transaction.error = error;
76
- }
77
-
78
- if (transaction.api && transaction.api.onResponseComplete) {
79
- transaction.api.onResponseComplete.apply(transaction.api, [req, res]);
80
- }
81
- profiler.endTransaction(time, transaction);
82
- };
83
-
84
- function createBTCallback(agent, profiler, time, transaction, req, res, thread, callback, self, origSelf, origArgs) {
85
- var didRun = false;
86
- var threadId = thread.current();
87
-
88
- // Node 0.8: need to ensure request isn't consumed
89
- // before delayed handler gets run
90
- if (agent.processInfo.isv0_8) {
91
- req.pause();
49
+ function invokeOriginal(callback, self, args, ot_api, span, otCtx, req, res) {
50
+ if (ot_api) {
51
+ ot_api.context.with(ot_api.trace.setSpan(otCtx, span), () => {
52
+ ot_api.context.bind(ot_api.context.active(), req);
53
+ ot_api.context.bind(ot_api.context.active(), res);
54
+ return callback.apply(self, args);
55
+ });
56
+ } else {
57
+ return callback.apply(self, args);
92
58
  }
93
-
94
- return self.agent.context.bind(function () {
95
- if (didRun) return;
96
- didRun = true;
97
-
98
- // Node 0.8: safe to resume the request now
99
- // we're ready to process it
100
- if (agent.processInfo.isv0_8) {
101
- req.resume();
102
- }
103
-
104
- var oldThreadId = thread.current();
105
- thread.resume(threadId);
106
- try {
107
- callback = agent.proxy.wrapWithThreadProxyIfEnabled(callback);
108
- callback.apply(origSelf, origArgs);
109
- } catch (e) {
110
- self.finalizeTransaction(e, profiler, time, transaction, req, res);
111
- throw e;
112
- } finally {
113
- thread.resume(oldThreadId);
114
- }
115
- });
116
59
  }
117
60
 
118
61
  HttpEntryProbe.prototype.__createRequestHandler = function (callback, isHTTPs) {
@@ -129,66 +72,43 @@ HttpEntryProbe.prototype.__createRequestHandler = function (callback, isHTTPs) {
129
72
  self.agent.context.run(requestHandler, req, res);
130
73
  });
131
74
  } else {
132
- self.agent.context.run(requestHandler, req, res);
75
+ if (
76
+ self.agent.opts.enableGraphQL
77
+ && self.agent.libagentConnector.getBusinessTransactionQueryType(
78
+ "NODEJS_WEB",
79
+ utility.createBtNamingWrapper(req)
80
+ ) == utility.constants.GRAPHQL_QUERY_TYPE
81
+ ) {
82
+ self.agent.context.run(callback, req, res);
83
+ } else {
84
+ self.agent.context.run(requestHandler, req, res);
85
+ }
133
86
  }
134
87
  };
135
88
 
136
89
  function requestHandler(req, res) {
137
- var profiler = self.agent.profiler;
138
- var proxy = self.agent.proxy;
139
- var time = profiler.time(true);
90
+ let profiler = self.agent.profiler;
91
+ let time = profiler.time(true);
140
92
 
141
93
  self.agent.metricsManager.addMetric(self.agent.metricsManager.HTTP_INCOMING_COUNT, 1);
142
94
 
143
- var transaction = profiler.startTransaction(time, req, 'NODEJS_WEB');
144
- self.agent.context.set('threadId', transaction.threadId);
145
- req.__appdThreadId = transaction.threadId;
146
-
147
- transaction.url = req.url;
148
- transaction.method = req.method;
149
- transaction.requestHeaders = req.headers;
95
+ let { transaction, span, otContext } = HttpCommon.startTransactionHandler(req, res, self.agent, isHTTPs, self.tracer, self.ot_api);
150
96
 
151
- var eumEnabled = (transaction.eumEnabled && !transaction.skip) || (self.agent.eum.enabled && self.agent.eum.enabledForTransaction(req));
97
+ var threadId = transaction.threadId;
98
+ self.agent.context.run(() => {
99
+
100
+ var oldThreadId = self.agent.thread.current();
101
+ self.agent.thread.resume(threadId);
152
102
 
153
- if (!transaction.corrHeader && eumEnabled) {
154
- proxy.before(res, 'writeHead', function (obj) {
155
- if (!transaction.isFinished) {
156
- var eumCookie = self.agent.eum.newEumCookie(transaction, req, obj, isHTTPs);
157
- eumCookie.build();
158
- }
159
- });
160
- }
161
-
162
- proxy.after(res, 'end', function () {
163
- self.finalizeTransaction(null, profiler, time, transaction, req, res);
164
- transaction = null;
165
- });
166
-
167
- if (self.agent.opts.btEntryPointDelayDisabled) {
168
103
  try {
169
- let threadProxyWrappedCb = self.agent.proxy.wrapWithThreadProxyIfEnabled(callback);
170
- return threadProxyWrappedCb.apply(this, arguments);
104
+ return invokeOriginal(callback, this, arguments, self.ot_api, span, otContext, req, res);
171
105
  } catch (e) {
172
- self.finalizeTransaction(e, profiler, time, transaction, req, res);
106
+ HttpCommon.finalizeTransaction(e, profiler, time, transaction, req, res, span);
173
107
  transaction = null;
174
108
  throw e;
109
+ } finally {
110
+ self.agent.thread.resume(oldThreadId);
175
111
  }
176
- }
177
-
178
- var delayedCallback = createBTCallback(self.agent,
179
- profiler,
180
- time,
181
- transaction,
182
- req, res,
183
- self.agent.thread,
184
- callback,
185
- self,
186
- this,
187
- arguments);
188
-
189
- transaction.once('ignoreTransactionCbExecute', delayedCallback);
190
- transaction.emit('delayedCallbackReady');
191
- transaction.once('btInfoResponse', delayedCallback);
192
- self.delayedCallbackQueue.push({ ts: Date.now(), func: delayedCallback });
112
+ });
193
113
  }
194
114
  };