appdynamics 21.9.0 → 22.5.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": "21.9.0.0",
2
+ "version": "22.5.0.0",
3
3
  "sha": "",
4
4
  "nodeVersion": "",
5
- "buildName": "8012",
5
+ "buildName": "8617",
6
6
  "compatibilityVersion": "4.4.1.0"
7
7
  }
package/lib/core/agent.js CHANGED
@@ -34,6 +34,7 @@ var CpuProfiler = require('../v8/cpu-profiler').CpuProfiler;
34
34
  var HeapProfiler = require('../v8/heap-profiler').HeapProfiler;
35
35
  var agentVersion = require('../../appdynamics_version.json');
36
36
  var appDNativeLoader = require('appdynamics-native');
37
+ var SecureApp = require('../secure_app/secure_app').SecureApp;
37
38
 
38
39
  var LibAgent = require('../libagent/libagent').LibAgent;
39
40
  var LibagentConnector = require('../libagent/libagent-connector').LibagentConnector;
@@ -88,6 +89,7 @@ function Agent() {
88
89
  this.gcStats = new GCStats(this);
89
90
  this.cpuProfiler = new CpuProfiler(this);
90
91
  this.heapProfiler = new HeapProfiler(this);
92
+ this.secureApp = new SecureApp(this);
91
93
 
92
94
  this.libagent = null;
93
95
 
@@ -177,6 +179,16 @@ Agent.prototype.init = function (opts) {
177
179
 
178
180
  self.backendConnector = new LibAgent(this);
179
181
 
182
+ if (opts.openTelemetry && opts.openTelemetry.enabled) {
183
+ var TracerProvider = require('./opentelemetry-tracer');
184
+ self.TracerProvider = new TracerProvider(self.logger);
185
+ if (!self.TracerProvider.register(opts)) {
186
+ self.logger.error('AppDynamics agent cannot be started: Tracer Provider registration has failed');
187
+ return;
188
+ }
189
+ self.tracer = self.TracerProvider.getTracer('appdynamics-tracer');
190
+ }
191
+
180
192
  self.precompiled = opts.precompiled === undefined || opts.precompiled;
181
193
 
182
194
  if (self.opts.excludeAgentFromCallGraph === undefined) {
@@ -272,6 +284,10 @@ Agent.prototype.init = function (opts) {
272
284
  self.cpuProfiler.init();
273
285
  self.heapProfiler.init();
274
286
 
287
+ if(self.opts.secureAppEnabled) {
288
+ self.secureApp.init(this);
289
+ }
290
+
275
291
  // Initialize libagent
276
292
  self.backendConnector.intializeAgentHelpers();
277
293
 
@@ -332,6 +348,12 @@ Agent.prototype.initializeOpts = function (opts) {
332
348
  if (self.opts.nodeName === undefined) {
333
349
  self.opts.nodeName = process.env.APPDYNAMICS_AGENT_NODE_NAME;
334
350
  }
351
+ if (self.opts.reuseNode === undefined) {
352
+ self.opts.reuseNode = process.env.APPDYNAMICS_AGENT_REUSE_NODE_NAME;
353
+ }
354
+ if (self.opts.reuseNodePrefix === undefined) {
355
+ self.opts.reuseNodePrefix = process.env.APPDYNAMICS_AGENT_REUSE_NODE_NAME_PREFIX;
356
+ }
335
357
  if (self.opts.analyticsMaxSegmentSizeInBytes === undefined && process.env.APPDYNAMICS_ANALYTICS_MAX_SEGMENT_SIZE) {
336
358
  self.opts.analyticsMaxSegmentSizeInBytes = parseInt(process.env.APPDYNAMICS_ANALYTICS_MAX_SEGMENT_SIZE, 10);
337
359
  }
@@ -217,7 +217,7 @@ AppDProxy.prototype.before = function(obj, meths, hook, isCallbackHook, copyAllP
217
217
  var beforeExecLogic = function() {
218
218
  var currentCtxt = self.agent.thread.current();
219
219
  try {
220
- var args = arguments;
220
+ var args = [...arguments];
221
221
  var methsInvocationCtxtLocal = methsInvocationCtxt;
222
222
  if (methsInvocationCtxtLocal)
223
223
  self.agent.thread.resume(methsInvocationCtxtLocal);
@@ -225,19 +225,19 @@ AppDProxy.prototype.before = function(obj, meths, hook, isCallbackHook, copyAllP
225
225
  var selfProxy = this;
226
226
 
227
227
  // the hook code should contain try/catch
228
- args = hook(this, arguments, function() {
229
- return orig.apply(selfProxy, args || arguments);
230
- });
228
+ args = hook(this, args, function() {
229
+ return orig.apply(selfProxy, args);
230
+ }) || args;
231
231
  }
232
232
  else {
233
233
  try {
234
- args = hook(this, arguments);
234
+ args = hook(this, args) || args;
235
235
  }
236
236
  catch (e) {
237
237
  self.logError(e);
238
238
  }
239
239
 
240
- var retValue = orig.apply(this, args || arguments);
240
+ var retValue = orig.apply(this, args);
241
241
  return retValue;
242
242
  }
243
243
  } finally {
@@ -277,7 +277,7 @@ AppDProxy.prototype.after = function(obj, meths, hook, copyAllProps, methsInvoca
277
277
 
278
278
  var hookRet;
279
279
  try {
280
- hookRet = hook(this, arguments, ret);
280
+ hookRet = hook(this, [...arguments], ret);
281
281
  }
282
282
  catch (e) {
283
283
  self.logError(e);
@@ -350,14 +350,14 @@ AppDProxy.prototype.around = function(obj, meths, hookBefore, hookAfter, copyAll
350
350
  defineProperty(obj, meth, function() {
351
351
  var currentCtxt = self.agent.thread.current();
352
352
  try {
353
- var args = arguments;
353
+ var args = [...arguments];
354
354
  var methsInvocationCtxtLocal = methsInvocationCtxt;
355
355
  if (methsInvocationCtxtLocal)
356
356
  self.agent.thread.resume(methsInvocationCtxtLocal);
357
357
  var locals = new Locals();
358
358
 
359
359
  try {
360
- args = hookBefore(this, arguments, locals);
360
+ args = hookBefore(this, args, locals) || args;
361
361
  }
362
362
  catch (e) {
363
363
  self.logError(e);
@@ -372,8 +372,8 @@ AppDProxy.prototype.around = function(obj, meths, hookBefore, hookAfter, copyAll
372
372
  }
373
373
  }
374
374
 
375
- var ret = orig.apply(this, args || arguments);
376
- var promiseRet = self.promise(ret, hookAfter, this, arguments, locals, methsInvocationCtxtLocal);
375
+ var ret = orig.apply(this, args);
376
+ var promiseRet = self.promise(ret, hookAfter, this, args, locals, methsInvocationCtxtLocal);
377
377
  if (promiseRet) {
378
378
  self.agent.thread.resume(currentCtxt);
379
379
  return promiseRet;
@@ -381,7 +381,7 @@ AppDProxy.prototype.around = function(obj, meths, hookBefore, hookAfter, copyAll
381
381
 
382
382
  var hookRet;
383
383
  try {
384
- hookRet = hookAfter(this, arguments, ret, locals);
384
+ hookRet = hookAfter(this, args, ret, locals);
385
385
  }
386
386
  catch (e) {
387
387
  self.logError(e);
@@ -5,9 +5,6 @@ All Rights Reserved
5
5
  */
6
6
  'use strict';
7
7
 
8
- var cluster = require('cluster');
9
- var log4js = require('log4js');
10
- var path = require('path');
11
8
 
12
9
 
13
10
  function isDebugEnabled(agent) {
@@ -50,94 +47,45 @@ function Logger(agent) {
50
47
  };
51
48
  }
52
49
  exports.Logger = Logger;
53
- Logger.sharedLogger = undefined; // (for unit tests)
54
-
55
50
 
56
51
  /* istanbul ignore next -- log4j mocked in unit tests */
57
- Logger.prototype.init = function (config, initializeBackend) {
52
+ Logger.prototype.init = function (config) {
58
53
  if (!config) {
59
54
  config = {};
60
55
  }
61
56
 
62
- if (initializeBackend && Logger.sharedLogger) {
63
- // work-around for unit tests to prevent too many loggers
64
- // being created, which kills output to stdout :-/
65
- this.logger = Logger.sharedLogger;
66
- } else {
67
- var dateString = new Date().toJSON();
68
- dateString = dateString.replace(/[-:]/g, "_").replace("T", "__").replace(/\..*$/, "");
69
- var logFileName = 'appd_node_agent_' + dateString + ".log";
70
- var rootPath = config.root_directory || this.agent.tmpDir;
71
- var baseName = config.filename || logFileName;
72
- // Libagent logFile is already created in the libagent. Since, there is no
73
- // way to tap on to the file name created by boost::log used by libagent
74
- // show the log filePath till agent tmpDir.
75
- var fileName = initializeBackend ? path.join(rootPath, baseName) : this.agent.tmpDir;
76
-
77
-
78
- var consoleOnly = (this.agent.opts.logging && this.agent.opts.logging.logfiles &&
79
- this.agent.opts.logging.logfiles.every(function (lf) {
80
- return lf.outputType == 'console';
81
- }));
82
-
83
- // If console logging env variable is set and no custom logging config is provided
84
- // then don't create temp path for logs
85
- if (process.env.APPDYNAMICS_LOGGER_OUTPUT_TYPE === "console" && (!config.logfiles || config.logfiles.length == 0)) {
86
- consoleOnly = true;
87
- }
57
+ var rootPath = config.root_directory || this.agent.tmpDir;
58
+ // Libagent logFile is already created in the libagent. Since, there is no
59
+ // way to tap on to the file name created by boost::log used by libagent
60
+ // show the log filePath till agent tmpDir.
61
+ var fileName = this.agent.tmpDir;
88
62
 
89
- if (!consoleOnly) {
90
- this.agent.recursiveMkDir(rootPath);
91
- }
92
63
 
93
- if (this.agent.opts.debug) {
94
- // force logging level to DEBUG and output location of logs
95
- config.level = 'DEBUG';
96
- if (!consoleOnly) {
97
- console.log('[DEBUG] Appdynamics agent logs: ' + fileName);
98
- }
99
- }
64
+ var consoleOnly = (this.agent.opts.logging && this.agent.opts.logging.logfiles &&
65
+ this.agent.opts.logging.logfiles.every(function (lf) {
66
+ return lf.outputType == 'console';
67
+ }));
100
68
 
101
- // libagent uses its own logging, and does not need the log4js backend to be initialized
102
- if (!initializeBackend) {
103
- this.libAgentConnector.initLogger();
104
- return;
105
- }
69
+ // If console logging env variable is set and no custom logging config is provided
70
+ // then don't create temp path for logs
71
+ if (process.env.APPDYNAMICS_LOGGER_OUTPUT_TYPE === "console" && (!config.logfiles || config.logfiles.length == 0)) {
72
+ consoleOnly = true;
73
+ }
106
74
 
107
- if (process.env.APPDYNAMICS_LOGGER_OUTPUT_TYPE === "console") {
108
- // Update the outputType in logging config to console for JavaProxy
109
- config.outputType = config.outputType || "console";
110
- }
75
+ if (!consoleOnly) {
76
+ this.agent.recursiveMkDir(rootPath);
77
+ }
111
78
 
112
- if (cluster.isMaster) {
113
- log4js.configure({
114
- appenders: [{
115
- type: 'clustered',
116
- appenders: [{
117
- type: 'logLevelFilter',
118
- level: config.level || process.env.APPDYNAMICS_LOGGER_LEVEL || 'INFO',
119
- appender: {
120
- type: config.outputType || 'file',
121
- filename: fileName,
122
- maxLogSize: config.max_size || 5242880,
123
- backups: config.max_files || 10,
124
- category: 'default',
125
- mode: config.mode || 'append'
126
- }
127
- }]
128
- }]
129
- });
130
- }
131
- else {
132
- log4js.configure({
133
- appenders: [{
134
- type: 'clustered'
135
- }]
136
- });
79
+ if (this.agent.opts.debug) {
80
+ // force logging level to DEBUG and output location of logs
81
+ config.level = 'DEBUG';
82
+ if (!consoleOnly) {
83
+ console.log('[DEBUG] Appdynamics agent logs: ' + fileName);
137
84
  }
138
-
139
- Logger.sharedLogger = this.logger = log4js.getLogger('default');
140
85
  }
86
+
87
+ // libagent uses its own logging, and does not need the log4js backend to be initialized
88
+ this.libAgentConnector.initLogger();
141
89
  };
142
90
 
143
91
  Logger.prototype.trace = function (msg) {
@@ -222,4 +170,4 @@ Logger.prototype.isErrorEnabled = function () {
222
170
 
223
171
  Logger.prototype.isFatalEnabled = function () {
224
172
  return this.logger.isFatalEnabled();
225
- };
173
+ };
@@ -0,0 +1,97 @@
1
+ 'use strict';
2
+
3
+ const opentelemetry_api = require('@opentelemetry/api');
4
+ const { ROOT_CONTEXT } = require('@opentelemetry/api');
5
+ const { BatchSpanProcessor, ConsoleSpanExporter, BasicTracerProvider } = require('@opentelemetry/sdk-trace-base');
6
+ const { OTLPTraceExporter } = require("@opentelemetry/exporter-trace-otlp-proto");
7
+ const { AsyncHooksContextManager, AsyncLocalStorageContextManager } = require("@opentelemetry/context-async-hooks");
8
+ const { ParentBasedSampler, AlwaysOnSampler, TraceIdRatioBasedSampler } = require("@opentelemetry/core");
9
+ const { Resource } = require('@opentelemetry/resources');
10
+ const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
11
+ const url = require('url');
12
+
13
+ module.exports = TracerProvider;
14
+
15
+ function TracerProvider(logger) {
16
+ this.host = 'localhost';
17
+ this.port = '55681';
18
+ this.ot_api = opentelemetry_api;
19
+ this.ROOT_CONTEXT = ROOT_CONTEXT;
20
+ this.logger = logger;
21
+ }
22
+
23
+ function getSamplerFromConfig(config) {
24
+ if(config.sampler && config.sampler.TraceIdRatioBasedSampler) {
25
+ const ratio = config.sampler.TraceIdRatioBasedSampler.Ratio || 1;
26
+ return new TraceIdRatioBasedSampler(ratio);
27
+ } else {
28
+ return new AlwaysOnSampler();
29
+ }
30
+ }
31
+
32
+ TracerProvider.prototype.register = function(config) {
33
+ const provider = new BasicTracerProvider({
34
+ sampler: new ParentBasedSampler({
35
+ root: getSamplerFromConfig(config.openTelemetry)
36
+ }),
37
+ resource: new Resource({
38
+ [SemanticResourceAttributes.SERVICE_NAME]: config.tierName,
39
+ [SemanticResourceAttributes.SERVICE_NAMESPACE]: config.applicationName
40
+ }),
41
+ });
42
+
43
+ // default collector configuration, can be overridden from agent config
44
+ const collectorOptions = {
45
+ attributes: {'service.name': config.tierName,
46
+ 'service.namespace': config.applicationName}
47
+ };
48
+
49
+ // batch export config, empty by default
50
+ const batchExporterConfig = {};
51
+
52
+ if (config.openTelemetry) {
53
+ if (config.openTelemetry.collector) {
54
+ Object.assign(collectorOptions, config.openTelemetry.collector);
55
+ this.url = collectorOptions.url;
56
+ try {
57
+ var urlObj = url.parse(this.url);
58
+ this.host = urlObj.hostname;
59
+ this.port = urlObj.port;
60
+ } catch (e) {
61
+ this.logger.error('Collector url must be in <host>:<port> format');
62
+ return false;
63
+ }
64
+ }
65
+ if(config.openTelemetry.exporter) {
66
+ if(config.openTelemetry.exporter.maxExportBatchSize) {
67
+ batchExporterConfig.maxExportBatchSize = config.openTelemetry.exporter.maxExportBatchSize;
68
+ }
69
+ if(config.openTelemetry.exporter.maxQueueSize) {
70
+ batchExporterConfig.maxQueueSize = config.openTelemetry.exporter.maxQueueSize;
71
+ }
72
+ if(config.openTelemetry.exporter.exportTimeoutMillis) {
73
+ batchExporterConfig.exportTimeoutMillis = config.openTelemetry.exporter.exportTimeoutMillis;
74
+ }
75
+ if(config.openTelemetry.exporter.maxExportBatchSize) {
76
+ batchExporterConfig.maxExportBatchSize = config.openTelemetry.exporter.maxExportBatchSize;
77
+ }
78
+ }
79
+ }
80
+
81
+ const exporter = new OTLPTraceExporter(collectorOptions);
82
+ provider.addSpanProcessor(new BatchSpanProcessor(exporter, batchExporterConfig));
83
+ if (config.openTelemetry && config.openTelemetry.debug) {
84
+ provider.addSpanProcessor(new BatchSpanProcessor(new ConsoleSpanExporter(), batchExporterConfig));
85
+ }
86
+
87
+ const majorVersion = parseInt(process.versions.node.split('.')[0]);
88
+ const minorVersion = parseInt(process.versions.node.split('.')[1]);
89
+ const contextManager = majorVersion > 14 || majorVersion == 14 && minorVersion >= 8 ?
90
+ AsyncLocalStorageContextManager : AsyncHooksContextManager;
91
+ provider.register({contextManager: new contextManager()});
92
+ return true;
93
+ };
94
+
95
+ TracerProvider.prototype.getTracer = function(name) {
96
+ return opentelemetry_api.trace.getTracer(name);
97
+ };
@@ -144,6 +144,7 @@ LibagentConnector.prototype.init = function () {
144
144
  self.updateConfigTimerId = new MessageSender(self.agent, 30, 60 * 1000, function () {
145
145
  self.libagent.updateConfig();
146
146
  });
147
+ self.setupEum(self.agent);
147
148
  self.emit("connected");
148
149
 
149
150
  self.agent.transactionSender.isEnabled = true;
@@ -345,6 +346,11 @@ LibagentConnector.prototype.startProcessSnapshot = function () {
345
346
  self.libagent.startProcessSnapshot();
346
347
  };
347
348
 
349
+ LibagentConnector.prototype.getBusinessTransactionQueryType = function (entryPointType, callback) {
350
+ var self = this;
351
+ return self.libagent.getBusinessTransactionQueryType(entryPointType, callback);
352
+ };
353
+
348
354
  LibagentConnector.prototype.sendProcessSnapshot = function (processSnapshot) {
349
355
  var self = this;
350
356
  self.libagent.addProcessSnapshot(processSnapshot);
@@ -534,3 +540,21 @@ LibagentConnector.prototype.getEumCookieFields = function (transaction, shortFor
534
540
  else
535
541
  return {};
536
542
  };
543
+
544
+ LibagentConnector.prototype.setupEum = function (agent) {
545
+ var libAgentConnector = this;
546
+ agent.eum.eumCookie.prototype.setFieldValues = function () {
547
+ var self = this;
548
+ var shortForm = self.keyForm == 'short';
549
+ var fields = libAgentConnector.getEumCookieFields(self.transaction, shortForm);
550
+ if (fields) {
551
+ for (var key in fields) {
552
+ self.addSubCookie(key, fields[key]);
553
+ }
554
+ self.transaction.eumGuid = fields.g || fields.clientRequestGuid;
555
+ self.guid = self.transaction.eumGuid;
556
+ self.setCookie();
557
+ }
558
+ return true;
559
+ };
560
+ };
@@ -143,7 +143,7 @@ LibAgent.prototype.readNodeIndex = function(callback) {
143
143
  LibAgent.prototype.initializeLogger = function() {
144
144
  var self = this;
145
145
  self.agent.logger.setLibAgentConnector(self.agent.libagentConnector);
146
- self.agent.logger.init(self.agent.opts.logging, false);
146
+ self.agent.logger.init(self.agent.opts.logging);
147
147
  };
148
148
 
149
149
  LibAgent.prototype.createCLRDirectories = function() {
@@ -182,6 +182,7 @@ LibAgent.prototype.createExitCall = function(time, exitCallInfo) {
182
182
  command: exitCallInfo.command || '',
183
183
  properties: exitCallInfo.supportedProperties,
184
184
  useBackendConfig: exitCallInfo.useBackendConfig,
185
+ protocol: exitCallInfo.protocol,
185
186
  addAnalyticsData: function(key, value) {
186
187
  this.userData = this.userData || [];
187
188
  if (value instanceof Date) {
@@ -3,7 +3,7 @@
3
3
  * 2016
4
4
  * All Rights Reserved
5
5
  */
6
- var url = require('url');
6
+ var utility = require('../utility');
7
7
 
8
8
  function TransactionSender(agent) {
9
9
  this.agent = agent;
@@ -46,6 +46,18 @@ TransactionSender.prototype.init = function() {
46
46
  isHttpRequest = true;
47
47
  if('singularityheader' in req.headers) {
48
48
  corrHeader = req.headers.singularityheader || "";
49
+ } else if(self.agent.tracer && transaction.baggageCorrHeader) {
50
+ /*
51
+ * 1: We append the doNotResolveSubHeader when the upstream is a pure OT service to
52
+ * prevent resolution to the preceding APPD service
53
+ 2: The noTxDetectHeader is treated specially by libagent, so do not append the doNotResolveSubHeader
54
+ in this case
55
+ */
56
+ const noTxDetectHeader = self.agent.correlation.DISABLE_TRANSACTION_DETECTION + '=true';
57
+ const doNotResolveSubHeader = self.agent.correlation.DONOTRESOLVE + '=true';
58
+ corrHeader = transaction.baggageCorrHeader != noTxDetectHeader ? transaction.baggageCorrHeader + '*' +
59
+ doNotResolveSubHeader : transaction.baggageCorrHeader;
60
+ self.agent.logger.debug(`Using Singularity Header from Opentelemetry Baggage ${corrHeader}`);
49
61
  }
50
62
  }
51
63
  if (req.businessTransactionName) {
@@ -53,7 +65,7 @@ TransactionSender.prototype.init = function() {
53
65
  }
54
66
  }
55
67
 
56
- var txData = libagentConnector.startBusinessTransaction('NODEJS_WEB', name, corrHeader, self.createBtNamingWrapper(req), isHttpRequest);
68
+ var txData = libagentConnector.startBusinessTransaction('NODEJS_WEB', name, corrHeader, utility.createBtNamingWrapper(req), isHttpRequest);
57
69
 
58
70
  if (txData === undefined || txData.isExcluded) {
59
71
  transaction.skip = true;
@@ -108,14 +120,3 @@ TransactionSender.prototype.init = function() {
108
120
  libagentConnector.stopExitCall(exitCall, error);
109
121
  });
110
122
  };
111
-
112
-
113
- TransactionSender.prototype.createBtNamingWrapper = function(req) {
114
- // TODO: replace these with boost::regex in libagent bindings
115
- if (req.url) {
116
- var parsedUrl = url.parse(req.url);
117
- req.parsedPathName = parsedUrl.pathname;
118
- req.parsedParameterString = parsedUrl.query;
119
- }
120
- return req;
121
- };
@@ -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
+ };
@@ -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
  });