appdynamics 23.7.0 → 24.1.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": "23.7.0.0",
3
- "sha": "",
2
+ "version": "24.1.0.0",
3
+ "sha": "e8cff3813a1c37f72ee6694209ae1b557d372eb0",
4
4
  "nodeVersion": "",
5
- "buildName": "9326",
5
+ "buildName": "9734",
6
6
  "compatibilityVersion": "4.4.1.0"
7
7
  }
package/lib/core/agent.js CHANGED
@@ -163,6 +163,27 @@ Agent.computeTmpDir = function (rootTmpDir,
163
163
  return path.join(rootTmpDir, sha256.digest('hex').slice(0, 32));
164
164
  };
165
165
 
166
+ Agent.prototype.setKubernetesConfig = function() {
167
+ var self = this;
168
+ try {
169
+ const NSPACE_PATH = "/var/run/secrets/kubernetes.io/serviceaccount/namespace";
170
+
171
+ let clusterService = (process.env.APPDYNAMICS_CONTAINERINFO_FETCH_SERVICE).split(":");
172
+ if(clusterService.length != 2) {
173
+ return;
174
+ }
175
+
176
+ self.opts.kbHost = clusterService[0];
177
+ self.opts.kbPort = parseInt(clusterService[1]);
178
+ self.opts.kbPodName = process.env.HOSTNAME;
179
+ self.opts.kbContainerName = process.env.APPDYNAMICS_CONTAINER_NAME;
180
+ self.opts.kbNspace = fs.readFileSync(NSPACE_PATH, 'utf-8').trim();
181
+ self.opts.kbConfigEnabled = true;
182
+ } catch(err) {
183
+ self.logger.warn('Kubernetes containerid disabled due to' + err + '\n' + err.stack);
184
+ }
185
+ };
186
+
166
187
  /* istanbul ignore next -- requires too much stubbing and mocking to unit test */
167
188
  Agent.prototype.init = function (opts) {
168
189
  var self = this;
@@ -177,6 +198,10 @@ Agent.prototype.init = function (opts) {
177
198
 
178
199
  self.opts.clsDisabled = !!self.opts.clsDisabled;
179
200
 
201
+ if(process.env.APPDYNAMICS_CONTAINERINFO_FETCH_SERVICE) {
202
+ self.setKubernetesConfig();
203
+ }
204
+
180
205
  self.backendConnector = new LibAgent(this);
181
206
 
182
207
  if (opts.openTelemetry && opts.openTelemetry.enabled) {
@@ -225,7 +250,7 @@ Agent.prototype.init = function (opts) {
225
250
  self.logger.error('AppDynamics agent cannot be started: node name/node name prefix is either missing or empty');
226
251
  return;
227
252
  }
228
-
253
+
229
254
  var nodeName;
230
255
  if(self.opts.nodeName && self.opts.nodeName.length) {
231
256
  nodeName = self.opts.nodeName;
@@ -319,6 +344,19 @@ Agent.prototype.init = function (opts) {
319
344
  }
320
345
  };
321
346
 
347
+ Agent.prototype.registerOtelProviders = function(containerId) {
348
+ var self = this;
349
+ if (self.opts.openTelemetryLogger && self.opts.openTelemetryLogger.enabled) {
350
+ var OtelLoggerProvider = require('./opentelemetry-logger');
351
+ self.OtelLoggerProvider = new OtelLoggerProvider(self.logger);
352
+ if (!self.OtelLoggerProvider.register(self.opts, containerId)) {
353
+ self.logger.error('OtelLoggerProvider registration has failed, feature disabled');
354
+ return;
355
+ }
356
+ self.OtelLogger = self.OtelLoggerProvider;
357
+ }
358
+ };
359
+
322
360
  Agent.prototype.initializeOpts = function (opts) {
323
361
  var self = this;
324
362
  opts = opts || {};
@@ -363,8 +401,8 @@ Agent.prototype.initializeOpts = function (opts) {
363
401
  if (self.opts.analyticsMaxMessageSizeInBytes === undefined && process.env.APPDYNAMICS_ANALYTICS_MAX_MESSAGE_SIZE) {
364
402
  self.opts.analyticsMaxMessageSizeInBytes = parseInt(process.env.APPDYNAMICS_ANALYTICS_MAX_MESSAGE_SIZE, 10);
365
403
  }
366
- };
367
404
 
405
+ };
368
406
 
369
407
  Agent.prototype.fetchMetadata = function (cb) {
370
408
  var self = this, key;
@@ -437,6 +475,7 @@ Agent.prototype.loadProbes = function () {
437
475
  probeCons.push(require('../probes/cassandra-probe').CassandraProbe);
438
476
  probeCons.push(require('../probes/express-probe').ExpressProbe);
439
477
  probeCons.push(require('../probes/rabbitmq-probe').RabbitMQProbe);
478
+ probeCons.push(require('../probes/winston-probe').WinstonProbe);
440
479
 
441
480
  var packageProbes = {};
442
481
  probeCons.forEach(function (ProbeCon) {
@@ -0,0 +1,88 @@
1
+ 'use strict';
2
+
3
+ const opentelemetry_api = require('@opentelemetry/api');
4
+ const { DiagConsoleLogger, DiagLogLevel, diag } = require('@opentelemetry/api');
5
+ const { logs, SeverityNumber } = require('@opentelemetry/api-logs');
6
+ const { LoggerProvider, ConsoleLogRecordExporter, SimpleLogRecordProcessor, BatchLogRecordProcessor} = require('@opentelemetry/sdk-logs');
7
+ const { OTLPLogExporter } = require('@opentelemetry/exporter-logs-otlp-proto');
8
+ const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
9
+ const { Resource } = require('@opentelemetry/resources');
10
+ const url = require('url');
11
+
12
+ module.exports = OtelLoggerProvider;
13
+
14
+ function OtelLoggerProvider(logger) {
15
+ this.ot_api = opentelemetry_api;
16
+ this.logger = logger;
17
+ }
18
+
19
+ OtelLoggerProvider.prototype.register = function(config, containerId) {
20
+ const collectorOptions = {};
21
+
22
+ if (config.openTelemetryLogger) {
23
+ if (config.openTelemetryLogger.collector) {
24
+ Object.assign(collectorOptions, config.openTelemetryLogger.collector);
25
+ var urlconfig = collectorOptions.url;
26
+ this.logger.debug('Exporter using config ' + JSON.stringify(collectorOptions));
27
+ try {
28
+ url.parse(urlconfig);
29
+ } catch (e) {
30
+ this.logger.error('Collector url must be in <host>:<port> format');
31
+ return false;
32
+ }
33
+ }
34
+ }
35
+
36
+ // Optional and only needed to see the internal diagnostic logging (during development)
37
+ diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG);
38
+
39
+ const resource = Resource.default().merge(new Resource({
40
+ [SemanticResourceAttributes.SERVICE_NAME]: config.tierName,
41
+ [SemanticResourceAttributes.SERVICE_NAMESPACE]: config.applicationName,
42
+ [SemanticResourceAttributes.SERVICE_INSTANCE_ID]: config.nodeName,
43
+ [SemanticResourceAttributes.CONTAINER_ID]: containerId
44
+ }));
45
+
46
+ const loggerProvider = new LoggerProvider({
47
+ resource: resource,
48
+ });
49
+
50
+ if(config.openTelemetryLogger.debug) {
51
+ loggerProvider.addLogRecordProcessor(
52
+ new SimpleLogRecordProcessor(new ConsoleLogRecordExporter())
53
+ );
54
+ }
55
+
56
+ const loggerExporter = new OTLPLogExporter(collectorOptions);
57
+ loggerProvider.addLogRecordProcessor(
58
+ new BatchLogRecordProcessor(loggerExporter)
59
+ );
60
+
61
+ logs.setGlobalLoggerProvider(loggerProvider);
62
+
63
+ this.logger = logs.getLogger('Appdynamics', '1.0.0');
64
+
65
+ return true;
66
+ };
67
+
68
+ OtelLoggerProvider.prototype.emit = function(txn, btId, obj, filteredMsg, allowedLevel) {
69
+
70
+ const severityNumber = SeverityNumber[obj.level.toUpperCase()];
71
+ if(severityNumber < allowedLevel) {
72
+ return;
73
+ }
74
+
75
+ const attributes = {
76
+ 'severity': obj.level.toUpperCase(), // obj
77
+ 'appd.bt.id': btId, // transaction
78
+ 'appd.bt.name': txn.name, // transaction
79
+ 'appd.request.guid': txn.guid // transaction
80
+ };
81
+
82
+ this.logger.emit({
83
+ severityNumber: severityNumber,
84
+ severityText: obj.level.toUpperCase(),
85
+ body: filteredMsg,
86
+ attributes: attributes,
87
+ });
88
+ };
@@ -85,6 +85,7 @@ function LibagentConnector(agent) {
85
85
  this.manualProcessSnapshotInProgress = undefined;
86
86
  this.instanceTrackingTimerId = undefined;
87
87
  this.timersInitialized = false;
88
+ this.nodeProperties = new Map();
88
89
  EventEmitter.call(this);
89
90
  }
90
91
  util.inherits(LibagentConnector, EventEmitter);
@@ -99,13 +100,14 @@ LibagentConnector.prototype.initLogger = function () {
99
100
 
100
101
  LibagentConnector.prototype.init = function () {
101
102
  var self = this;
102
-
103
103
  // initialize protobuf
104
104
  self.protobufModel = new ProtobufModel(self.agent);
105
105
  self.protobufModel.init();
106
106
 
107
107
  self.manualProcessSnapshotInProgress = false;
108
108
 
109
+ self.nodeProperties.set("opentelemetry-logs-push-enabled", 0);
110
+ self.nodeProperties.set("opentelemetry-allowed-log-level", 0);
109
111
  self.libagent.init(self.agent);
110
112
  self.agent.TracerProvider && self.agent.TracerProvider.updateResourceAttributes({ "container.id": self.getContainerId() });
111
113
 
@@ -143,6 +145,10 @@ LibagentConnector.prototype.init = function () {
143
145
 
144
146
  self.agent.on('agentStarted', function (meta, filters) {
145
147
  self.libagent.start(meta, filters);
148
+ self.registerNodeProperties();
149
+
150
+ self.agent.registerOtelProviders(self.getContainerId());
151
+
146
152
  self.updateConfigTimerId = new MessageSender(self.agent, 30, 60 * 1000, function () {
147
153
  self.libagent.updateConfig();
148
154
  });
@@ -257,7 +263,7 @@ LibagentConnector.prototype.startExitCall = function (transaction, exitCall) {
257
263
 
258
264
  LibagentConnector.prototype.disableResolutionForExitCall = function (exitCall) {
259
265
  var self = this;
260
-
266
+
261
267
  if(!self.agent.profiler.isValidThreadId(exitCall.threadId)) {
262
268
  return;
263
269
  }
@@ -322,6 +328,20 @@ LibagentConnector.prototype.updateInstanceTracking = function () {
322
328
  this.emit("instanceTrackerConfig", config);
323
329
  };
324
330
 
331
+ LibagentConnector.prototype.updateNodeProperties = function () {
332
+ this.nodeProperties.forEach((value, key) => {
333
+ this.nodeProperties.set(key, this.libagent.getNodeProperty(key));
334
+ });
335
+ };
336
+
337
+ LibagentConnector.prototype.getNodeProperty = function (name) {
338
+ return this.nodeProperties.get(name);
339
+ };
340
+
341
+ LibagentConnector.prototype.filterLogMessage = function (msg) {
342
+ return this.libagent.filterLogMessage(msg);
343
+ };
344
+
325
345
  LibagentConnector.prototype.sendInstanceTrackerInfo = function (instanceCounts) {
326
346
  this.libagent.addInstanceData(instanceCounts);
327
347
  };
@@ -496,6 +516,13 @@ LibagentConnector.prototype.handleProcessSnapshotRequest = function () {
496
516
  }
497
517
  };
498
518
 
519
+ LibagentConnector.prototype.registerNodeProperties = function () {
520
+ var self = this;
521
+ this.nodeProperties.forEach((value, key) => {
522
+ self.libagent.registerNodeProperty(key, value);
523
+ });
524
+ };
525
+
499
526
  LibagentConnector.prototype.initializeTimers = function () {
500
527
  var self = this;
501
528
 
@@ -565,6 +592,10 @@ LibagentConnector.prototype.initializeTimers = function () {
565
592
  self.updateInstanceTracking();
566
593
  });
567
594
 
595
+ self.updateNodePropertyTimerId = new MessageSender(self.agent, 10, 60 * 1000, function () {
596
+ self.updateNodeProperties();
597
+ });
598
+
568
599
  self.logDebug("Initialized libagent timers");
569
600
  };
570
601
 
@@ -580,7 +611,7 @@ LibagentConnector.prototype.setupEum = function (agent) {
580
611
  var libAgentConnector = this;
581
612
  agent.eum.eumCookie.prototype.setFieldValues = function () {
582
613
  var self = this;
583
-
614
+
584
615
  if(!agent.profiler.isValidThreadId(self.transaction.threadId)) {
585
616
  return false;
586
617
  }
@@ -602,4 +633,4 @@ LibagentConnector.prototype.setupEum = function (agent) {
602
633
  LibagentConnector.prototype.getContainerId = function () {
603
634
  var self = this;
604
635
  return self.libagent.getContainerId();
605
- };
636
+ };
@@ -18,6 +18,7 @@ function LibAgent(agent) {
18
18
  self.agent.libagentConnector.init();
19
19
  });
20
20
  this.nodeIndexComputed = false;
21
+
21
22
  // For unit-testing
22
23
  this.libagent = true;
23
24
  }
@@ -50,11 +51,11 @@ LibAgent.prototype.addNodeIndexToNodeName = function() {
50
51
  if (process.argv.filter(arg => arg.includes("yarn")).length !== 0) {
51
52
  return;
52
53
  }
53
-
54
+
54
55
  if (process.argv.filter(arg => arg.includes("npm")).length !== 0) {
55
56
  return;
56
57
  }
57
- }
58
+ }
58
59
  // create or update node name
59
60
  var computedNodeName = (self.agent.opts.nodeName || os.hostname());
60
61
  if (!self.agent.opts.noNodeNameSuffix) {
@@ -12,13 +12,25 @@ function ApolloEntryProbe(agent) {
12
12
 
13
13
  ApolloEntryProbe.prototype.init = function () {};
14
14
 
15
- ApolloEntryProbe.prototype.attach = function (obj) {
15
+ ApolloEntryProbe.prototype.attach = function (obj, moduleName) {
16
+
16
17
  let self = this;
17
- self.agent.proxy.before(
18
- obj.ApolloServer.prototype,
19
- "createServerInfo",
20
- (args) => this.addLifeCycleHooks(args)
21
- );
18
+
19
+ if(moduleName == 'apollo-server') {
20
+ self.agent.proxy.before(
21
+ obj.ApolloServer.prototype,
22
+ "createServerInfo",
23
+ (args) => this.addLifeCycleHooks(args)
24
+ );
25
+ } else {
26
+ const originalObject = obj;
27
+ const overriddenObject = {};
28
+
29
+ overriddenObject.startStandaloneServer = proxyStartStandaloneServer(self, originalObject);
30
+ overriddenObject.__proto__ = originalObject;
31
+ return overriddenObject;
32
+ }
33
+
22
34
  };
23
35
 
24
36
  ApolloEntryProbe.prototype.addLifeCycleHooks = function (obj) {
@@ -67,3 +79,49 @@ ApolloEntryProbe.prototype.addLifeCycleHooks = function (obj) {
67
79
  ...obj.plugins,
68
80
  ];
69
81
  };
82
+
83
+ function proxyStartStandaloneServer(self, originalObject) {
84
+
85
+ return async function startStandaloneServerProxy(server, options) {
86
+ const overriddenOptions = options || {};
87
+
88
+ const context = options ? options.context : undefined;
89
+ const overriddenContext = async function (contextParam) {
90
+ const contextValue = context ? await context(contextParam) : {};
91
+ contextValue.gqlReq = contextParam.req;
92
+ contextValue.gqlRes = contextParam.res;
93
+ return contextValue;
94
+ };
95
+ overriddenOptions.context = overriddenContext;
96
+
97
+ const plugin = {
98
+ async requestDidStart() {
99
+ return {
100
+ didResolveOperation(requestContext) {
101
+ requestContext.contextValue.gqlReq.graphqlop = requestContext.operationName;
102
+ requestContext.contextValue.gqlReq.transactionStarted = true;
103
+
104
+ HttpCommon.startTransactionHandler(
105
+ requestContext.contextValue.gqlReq,
106
+ requestContext.contextValue.gqlRes,
107
+ self.agent
108
+ );
109
+ },
110
+ didEncounterErrors(requestContext) {
111
+ requestContext.contextValue.gqlRes.error = requestContext.errors[0];
112
+ if(requestContext.contextValue.gqlReq.transactionStarted) {
113
+ return;
114
+ }
115
+ HttpCommon.startTransactionHandler(
116
+ requestContext.contextValue.gqlReq,
117
+ requestContext.contextValue.gqlRes,
118
+ self.agent
119
+ );
120
+ },
121
+ };
122
+ }
123
+ };
124
+ server.addPlugin(plugin);
125
+ return await originalObject.startStandaloneServer(server, overriddenOptions);
126
+ };
127
+ }
@@ -8,6 +8,7 @@ All Rights Reserved
8
8
  var utility = require("../utility");
9
9
  var HttpCommon = require("./http-common");
10
10
  var getGraphQLParams;
11
+ var parseRequestParams;
11
12
 
12
13
  function HttpEntryProbe(agent) {
13
14
  this.agent = agent;
@@ -21,6 +22,10 @@ HttpEntryProbe.prototype.enableGraphQL = function (egql) {
21
22
  getGraphQLParams = egql.getGraphQLParams;
22
23
  };
23
24
 
25
+ HttpEntryProbe.prototype.enableGraphQLHttp = function (obj) {
26
+ parseRequestParams = obj.parseRequestParams;
27
+ };
28
+
24
29
  HttpEntryProbe.prototype.attach = function (obj, moduleName) {
25
30
  var self = this;
26
31
 
@@ -71,6 +76,12 @@ HttpEntryProbe.prototype.__createRequestHandler = function (callback, isHTTPs) {
71
76
  }
72
77
  self.agent.context.run(requestHandler, req, res);
73
78
  });
79
+ } else if (parseRequestParams) {
80
+ parseRequestParams(req).then(function(params) {
81
+ const { operationName } = params;
82
+ req.graphqlop = operationName;
83
+ });
84
+ self.agent.context.run(requestHandler, req, res);
74
85
  } else {
75
86
  if (
76
87
  self.agent.opts.enableGraphQL
@@ -69,7 +69,7 @@ HttpExitProbe.prototype.attach = function (obj, moduleName) {
69
69
  var isRepeatForHttps = false;
70
70
 
71
71
  var [input, options] = args;
72
-
72
+
73
73
  if (typeof(input) != 'string' && !(input instanceof url.URL)) {
74
74
  options = input;
75
75
  input = null;
@@ -88,11 +88,11 @@ HttpExitProbe.prototype.attach = function (obj, moduleName) {
88
88
  if (moduleName === 'https') {
89
89
  options.__appdIsHttps = true;
90
90
  }
91
-
91
+
92
92
  self.setHttpDefaults(locals, args[0], args[1], moduleName);
93
93
 
94
94
  if (locals.opts.method === 'CONNECT') {
95
- // ignore proxy tunnel setup; requests sent via the
95
+ // ignore proxy tunnel setup; requests sent via the
96
96
  // proxy tunnel will get instrumented as they are made
97
97
  options.appdIgnore = true;
98
98
  return;
@@ -117,7 +117,7 @@ HttpExitProbe.prototype.attach = function (obj, moduleName) {
117
117
  self.agent.logger.debug('Skipping HTTP exit call for the transaction.' +
118
118
  'AppdIgnore is: ' + options.appdIgnore + ' ' +
119
119
  'DynamoDB call is:' + isDynamoDBReq + ' ' +
120
- 'HTTPS call is:' + isRepeatForHttps + ' ' +
120
+ 'HTTPS call is:' + isRepeatForHttps + ' ' +
121
121
  'isOtPath is :' + isOtPath);
122
122
  } else {
123
123
  self.agent.logger.debug('Gatheing HTTP exit call information.');
@@ -210,7 +210,7 @@ HttpExitProbe.prototype.attach = function (obj, moduleName) {
210
210
  },
211
211
  function (obj, args, ret, locals) {
212
212
  var [input, options] = args;
213
-
213
+
214
214
  if (typeof(input) != 'string' && !(input instanceof url.URL)) {
215
215
  options = input;
216
216
  input = null;
@@ -223,7 +223,7 @@ HttpExitProbe.prototype.attach = function (obj, moduleName) {
223
223
  }
224
224
  var writeOnce = false, httpParser, httpParserMethod;
225
225
  var threadId = locals.time.threadId;
226
-
226
+
227
227
  proxy.before(ret, ['on', 'addListener'], function (obj, args) {
228
228
  proxy.callback(args, -1, null, null, threadId);
229
229
  }, false, false, threadId);
@@ -259,7 +259,7 @@ HttpExitProbe.prototype.attach = function (obj, moduleName) {
259
259
  obj.setHeader(self.agent.correlation.HEADER_NAME, correlationHeaderValue);
260
260
  }
261
261
  }, false, false, threadId);
262
-
262
+
263
263
  ret.on('socket', function (socket) {
264
264
  httpParser = socket.parser;
265
265
  httpParserMethod = httpParser.__proto__.constructor.kOnHeadersComplete;
@@ -305,6 +305,8 @@ HttpExitProbe.prototype.attach = function (obj, moduleName) {
305
305
  HttpExitProbe.prototype.setHttpDefaults = function (locals, spec, opts, protocol) {
306
306
  if (typeof (spec) === 'string') {
307
307
  locals.opts = url.parse(spec);
308
+ } else if (spec instanceof url.URL) {
309
+ locals.opts = url.parse(spec.toString());
308
310
  } else {
309
311
  locals.opts = Object.assign({}, spec);
310
312
  }
@@ -313,7 +315,7 @@ HttpExitProbe.prototype.setHttpDefaults = function (locals, spec, opts, protocol
313
315
  }
314
316
 
315
317
  locals.opts.hostname = locals.opts.hostname || locals.opts.host || 'localhost';
316
- locals.opts.port = locals.opts.port
318
+ locals.opts.port = locals.opts.port
317
319
  || locals.opts.defaultPort
318
320
  || locals.opts.agent && locals.opts.agent.defaultPort
319
321
  || ((protocol === 'https') ? 443 : 80);
@@ -9,9 +9,17 @@ var HttpEntryProbe = require('./http-entry-probe').HttpEntryProbe;
9
9
  var HttpExitProbe = require('./http-exit-probe').HttpExitProbe;
10
10
  var ApolloEntryProbe = require('./apollo-entry-probe').ApolloEntryProbe;
11
11
 
12
+ const graphQLHttpImplementationPaths = [
13
+ 'graphql-http/lib/use/http',
14
+ 'graphql-http/lib/use/http2',
15
+ 'graphql-http/lib/use/express'
16
+ ];
17
+
18
+ const apolloPackages = ['apollo-server', '@apollo/server/standalone'];
19
+
12
20
  function HttpProbe(agent) {
13
21
  this.agent = agent;
14
- this.packages = ['http', 'https', 'express-graphql', 'apollo-server'];
22
+ this.packages = ['http', 'https', 'express-graphql', ...apolloPackages, ...graphQLHttpImplementationPaths];
15
23
 
16
24
  this.entryProbe = new HttpEntryProbe(agent);
17
25
  this.exitProbe = new HttpExitProbe(agent);
@@ -33,17 +41,19 @@ HttpProbe.prototype.attach = function (obj, moduleName) {
33
41
 
34
42
  if (obj.__appdynamicsProbeAttached__) return;
35
43
  obj.__appdynamicsProbeAttached__ = true;
36
- self.agent.on('destroy', function () {
37
- if (obj.__appdynamicsProbeAttached__) {
38
- delete obj.__appdynamicsProbeAttached__;
39
- if (moduleName !== 'express-graphql' && moduleName !== 'apollo-server') {
44
+
45
+ if(moduleName == 'http' || moduleName == 'https') {
46
+ // Skipping destroy for graphql-http modules as we do not modify them
47
+ self.agent.on('destroy', function () {
48
+ if (obj.__appdynamicsProbeAttached__) {
49
+ delete obj.__appdynamicsProbeAttached__;
40
50
  proxy.release(obj.Server.prototype.on);
41
51
  proxy.release(obj.Server.prototype.addListener);
42
52
  proxy.release(obj.request);
43
53
  }
44
- }
45
- });
46
-
54
+ });
55
+ }
56
+
47
57
  if (moduleName === 'express-graphql') {
48
58
  if (self.agent.opts.enableGraphQL) {
49
59
  this.entryProbe.enableGraphQL(obj);
@@ -52,6 +62,14 @@ HttpProbe.prototype.attach = function (obj, moduleName) {
52
62
  if(self.agent.opts.enableGraphQL) {
53
63
  this.apolloEntryProbe.attach(obj, moduleName);
54
64
  }
65
+ } else if (moduleName === '@apollo/server/standalone') {
66
+ if(self.agent.opts.enableGraphQL) {
67
+ return this.apolloEntryProbe.attach(obj, moduleName);
68
+ }
69
+ } else if (moduleName.includes('graphql-http')) {
70
+ if(self.agent.opts.enableGraphQL) {
71
+ this.entryProbe.enableGraphQLHttp(obj);
72
+ }
55
73
  } else {
56
74
  this.entryProbe.attach(obj, moduleName);
57
75
  this.exitProbe.attach(obj, moduleName);
@@ -0,0 +1,41 @@
1
+ exports.WinstonProbe = WinstonProbe;
2
+
3
+ function WinstonProbe(agent) {
4
+ this.agent = agent;
5
+ this.packages = ['winston'];
6
+ }
7
+
8
+ WinstonProbe.prototype.init = function () {};
9
+
10
+ WinstonProbe.prototype.attach = function (obj) {
11
+ if(obj.__appdynamicsProbeAttached__) return;
12
+ obj.__appdynamicsProbeAttached__ = true;
13
+ let self = this;
14
+ self.agent.proxy.before(
15
+ obj.Logger.prototype,
16
+ "write",
17
+ (obj, args) => this.addLifeCycleHooks(obj, args)
18
+ );
19
+ };
20
+
21
+ WinstonProbe.prototype.addLifeCycleHooks = function (obj, args) {
22
+ let self = this;
23
+
24
+ if(!self.agent.libagentConnector.getNodeProperty("opentelemetry-logs-push-enabled")
25
+ || !self.agent.OtelLogger) {
26
+ return;
27
+ }
28
+
29
+ const threadId = self.agent.profiler.time().threadId;
30
+ const txn = self.agent.profiler.getTransaction(threadId);
31
+ if(!args[0]) {
32
+ self.agent.logger.debug('Invalid Log message captured in winston probe');
33
+ return;
34
+ }
35
+ const logMessage = args[0];
36
+ this.agent.OtelLogger.emit(txn,
37
+ self.agent.libagentConnector.getBusinessTransactionId(txn.btGuid),
38
+ logMessage,
39
+ self.agent.libagentConnector.filterLogMessage(logMessage.message),
40
+ self.agent.libagentConnector.getNodeProperty("opentelemetry-allowed-log-level"));
41
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appdynamics",
3
- "version": "23.7.0",
3
+ "version": "24.1.0",
4
4
  "description": "Performance Profiler and Monitor",
5
5
  "author": "AppDynamics, Inc.",
6
6
  "homepage": "https://www.appdynamics.com",
@@ -31,30 +31,34 @@
31
31
  "lib": "./lib"
32
32
  },
33
33
  "optionalDependencies": {
34
- "n": "^6.7.0"
34
+ "n": "^6.8.0"
35
35
  },
36
36
  "dependencies": {
37
37
  "@opentelemetry/api": "~1.4.1",
38
+ "@opentelemetry/api-logs": "^0.45.1",
38
39
  "@opentelemetry/context-async-hooks": "~1.10.1",
39
40
  "@opentelemetry/core": "~1.10.1",
40
- "@opentelemetry/exporter-trace-otlp-proto": "~0.36.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",
41
44
  "@opentelemetry/resources": "~1.10.1",
45
+ "@opentelemetry/sdk-logs": "^0.45.1",
42
46
  "@opentelemetry/sdk-trace-base": "~1.10.1",
43
47
  "@opentelemetry/semantic-conventions": "~1.10.1",
44
48
  "@yarnpkg/lockfile": "^1.1.0",
45
49
  "cls-hooked": "4.2.2",
46
- "https-proxy-agent": "^5.0.0",
50
+ "https-proxy-agent": "^5.0.1",
47
51
  "uuid": "^8.3.2",
48
52
  "y18n": "^5.0.8",
49
- "appdynamics-libagent-napi": "https://cdn.appdynamics.com/packages/nodejs/23.7.0.0/appdynamics-libagent-napi-node.tgz",
50
- "appdynamics-native": "https://cdn.appdynamics.com/packages/nodejs/23.7.0.0/appdynamics-native-node.tgz",
51
- "appdynamics-protobuf": "https://cdn.appdynamics.com/packages/nodejs/23.7.0.0/appdynamics-protobuf-node.tgz"
53
+ "appdynamics-libagent-napi": "https://cdn.appdynamics.com/packages/nodejs/24.1.0.0/appdynamics-libagent-napi-node.tgz",
54
+ "appdynamics-native": "https://cdn.appdynamics.com/packages/nodejs/24.1.0.0/appdynamics-native-node.tgz",
55
+ "appdynamics-protobuf": "https://cdn.appdynamics.com/packages/nodejs/24.1.0.0/appdynamics-protobuf-node.tgz"
52
56
  },
53
57
  "overrides": {
54
58
  "semver": "7.5.4"
55
59
  },
56
60
  "engines": {
57
- "node": ">=12 <=v20.*"
61
+ "node": ">=12 <=v21.*"
58
62
  },
59
63
  "engine-strict": true
60
64
  }
package/packageBck.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appdynamics",
3
- "version": "23.7.0",
3
+ "version": "24.1.0",
4
4
  "description": "Performance Profiler and Monitor",
5
5
  "author": "AppDynamics, Inc.",
6
6
  "homepage": "https://www.appdynamics.com",
@@ -31,30 +31,34 @@
31
31
  "lib": "./lib"
32
32
  },
33
33
  "optionalDependencies": {
34
- "n": "^6.7.0"
34
+ "n": "^6.8.0"
35
35
  },
36
36
  "dependencies": {
37
37
  "@opentelemetry/api": "~1.4.1",
38
+ "@opentelemetry/api-logs": "^0.45.1",
38
39
  "@opentelemetry/context-async-hooks": "~1.10.1",
39
40
  "@opentelemetry/core": "~1.10.1",
40
- "@opentelemetry/exporter-trace-otlp-proto": "~0.36.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",
41
44
  "@opentelemetry/resources": "~1.10.1",
45
+ "@opentelemetry/sdk-logs": "^0.45.1",
42
46
  "@opentelemetry/sdk-trace-base": "~1.10.1",
43
47
  "@opentelemetry/semantic-conventions": "~1.10.1",
44
48
  "@yarnpkg/lockfile": "^1.1.0",
45
49
  "cls-hooked": "4.2.2",
46
- "https-proxy-agent": "^5.0.0",
50
+ "https-proxy-agent": "^5.0.1",
47
51
  "uuid": "^8.3.2",
48
52
  "y18n": "^5.0.8",
49
- "appdynamics-libagent-napi": "https://cdn.appdynamics.com/packages/nodejs/23.7.0.0/appdynamics-libagent-napi-node.tgz",
50
- "appdynamics-native": "https://cdn.appdynamics.com/packages/nodejs/23.7.0.0/appdynamics-native-node.tgz",
51
- "appdynamics-protobuf": "https://cdn.appdynamics.com/packages/nodejs/23.7.0.0/appdynamics-protobuf-node.tgz"
53
+ "appdynamics-libagent-napi": "https://cdn.appdynamics.com/packages/nodejs/24.1.0.0/appdynamics-libagent-napi-node.tgz",
54
+ "appdynamics-native": "https://cdn.appdynamics.com/packages/nodejs/24.1.0.0/appdynamics-native-node.tgz",
55
+ "appdynamics-protobuf": "https://cdn.appdynamics.com/packages/nodejs/24.1.0.0/appdynamics-protobuf-node.tgz"
52
56
  },
53
57
  "overrides": {
54
58
  "semver": "7.5.4"
55
59
  },
56
60
  "engines": {
57
- "node": ">=12 <=v20.*"
61
+ "node": ">=12 <=v21.*"
58
62
  },
59
63
  "engine-strict": true
60
64
  }