appdynamics 23.10.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.10.0.0",
3
- "sha": "",
2
+ "version": "24.1.0.0",
3
+ "sha": "e8cff3813a1c37f72ee6694209ae1b557d372eb0",
4
4
  "nodeVersion": "",
5
- "buildName": "9494",
5
+ "buildName": "9734",
6
6
  "compatibilityVersion": "4.4.1.0"
7
7
  }
package/lib/core/agent.js CHANGED
@@ -344,6 +344,19 @@ Agent.prototype.init = function (opts) {
344
344
  }
345
345
  };
346
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
+
347
360
  Agent.prototype.initializeOpts = function (opts) {
348
361
  var self = this;
349
362
  opts = opts || {};
@@ -462,6 +475,7 @@ Agent.prototype.loadProbes = function () {
462
475
  probeCons.push(require('../probes/cassandra-probe').CassandraProbe);
463
476
  probeCons.push(require('../probes/express-probe').ExpressProbe);
464
477
  probeCons.push(require('../probes/rabbitmq-probe').RabbitMQProbe);
478
+ probeCons.push(require('../probes/winston-probe').WinstonProbe);
465
479
 
466
480
  var packageProbes = {};
467
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);
@@ -105,8 +106,11 @@ LibagentConnector.prototype.init = function () {
105
106
 
106
107
  self.manualProcessSnapshotInProgress = false;
107
108
 
109
+ self.nodeProperties.set("opentelemetry-logs-push-enabled", 0);
110
+ self.nodeProperties.set("opentelemetry-allowed-log-level", 0);
108
111
  self.libagent.init(self.agent);
109
112
  self.agent.TracerProvider && self.agent.TracerProvider.updateResourceAttributes({ "container.id": self.getContainerId() });
113
+
110
114
  self.exceptionHandlers = new ExceptionHandlers();
111
115
  self.exceptionHandlers.init(
112
116
  self.agent,
@@ -141,6 +145,10 @@ LibagentConnector.prototype.init = function () {
141
145
 
142
146
  self.agent.on('agentStarted', function (meta, filters) {
143
147
  self.libagent.start(meta, filters);
148
+ self.registerNodeProperties();
149
+
150
+ self.agent.registerOtelProviders(self.getContainerId());
151
+
144
152
  self.updateConfigTimerId = new MessageSender(self.agent, 30, 60 * 1000, function () {
145
153
  self.libagent.updateConfig();
146
154
  });
@@ -320,6 +328,20 @@ LibagentConnector.prototype.updateInstanceTracking = function () {
320
328
  this.emit("instanceTrackerConfig", config);
321
329
  };
322
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
+
323
345
  LibagentConnector.prototype.sendInstanceTrackerInfo = function (instanceCounts) {
324
346
  this.libagent.addInstanceData(instanceCounts);
325
347
  };
@@ -494,6 +516,13 @@ LibagentConnector.prototype.handleProcessSnapshotRequest = function () {
494
516
  }
495
517
  };
496
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
+
497
526
  LibagentConnector.prototype.initializeTimers = function () {
498
527
  var self = this;
499
528
 
@@ -563,6 +592,10 @@ LibagentConnector.prototype.initializeTimers = function () {
563
592
  self.updateInstanceTracking();
564
593
  });
565
594
 
595
+ self.updateNodePropertyTimerId = new MessageSender(self.agent, 10, 60 * 1000, function () {
596
+ self.updateNodeProperties();
597
+ });
598
+
566
599
  self.logDebug("Initialized libagent timers");
567
600
  };
568
601
 
@@ -600,4 +633,4 @@ LibagentConnector.prototype.setupEum = function (agent) {
600
633
  LibagentConnector.prototype.getContainerId = function () {
601
634
  var self = this;
602
635
  return self.libagent.getContainerId();
603
- };
636
+ };
@@ -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);
@@ -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.10.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.10.0.0/appdynamics-libagent-napi-node.tgz",
50
- "appdynamics-native": "https://cdn.appdynamics.com/packages/nodejs/23.10.0.0/appdynamics-native-node.tgz",
51
- "appdynamics-protobuf": "https://cdn.appdynamics.com/packages/nodejs/23.10.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.10.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.10.0.0/appdynamics-libagent-napi-node.tgz",
50
- "appdynamics-native": "https://cdn.appdynamics.com/packages/nodejs/23.10.0.0/appdynamics-native-node.tgz",
51
- "appdynamics-protobuf": "https://cdn.appdynamics.com/packages/nodejs/23.10.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
  }