appdynamics 21.8.0 → 22.3.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/README.md +1 -1
- package/appdynamics_version.json +2 -2
- package/lib/core/agent.js +21 -44
- package/lib/core/appDProxy.js +12 -12
- package/lib/core/logger.js +27 -79
- package/lib/core/opentelemetry-tracer.js +89 -0
- package/lib/libagent/libagent-connector.js +5 -47
- package/lib/libagent/libagent.js +2 -3
- package/lib/libagent/transaction-sender.js +15 -16
- package/lib/libagent/transactions/transaction-reporter.js +0 -5
- package/lib/{libagent/metrics → metrics}/metric.js +4 -1
- package/lib/metrics/metrics-manager.js +4 -3
- package/lib/probes/apollo-entry-probe.js +69 -0
- package/lib/probes/cluster-probe.js +1 -1
- package/lib/probes/couchbase-probe.js +19 -0
- package/lib/probes/grpc-exit-probe.js +1 -1
- package/lib/probes/http-common.js +97 -0
- package/lib/probes/http-entry-probe.js +42 -122
- package/lib/probes/http-exit-probe.js +112 -48
- package/lib/probes/http-ot-utils.js +117 -0
- package/lib/probes/http-probe.js +14 -7
- package/lib/probes/http2-entry-probe.js +1 -7
- package/lib/probes/http2-exit-probe.js +4 -7
- package/lib/probes/ioredis-probe.js +2 -2
- package/lib/probes/mongodb-probe.js +200 -113
- package/lib/probes/rabbitmq-entry-probe.js +184 -0
- package/lib/probes/rabbitmq-exit-probe.js +108 -0
- package/lib/probes/rabbitmq-probe.js +76 -0
- package/lib/process/process-scanner.js +2 -2
- package/lib/profiler/profiler.js +6 -2
- package/lib/profiler/time-promise.js +0 -3
- package/lib/proxy/protobuf-model.js +0 -264
- package/lib/transactions/correlation.js +1 -20
- package/lib/transactions/eum.js +2 -34
- package/lib/utility.js +20 -1
- package/package.json +15 -13
- package/packageBck.json +15 -13
- package/lib/libproxy/instance-info-sender.js +0 -41
- package/lib/libproxy/libproxy.js +0 -204
- package/lib/libproxy/metric.js +0 -109
- package/lib/libproxy/proxy-launcher.js +0 -308
- package/lib/libproxy/proxy-transport.js +0 -634
- package/lib/libproxy/transaction-reporter.js +0 -168
- package/lib/proxy/backend-config.js +0 -488
- package/lib/transactions/analytics-reporter.js +0 -187
- package/lib/transactions/config-manager.js +0 -87
- package/lib/transactions/correlation-header.js +0 -495
- package/lib/transactions/data-collectors.js +0 -95
- package/lib/transactions/sep-config.js +0 -66
- package/lib/transactions/transaction-naming.js +0 -231
- package/lib/transactions/transaction-registry.js +0 -156
- package/lib/transactions/transaction-rules.js +0 -173
- package/postInstallScript.js +0 -33
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright (c) AppDynamics, Inc., and its affiliates
|
|
3
|
-
2015
|
|
4
|
-
All Rights Reserved
|
|
5
|
-
*/
|
|
6
|
-
/* global process, require, exports */
|
|
7
|
-
'use strict';
|
|
8
|
-
|
|
9
|
-
function InstanceInfoSender(agent) {
|
|
10
|
-
this.agent = agent;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
exports.InstanceInfoSender = InstanceInfoSender;
|
|
14
|
-
|
|
15
|
-
InstanceInfoSender.prototype.init = function() {
|
|
16
|
-
var self = this;
|
|
17
|
-
|
|
18
|
-
self.agent.on('configUpdated', function() {
|
|
19
|
-
var configManager = self.agent.configManager;
|
|
20
|
-
var config = configManager.getConfigValue('instanceTrackingConfig');
|
|
21
|
-
var instanceTracker = self.agent.instanceTracker;
|
|
22
|
-
var isRunning;
|
|
23
|
-
|
|
24
|
-
if (config) {
|
|
25
|
-
isRunning = instanceTracker.enabled;
|
|
26
|
-
instanceTracker.enabled = config.enabled;
|
|
27
|
-
instanceTracker.customTypes = config.customTypes || instanceTracker.customTypes;
|
|
28
|
-
|
|
29
|
-
if (config.enabled && !isRunning) {
|
|
30
|
-
instanceTracker.startInstanceTracking(function(err, instanceCounts) {
|
|
31
|
-
if (err) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
self.agent.backendConnector.proxyTransport.sendInstanceData(instanceCounts);
|
|
35
|
-
});
|
|
36
|
-
} else if (!config.enabled && isRunning) {
|
|
37
|
-
instanceTracker.stopInstanceTracking();
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
};
|
package/lib/libproxy/libproxy.js
DELETED
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright (c) AppDynamics, Inc., and its affiliates
|
|
3
|
-
2015
|
|
4
|
-
All Rights Reserved
|
|
5
|
-
*/
|
|
6
|
-
/* global process, require, exports */
|
|
7
|
-
'use strict';
|
|
8
|
-
|
|
9
|
-
var Metric = require('./metric').Metric;
|
|
10
|
-
var ProxyLauncher = require('./proxy-launcher').ProxyLauncher;
|
|
11
|
-
var ProxyTransport = require('./proxy-transport').ProxyTransport;
|
|
12
|
-
var InstanceInfoSender = require('./instance-info-sender').InstanceInfoSender;
|
|
13
|
-
var TransactionReporter = require('./transaction-reporter').TransactionReporter;
|
|
14
|
-
var ExitCall = require('../transactions/exit-call').ExitCall;
|
|
15
|
-
var path = require('path');
|
|
16
|
-
|
|
17
|
-
function LibProxy(agent) {
|
|
18
|
-
this.agent = agent;
|
|
19
|
-
this.proxyLauncher = new ProxyLauncher(agent);
|
|
20
|
-
this.proxyTransport = new ProxyTransport(agent);
|
|
21
|
-
this.instanceInfoSender = new InstanceInfoSender(agent);
|
|
22
|
-
this.transactionReporter = new TransactionReporter(agent);
|
|
23
|
-
// For unit-testing
|
|
24
|
-
this.proxyMode = true;
|
|
25
|
-
|
|
26
|
-
agent.Metric = Metric;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
exports.LibProxy = LibProxy;
|
|
30
|
-
|
|
31
|
-
LibProxy.prototype.init = function () {
|
|
32
|
-
this.proxyTransport.init();
|
|
33
|
-
this.proxyLauncher.init();
|
|
34
|
-
this.proxyLauncher.start();
|
|
35
|
-
this.instanceInfoSender.init();
|
|
36
|
-
this.transactionReporter.init();
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
LibProxy.prototype.addNodeIndexToNodeName = function () {
|
|
40
|
-
// No logic is present in this function. Proxy already
|
|
41
|
-
// does this work in proxy-launcher.
|
|
42
|
-
// Function is placed here to match the corresponding libagent file.
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
LibProxy.prototype.initializeLogger = function () {
|
|
46
|
-
this.agent.logger.init(this.agent.opts.logging, true);
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
LibProxy.prototype.createCLRDirectories = function () {
|
|
50
|
-
var proxyTmpDir = path.join(this.agent.tmpDir, 'proxy');
|
|
51
|
-
|
|
52
|
-
this.agent.proxyCtrlDir = LibProxy.resolveProxyCtrlDir(path.join(proxyTmpDir, 'c'), this.agent.opts);
|
|
53
|
-
this.agent.logger.info("agent.proxyCtrlDir = " + JSON.stringify(this.agent.proxyCtrlDir));
|
|
54
|
-
this.agent.recursiveMkDir(this.agent.proxyCtrlDir);
|
|
55
|
-
|
|
56
|
-
this.agent.proxyLogsDir = path.join(proxyTmpDir, 'l');
|
|
57
|
-
this.agent.recursiveMkDir(this.agent.proxyLogsDir);
|
|
58
|
-
|
|
59
|
-
this.agent.proxyRuntimeDir = path.join(proxyTmpDir, 'r');
|
|
60
|
-
this.agent.recursiveMkDir(this.agent.proxyRuntimeDir);
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
LibProxy.prototype.intializeAgentHelpers = function () {
|
|
64
|
-
// Function is placed here to match the corresponding libagent file.
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
LibProxy.prototype.startAgent = function () {
|
|
68
|
-
// Function is placed here to match the corresponding libagent file.
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
LibProxy.prototype.createExitCall = function (time, exitCallInfo) {
|
|
72
|
-
var self = this;
|
|
73
|
-
var exitType = exitCallInfo.exitType.replace(/^EXIT_/, '');
|
|
74
|
-
// if there's no backend config (OOTB or custom), then ignore this exit call;
|
|
75
|
-
// if exit call has backend config and identifying properties already, we use
|
|
76
|
-
// those (which allows API constructed exit calls to supply these values).
|
|
77
|
-
var backendConfig = exitCallInfo.backendConfig;
|
|
78
|
-
var props = exitCallInfo.identifyingProperties;
|
|
79
|
-
if (!props) {
|
|
80
|
-
var configType = exitCallInfo.configType || (exitType[0] + exitType.substring(1).toLowerCase());
|
|
81
|
-
|
|
82
|
-
if (!backendConfig) {
|
|
83
|
-
var configTypeMethod = 'get' + configType + 'Config';
|
|
84
|
-
if (configTypeMethod in self.agent.backendConfig) {
|
|
85
|
-
backendConfig = self.agent.backendConfig[configTypeMethod](exitCallInfo.supportedProperties);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (!backendConfig) {
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
var propertiesMethod = 'populate' + configType + 'Properties';
|
|
94
|
-
if (propertiesMethod in self.agent.backendConfig) {
|
|
95
|
-
props = self.agent.backendConfig['populate' + configType + 'Properties'](backendConfig, exitCallInfo.supportedProperties);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
if (!props) {
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
exitCallInfo.backendConfig = backendConfig;
|
|
103
|
-
exitCallInfo.identifyingProperties = props;
|
|
104
|
-
|
|
105
|
-
var exitCall = new ExitCall(exitCallInfo);
|
|
106
|
-
exitCall.time = time;
|
|
107
|
-
exitCall.id = time.id;
|
|
108
|
-
exitCall.ts = time.begin;
|
|
109
|
-
exitCall.threadId = time.threadId;
|
|
110
|
-
|
|
111
|
-
var transaction = self.agent.profiler.transactions[time.threadId];
|
|
112
|
-
|
|
113
|
-
if (transaction && !transaction.ignore) {
|
|
114
|
-
exitCall.sequenceInfo = self.agent.profiler.__getNextSequenceInfo(transaction);
|
|
115
|
-
|
|
116
|
-
if (transaction.api && transaction.api.beforeExitCall) {
|
|
117
|
-
exitCall = transaction.api.beforeExitCall(exitCall);
|
|
118
|
-
if (!exitCall) {
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (!transaction.startedExitCalls) {
|
|
124
|
-
transaction.startedExitCalls = [];
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
transaction.startedExitCalls.push(exitCall);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return exitCall;
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
LibProxy.prototype.getCorrelationHeader = function (exitCall) {
|
|
134
|
-
if (!exitCall.backendConfig.correlationEnabled) return;
|
|
135
|
-
var transaction = this.agent.profiler.getTransaction(exitCall.threadId);
|
|
136
|
-
if (!transaction) return;
|
|
137
|
-
var corrHeader = this.agent.correlation.newCorrelationHeader();
|
|
138
|
-
corrHeader.build(transaction, exitCall);
|
|
139
|
-
|
|
140
|
-
// to check if we are ignoring possible snapshot request from btInfoResponse
|
|
141
|
-
if (!transaction.ignore && !transaction.btInfoResponse) {
|
|
142
|
-
this.agent.logger.debug("btInfoResponse is not yet available");
|
|
143
|
-
}
|
|
144
|
-
return corrHeader.getStringHeader();
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
LibProxy.prototype.createSnapshotTrigger = function (transaction) {
|
|
148
|
-
if (!transaction.btInfoResponse) return {
|
|
149
|
-
attachSnapshot: false
|
|
150
|
-
};
|
|
151
|
-
if (transaction.btInfoResponse.isSnapshotRequired) {
|
|
152
|
-
return {
|
|
153
|
-
attachSnapshot: true,
|
|
154
|
-
snapshotTrigger: 'REQUIRED'
|
|
155
|
-
};
|
|
156
|
-
} else if (transaction.btInfoResponse.currentSlowThreshold > 0 &&
|
|
157
|
-
transaction.btInfoResponse.currentSlowThreshold < transaction.ms) {
|
|
158
|
-
return {
|
|
159
|
-
attachSnapshot: true,
|
|
160
|
-
snapshotTrigger: 'SLOW'
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
else if (transaction.btInfoResponse.sendSnapshotIfError &&
|
|
164
|
-
transaction.hasErrors) {
|
|
165
|
-
return {
|
|
166
|
-
attachSnapshot: true,
|
|
167
|
-
snapshotTrigger: 'ERROR'
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
else if (transaction.btInfoResponse.sendSnapshotIfContinuing &&
|
|
171
|
-
transaction.corrHeader &&
|
|
172
|
-
(!transaction.corrHeader.crossAppCorrelation) &&
|
|
173
|
-
transaction.corrHeader.getSubHeader(this.agent.correlation.SNAPSHOT_ENABLE)) {
|
|
174
|
-
return {
|
|
175
|
-
attachSnapshot: true,
|
|
176
|
-
snapshotTrigger: 'CONTINUING'
|
|
177
|
-
};
|
|
178
|
-
} else {
|
|
179
|
-
return {
|
|
180
|
-
attachSnapshot: false,
|
|
181
|
-
snapshotTrigger: undefined
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
LibProxy.prototype.startProcessSnapshot = function () {
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
LibProxy.resolveProxyCtrlDir = function (defaultDir, opts) {
|
|
190
|
-
var dirFromOpts = opts.proxyCtrlDir;
|
|
191
|
-
if (!dirFromOpts) {
|
|
192
|
-
return defaultDir;
|
|
193
|
-
}
|
|
194
|
-
dirFromOpts = path.normalize(dirFromOpts.toString());
|
|
195
|
-
if (path.dirname(dirFromOpts) == dirFromOpts) {
|
|
196
|
-
// Eeeck!!!
|
|
197
|
-
// Looks like someone tried to specify the root directory as
|
|
198
|
-
// the proxy communication directory. There is a really unsafe
|
|
199
|
-
// rm -rf in proxy-launcher that will do a:
|
|
200
|
-
// rm -rf //* if the proxy communication directory is '/'.
|
|
201
|
-
return defaultDir;
|
|
202
|
-
}
|
|
203
|
-
return dirFromOpts;
|
|
204
|
-
};
|
package/lib/libproxy/metric.js
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright (c) AppDynamics, Inc., and its affiliates
|
|
3
|
-
2015
|
|
4
|
-
All Rights Reserved
|
|
5
|
-
*/
|
|
6
|
-
'use strict';
|
|
7
|
-
|
|
8
|
-
/*
|
|
9
|
-
* Metric object used for aggregating values and transferring
|
|
10
|
-
* the aggregated metric to data sender. It can have three states:
|
|
11
|
-
* - created/resetted
|
|
12
|
-
* - initialized, i.e. accumulating values
|
|
13
|
-
* - aggregated
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
function convertOp(op) {
|
|
17
|
-
if (op == 'sum' || op == 'inc')
|
|
18
|
-
return 'TIME_SUM';
|
|
19
|
-
else if (op == 'avg')
|
|
20
|
-
return 'TIME_AVERAGE';
|
|
21
|
-
else if (op == 'set')
|
|
22
|
-
return 'CURRENT';
|
|
23
|
-
else
|
|
24
|
-
return op;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function Metric(agent, definition, isCustom) {
|
|
28
|
-
this.agent = agent;
|
|
29
|
-
this.metricName = definition.path;
|
|
30
|
-
this.unit = definition.unit;
|
|
31
|
-
this.op = convertOp(definition.op) || 'TIME_AVERAGE';
|
|
32
|
-
this.clusterRollup = definition.clusterRollUp || 'INDIVIDUAL';
|
|
33
|
-
this.holeHandling = definition.holeHandling || 'REGULAR_COUNTER';
|
|
34
|
-
this.isCustom = isCustom;
|
|
35
|
-
// used for avg aggregation only
|
|
36
|
-
this._count = undefined;
|
|
37
|
-
|
|
38
|
-
this.reset();
|
|
39
|
-
|
|
40
|
-
// dynamic value property to support live metrics
|
|
41
|
-
Object.defineProperty(this, 'value', {
|
|
42
|
-
enumerable: true,
|
|
43
|
-
get: function() {
|
|
44
|
-
return (typeof(this._value) == 'function'
|
|
45
|
-
? this._value()
|
|
46
|
-
: this._value);
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
exports.Metric = Metric;
|
|
52
|
-
|
|
53
|
-
Metric.prototype.reset = function() {
|
|
54
|
-
var self = this;
|
|
55
|
-
|
|
56
|
-
if (typeof(self._value) != 'function') {
|
|
57
|
-
self._value = 0;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if(self.op === 'TIME_AVERAGE') {
|
|
61
|
-
self._count = 0;
|
|
62
|
-
} else {
|
|
63
|
-
self._count = undefined;
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
Metric.prototype.addValue = function(value) {
|
|
68
|
-
var self = this;
|
|
69
|
-
|
|
70
|
-
if(typeof(value) != 'number' && typeof(value) == 'function' && self.op != 'CURRENT') return;
|
|
71
|
-
|
|
72
|
-
switch(self.op) {
|
|
73
|
-
case 'TIME_AVERAGE':
|
|
74
|
-
self._value = (value + self._value * self._count) / ++self._count;
|
|
75
|
-
break;
|
|
76
|
-
case 'TIME_SUM':
|
|
77
|
-
self._value += value;
|
|
78
|
-
break;
|
|
79
|
-
case 'CURRENT':
|
|
80
|
-
self._value = value;
|
|
81
|
-
break;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if(self.isCustom) {
|
|
85
|
-
self.agent.backendConnector.proxyTransport.sendCustomMetricData(self);
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
Metric.prototype.clone = function() {
|
|
90
|
-
var cln = new Metric(this.agent, {
|
|
91
|
-
path: this.metricName,
|
|
92
|
-
unit: this.unit,
|
|
93
|
-
op: this.op,
|
|
94
|
-
clusterRollup: this.clusterRollup,
|
|
95
|
-
holeHandling: this.holeHandling
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
cln._value = this._value;
|
|
99
|
-
|
|
100
|
-
if(this.op === 'TIME_AVERAGE') {
|
|
101
|
-
cln._count = this._count;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return cln;
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
@@ -1,308 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright (c) AppDynamics, Inc., and its affiliates
|
|
3
|
-
2015
|
|
4
|
-
All Rights Reserved
|
|
5
|
-
*/
|
|
6
|
-
/* global process, require, exports */
|
|
7
|
-
'use strict';
|
|
8
|
-
|
|
9
|
-
var fs = require('fs');
|
|
10
|
-
var path = require('path');
|
|
11
|
-
var cp = require('child_process');
|
|
12
|
-
var cluster = require('cluster');
|
|
13
|
-
var jre = require('appdynamics-jre');
|
|
14
|
-
var proxy = require('appdynamics-proxy');
|
|
15
|
-
var ExceptionHandlers = require('../core/exception-handlers.js').ExceptionHandlers;
|
|
16
|
-
|
|
17
|
-
/*
|
|
18
|
-
* Autolaunching:
|
|
19
|
-
* - The proxy is not launched if "proxyAutolaunchDisabled" option is set
|
|
20
|
-
* to false.
|
|
21
|
-
* - Only master node autolaunches proxy, i.e. in case of cluster only
|
|
22
|
-
* one proxy instance is autolaunched.
|
|
23
|
-
*
|
|
24
|
-
* StartNodeRequest:
|
|
25
|
-
* - In case of cluster, only workers send StartNodeRequest
|
|
26
|
-
* - For the cases where cluster master cannot be identified there
|
|
27
|
-
* is a "monitorClusterMaster" option, which is false by default
|
|
28
|
-
* - nodeIndex parameter is calculated by master node, which writes
|
|
29
|
-
* files for each worker to pick up their indexes from
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
function ProxyLauncher(agent) {
|
|
33
|
-
this.agent = agent;
|
|
34
|
-
|
|
35
|
-
this.indexDir = undefined;
|
|
36
|
-
|
|
37
|
-
this.processProcess = undefined;
|
|
38
|
-
this.exceptionHandlers = undefined;
|
|
39
|
-
}
|
|
40
|
-
exports.ProxyLauncher = ProxyLauncher;
|
|
41
|
-
|
|
42
|
-
ProxyLauncher.prototype.init = function() {
|
|
43
|
-
var self = this;
|
|
44
|
-
self.indexDir = self.agent.tmpDir + '/index';
|
|
45
|
-
|
|
46
|
-
self.agent.once('nodeIndex', function(nodeIndex) {
|
|
47
|
-
self.exceptionHandlers = new ExceptionHandlers();
|
|
48
|
-
self.exceptionHandlers.init(
|
|
49
|
-
self.agent,
|
|
50
|
-
function(){
|
|
51
|
-
if (!cluster.isMaster) return;
|
|
52
|
-
self.agent.logger.info("Terminating proxy");
|
|
53
|
-
if (self.proxyProcess) {
|
|
54
|
-
self.proxyProcess.kill('SIGTERM');
|
|
55
|
-
}
|
|
56
|
-
self.clearProxyControlDirectory();
|
|
57
|
-
var proxyRuntimeDir = self.agent.proxyRuntimeDir;
|
|
58
|
-
var proxyPidFile = path.join(proxyRuntimeDir, 'proxy.pid');
|
|
59
|
-
self.clearProxyPID(proxyPidFile);
|
|
60
|
-
self.agent.emit('proxyTerminated');
|
|
61
|
-
},
|
|
62
|
-
function(e){
|
|
63
|
-
self.agent.logger.error('uncaughtException:');
|
|
64
|
-
self.agent.logger.error(e);
|
|
65
|
-
|
|
66
|
-
self.agent.backendConnector.proxyTransport.sendAppException(e);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
if (!self.copyCaCertKeystore()) {
|
|
70
|
-
self.agent.emit('launchProxy', nodeIndex);
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
self.agent.on('launchProxy', function(nodeIndex, force) {
|
|
75
|
-
if(!self.agent.opts.proxyAutolaunchDisabled) {
|
|
76
|
-
if(cluster.isMaster) {
|
|
77
|
-
self.agent.logger.info('launching proxy from master node ' + nodeIndex);
|
|
78
|
-
self.startProxy(nodeIndex, force);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// wait for proxy to launch
|
|
82
|
-
self.agent.timers.setTimeout(function() {
|
|
83
|
-
self.agent.emit('proxyStarted', nodeIndex);
|
|
84
|
-
}, 5000);
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
// need some time to be able to identify cluster master
|
|
88
|
-
// by checking if any workers have been forked
|
|
89
|
-
self.agent.timers.setTimeout(function() {
|
|
90
|
-
self.agent.emit('proxyStarted', nodeIndex);
|
|
91
|
-
}, 1000);
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
ProxyLauncher.prototype.start = function() {
|
|
97
|
-
var self = this;
|
|
98
|
-
var nodeIndex;
|
|
99
|
-
|
|
100
|
-
if(cluster.isMaster) {
|
|
101
|
-
nodeIndex = self.agent.opts.nodeIndex || 0;
|
|
102
|
-
self.agent.emit('nodeIndex', nodeIndex);
|
|
103
|
-
}
|
|
104
|
-
else if ('pm_id' in process.env && !isNaN(process.env.pm_id)) {
|
|
105
|
-
nodeIndex = Number(process.env.pm_id);
|
|
106
|
-
self.agent.emit('nodeIndex', nodeIndex);
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
self.agent.timers.setTimeout(function() {
|
|
110
|
-
self.readNodeIndex(function(nodeIndex) {
|
|
111
|
-
if(nodeIndex !== null) {
|
|
112
|
-
self.agent.emit('nodeIndex', nodeIndex);
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
self.agent.timers.setTimeout(function() {
|
|
116
|
-
self.readNodeIndex(function(nodeIndex) {
|
|
117
|
-
if(nodeIndex !== null) {
|
|
118
|
-
self.agent.emit('nodeIndex', nodeIndex);
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
// return pid instead of index if indexing is not available,
|
|
122
|
-
// e.g. this process is forked from a worker
|
|
123
|
-
self.agent.emit('nodeIndex', process.pid);
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
}, 4000);
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
}, 1000);
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
/* istanbul ignore next */
|
|
134
|
-
ProxyLauncher.prototype.readNodeIndex = function(callback) {
|
|
135
|
-
var self = this;
|
|
136
|
-
|
|
137
|
-
var callbackCalled = false;
|
|
138
|
-
function callbackOnce(ret) {
|
|
139
|
-
if(!callbackCalled) {
|
|
140
|
-
callbackCalled = true;
|
|
141
|
-
callback(ret);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
fs.exists(self.indexDir, function(exists) {
|
|
146
|
-
if(!exists) return;
|
|
147
|
-
|
|
148
|
-
fs.readdir(self.indexDir, function(err, indexFiles) {
|
|
149
|
-
if(err) return self.agent.logger.error(err);
|
|
150
|
-
|
|
151
|
-
indexFiles.forEach(function(indexFile) {
|
|
152
|
-
var nodeIndex = parseInt(indexFile.split('.')[0]);
|
|
153
|
-
if(!isNaN(nodeIndex)) {
|
|
154
|
-
fs.readFile(self.indexDir + '/' + indexFile, function(err, pid) {
|
|
155
|
-
if(err) return self.agent.logger.error(err);
|
|
156
|
-
|
|
157
|
-
if(pid == process.pid) {
|
|
158
|
-
callbackOnce(nodeIndex);
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
self.agent.timers.setTimeout(function() {
|
|
167
|
-
callbackOnce(null);
|
|
168
|
-
}, 2000);
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
/* istanbul ignore next */
|
|
172
|
-
ProxyLauncher.prototype.isProxyRunning = function(proxyPidFile) {
|
|
173
|
-
if (fs.existsSync(proxyPidFile)) {
|
|
174
|
-
try {
|
|
175
|
-
var proxyPid = fs.readFileSync(proxyPidFile, 'utf-8');
|
|
176
|
-
process.kill(proxyPid, 0);
|
|
177
|
-
return true;
|
|
178
|
-
} catch (e) {
|
|
179
|
-
// proxy process went away; clean up stale pid file
|
|
180
|
-
fs.unlinkSync(proxyPidFile);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
return false;
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
/* istanbul ignore next */
|
|
188
|
-
ProxyLauncher.prototype.storeProxyPID = function(proxyPidFile, pid) {
|
|
189
|
-
fs.writeFileSync(proxyPidFile, pid);
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
/* istanbul ignore next */
|
|
193
|
-
ProxyLauncher.prototype.clearProxyPID = function(proxyPidFile) {
|
|
194
|
-
try {
|
|
195
|
-
fs.unlinkSync(proxyPidFile);
|
|
196
|
-
} catch (e) {
|
|
197
|
-
this.agent.logger.warn('unable to delete proxy PID file: ' + e.message);
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
ProxyLauncher.prototype.quote = function(path) {
|
|
202
|
-
var self = this;
|
|
203
|
-
if (!self.agent.isWindows || path.indexOf(' ') === -1) {
|
|
204
|
-
return path;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
return '"' + path + '"';
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
ProxyLauncher.prototype.startProxy = function(nodeIndex, force) {
|
|
211
|
-
var self = this;
|
|
212
|
-
|
|
213
|
-
var opts = self.agent.opts;
|
|
214
|
-
|
|
215
|
-
var proxyDir = proxy.dir;
|
|
216
|
-
var proxyCommDir = self.agent.proxyCtrlDir;
|
|
217
|
-
var proxyLogsDir = self.agent.proxyLogsDir;
|
|
218
|
-
var proxyRuntimeDir = self.agent.proxyRuntimeDir;
|
|
219
|
-
var proxyPidFile = path.join(proxyRuntimeDir, 'proxy.pid');
|
|
220
|
-
|
|
221
|
-
if (!force && self.isProxyRunning(proxyPidFile)) {
|
|
222
|
-
self.agent.logger.info('reusing existing proxy process');
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
self.clearProxyDirectories(function() {
|
|
227
|
-
var proxyArgs = [
|
|
228
|
-
'-d', self.quote(proxyDir),
|
|
229
|
-
'-r', self.quote(proxyRuntimeDir),
|
|
230
|
-
'-j', self.quote(jre.dir),
|
|
231
|
-
'--'
|
|
232
|
-
];
|
|
233
|
-
if (self.agent.isWindows) {
|
|
234
|
-
proxyArgs.push(
|
|
235
|
-
self.quote(proxyLogsDir),
|
|
236
|
-
opts.proxyCommPort || 10101
|
|
237
|
-
);
|
|
238
|
-
} else {
|
|
239
|
-
proxyArgs.push(
|
|
240
|
-
self.quote(proxyCommDir),
|
|
241
|
-
self.quote(proxyLogsDir),
|
|
242
|
-
'-Dregister=false'
|
|
243
|
-
);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
var proxyOutput;
|
|
247
|
-
|
|
248
|
-
self.agent.logger.info("proxyArgs = " + JSON.stringify(proxyArgs, null, " "));
|
|
249
|
-
|
|
250
|
-
if(self.agent.opts.proxyOutEnabled) {
|
|
251
|
-
proxyOutput = fs.openSync(proxyLogsDir + "/proxy.out", 'w');
|
|
252
|
-
self.proxyProcess = self.spawn(proxyDir, proxyArgs, ['ignore', proxyOutput, proxyOutput]);
|
|
253
|
-
}
|
|
254
|
-
else {
|
|
255
|
-
self.proxyProcess = self.spawn(proxyDir, proxyArgs, 'ignore');
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
self.storeProxyPID(proxyPidFile, self.proxyProcess.pid);
|
|
259
|
-
|
|
260
|
-
self.agent.logger.info("Proxy logging to: " + proxyLogsDir);
|
|
261
|
-
self.agent.logger.info("Proxy spawned!");
|
|
262
|
-
self.proxyProcess.unref();
|
|
263
|
-
});
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
/* istanbul ignore next */
|
|
267
|
-
ProxyLauncher.prototype.clearProxyDirectories = function(cb) {
|
|
268
|
-
var proxyCommDir = this.agent.proxyCtrlDir;
|
|
269
|
-
var proxyLogsDir = this.agent.proxyLogsDir;
|
|
270
|
-
cp.exec('rm -rf ' + proxyCommDir + '/* ' + proxyLogsDir + '/*', cb);
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
/* istanbul ignore next */
|
|
274
|
-
ProxyLauncher.prototype.clearProxyControlDirectory = function() {
|
|
275
|
-
cp.exec('rm -rf ' + this.agent.proxyCtrlDir + '/*');
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
/* istanbul ignore next */
|
|
279
|
-
ProxyLauncher.prototype.spawn = function(proxyDir, proxyArgs, input) {
|
|
280
|
-
var proxyCmd = path.join(proxyDir, "runProxy");
|
|
281
|
-
if (this.agent.isWindows) {
|
|
282
|
-
proxyCmd = this.quote(proxyCmd + '.cmd');
|
|
283
|
-
}
|
|
284
|
-
this.agent.logger.debug("cmdLine = " + proxyCmd + " " + proxyArgs.join(" "));
|
|
285
|
-
return cp.spawn(proxyCmd, proxyArgs, {
|
|
286
|
-
detached: false, stdio: input, shell: !!this.agent.isWindows
|
|
287
|
-
});
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
ProxyLauncher.prototype.copyCaCertKeystore = function() {
|
|
291
|
-
if (!this.agent.opts.certificateFile) return;
|
|
292
|
-
var self = this;
|
|
293
|
-
var pathToJreIs = require.resolve('appdynamics-jre');
|
|
294
|
-
var destKeystoreName = pathToJreIs.substring(0, pathToJreIs.indexOf('appdynamics-jre')) + 'appdynamics-jre/jre/lib/security/cacerts';
|
|
295
|
-
var sourceStream = fs.createReadStream(self.agent.opts.certificateFile);
|
|
296
|
-
sourceStream.on('error', function(error) {
|
|
297
|
-
self.agent.logger.error('Error in reading from the certificate file' + error);
|
|
298
|
-
return 'Failed';
|
|
299
|
-
});
|
|
300
|
-
var destinationStream = fs.createWriteStream(destKeystoreName);
|
|
301
|
-
destinationStream.on('error', function(error) {
|
|
302
|
-
self.agent.logger.error('Error in creating the destination keystore ' + error);
|
|
303
|
-
return 'Failed';
|
|
304
|
-
});
|
|
305
|
-
sourceStream.pipe(destinationStream);
|
|
306
|
-
self.agent.logger.info('SSL keystore copy completed');
|
|
307
|
-
return;
|
|
308
|
-
};
|