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.
- package/appdynamics_version.json +3 -3
- package/lib/core/agent.js +41 -2
- package/lib/core/opentelemetry-logger.js +88 -0
- package/lib/libagent/libagent-connector.js +35 -4
- package/lib/libagent/libagent.js +3 -2
- package/lib/probes/apollo-entry-probe.js +64 -6
- package/lib/probes/http-entry-probe.js +11 -0
- package/lib/probes/http-exit-probe.js +10 -8
- package/lib/probes/http-probe.js +26 -8
- package/lib/probes/winston-probe.js +41 -0
- package/package.json +12 -8
- package/packageBck.json +12 -8
package/appdynamics_version.json
CHANGED
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
|
+
};
|
package/lib/libagent/libagent.js
CHANGED
|
@@ -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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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);
|
package/lib/probes/http-probe.js
CHANGED
|
@@ -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',
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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": "
|
|
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.
|
|
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-
|
|
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.
|
|
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/
|
|
50
|
-
"appdynamics-native": "https://cdn.appdynamics.com/packages/nodejs/
|
|
51
|
-
"appdynamics-protobuf": "https://cdn.appdynamics.com/packages/nodejs/
|
|
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 <=
|
|
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": "
|
|
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.
|
|
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-
|
|
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.
|
|
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/
|
|
50
|
-
"appdynamics-native": "https://cdn.appdynamics.com/packages/nodejs/
|
|
51
|
-
"appdynamics-protobuf": "https://cdn.appdynamics.com/packages/nodejs/
|
|
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 <=
|
|
61
|
+
"node": ">=12 <=v21.*"
|
|
58
62
|
},
|
|
59
63
|
"engine-strict": true
|
|
60
64
|
}
|