newrelic 2.0.0 → 2.2.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/.eslintrc +1 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +5 -0
- package/NEWS.md +75 -0
- package/README.md +24 -12
- package/api.js +74 -29
- package/index.js +6 -2
- package/lib/agent.js +15 -3
- package/lib/collector/api.js +11 -9
- package/lib/collector/facts.js +9 -9
- package/lib/config.default.js +24 -2
- package/lib/config.js +70 -7
- package/lib/db/parse-sql.js +3 -0
- package/lib/db/tracer.js +3 -3
- package/lib/feature_flags.js +1 -0
- package/lib/instrumentation/core/async_hooks.js +92 -0
- package/lib/instrumentation/core/child_process.js +35 -0
- package/lib/instrumentation/core/globals.js +4 -23
- package/lib/instrumentation/core/http.js +1 -1
- package/lib/instrumentation/hapi.js +67 -33
- package/lib/instrumentation/ioredis.js +1 -6
- package/lib/metrics/names.js +7 -2
- package/lib/shim/datastore-shim.js +13 -1
- package/lib/shim/shim.js +46 -8
- package/lib/shim/webframework-shim.js +4 -2
- package/lib/stats/index.js +1 -1
- package/lib/system-info.js +21 -42
- package/lib/transaction/handle.js +14 -0
- package/lib/transaction/index.js +10 -2
- package/lib/transaction/tracer/index.js +1 -0
- package/lib/util/hashes.js +8 -1
- package/lib/util/logger.js +4 -4
- package/lib/util/sql/obfuscate.js +10 -4
- package/lib/utilization/aws-info.js +46 -0
- package/lib/utilization/azure-info.js +54 -0
- package/lib/utilization/common.js +106 -0
- package/lib/utilization/docker-info.js +100 -0
- package/lib/utilization/gcp-info.js +56 -0
- package/lib/utilization/index.js +28 -0
- package/lib/utilization/pcf-info.js +38 -0
- package/newrelic.js +1 -2
- package/package.json +2 -1
- package/stub_api.js +26 -9
- package/lib/aws-info.js +0 -100
- package/lib/parse-dockerinfo.js +0 -57
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
var logger = require('../logger.js').child({component: 'pcf-info'})
|
|
4
|
+
var NAMES = require('../metrics/names.js')
|
|
5
|
+
var common = require('./common')
|
|
6
|
+
|
|
7
|
+
module.exports = fetchPCFInfo
|
|
8
|
+
|
|
9
|
+
function fetchPCFInfo(agent, callback) {
|
|
10
|
+
if (!agent.config.utilization || !agent.config.utilization.detect_pcf) {
|
|
11
|
+
return setImmediate(callback, null, null)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
var metadataMap = {
|
|
15
|
+
'CF_INSTANCE_GUID': 'cf_instance_guid',
|
|
16
|
+
'CF_INSTANCE_IP': 'cf_instance_ip',
|
|
17
|
+
'MEMORY_LIMIT': 'memory_limit'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
var results = {}
|
|
21
|
+
var keys = Object.keys(metadataMap)
|
|
22
|
+
for (var i = 0; i < keys.length; i++) {
|
|
23
|
+
var key = keys[i]
|
|
24
|
+
var value = process.env[key]
|
|
25
|
+
if (value == null) {
|
|
26
|
+
logger.trace('Could not find environment value for %s', key)
|
|
27
|
+
return setImmediate(callback, null, null)
|
|
28
|
+
}
|
|
29
|
+
if (!common.checkValueString(value)) {
|
|
30
|
+
logger.trace('Invalid environment value for %s: %j', key, value)
|
|
31
|
+
agent.metrics.getOrCreateMetric(NAMES.UTILIZATION.PCF_ERROR).incrementCallCount()
|
|
32
|
+
return setImmediate(callback, null, null)
|
|
33
|
+
}
|
|
34
|
+
results[metadataMap[key]] = value
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
setImmediate(callback, null, results)
|
|
38
|
+
}
|
package/newrelic.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
-
|
|
3
2
|
/**
|
|
4
3
|
* New Relic agent configuration.
|
|
5
4
|
*
|
|
6
|
-
* See lib/config.
|
|
5
|
+
* See lib/config.defaults.js in the agent distribution for a more complete
|
|
7
6
|
* description of configuration variables and their potential values.
|
|
8
7
|
*/
|
|
9
8
|
exports.config = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "newrelic",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"author": "New Relic Node.js agent team <nodejs@newrelic.com>",
|
|
5
5
|
"licenses": [
|
|
6
6
|
{
|
|
@@ -115,6 +115,7 @@
|
|
|
115
115
|
},
|
|
116
116
|
"devDependencies": {
|
|
117
117
|
"async": "^2.1.4",
|
|
118
|
+
"benchmark": "^2.1.4",
|
|
118
119
|
"bluebird": "^3.4.7",
|
|
119
120
|
"eslint": "^2.9.0",
|
|
120
121
|
"jsdoc": "^3.4.0",
|
package/stub_api.js
CHANGED
|
@@ -3,13 +3,16 @@
|
|
|
3
3
|
var logger = require('./lib/logger.js')
|
|
4
4
|
var RealAPI = require('./api.js')
|
|
5
5
|
var TransactionHandle = require('./lib/transaction/handle')
|
|
6
|
+
var util = require('util')
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
/* eslint-disable no-eval */
|
|
9
10
|
function stubFunction(name) {
|
|
10
|
-
return eval(
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
return eval(
|
|
12
|
+
"(function () {return function " + name + "() {" +
|
|
13
|
+
"logger.debug('Not calling " + name + " because New Relic is disabled.');" +
|
|
14
|
+
"}}())"
|
|
15
|
+
)
|
|
13
16
|
}
|
|
14
17
|
/* eslint-enable no-eval */
|
|
15
18
|
|
|
@@ -28,8 +31,22 @@ for (var i = 0; i < length; i++) {
|
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
Stub.prototype.createTracer = createTracer
|
|
31
|
-
Stub.prototype.createWebTransaction =
|
|
32
|
-
|
|
34
|
+
Stub.prototype.createWebTransaction = util.deprecate(
|
|
35
|
+
createWebTransaction, [
|
|
36
|
+
'API#createWebTransaction is being deprecated!',
|
|
37
|
+
'Please use API#startWebTransaction for transaction creation',
|
|
38
|
+
'and API#getTransaction for transaction management including',
|
|
39
|
+
'ending transactions.'
|
|
40
|
+
].join(' ')
|
|
41
|
+
)
|
|
42
|
+
Stub.prototype.createBackgroundTransaction = util.deprecate(
|
|
43
|
+
createBackgroundTransaction, [
|
|
44
|
+
'API#createBackgroundTransaction is being deprecated!',
|
|
45
|
+
'Please use API#startBackgroundTransaction for transaction creation',
|
|
46
|
+
'and API#getTransaction for transaction management including',
|
|
47
|
+
'ending transactions.'
|
|
48
|
+
].join(' ')
|
|
49
|
+
)
|
|
33
50
|
Stub.prototype.startWebTransaction = startWebTransaction
|
|
34
51
|
Stub.prototype.startBackgroundTransaction = startBackgroundTransaction
|
|
35
52
|
Stub.prototype.getTransaction = getTransaction
|
|
@@ -89,17 +106,17 @@ function startBackgroundTransaction(name, group, callback) {
|
|
|
89
106
|
// Normally the following call executes callback asynchronously
|
|
90
107
|
function shutdown(options, cb) {
|
|
91
108
|
logger.debug('Not calling shutdown because New Relic is disabled.')
|
|
92
|
-
|
|
109
|
+
|
|
93
110
|
var callback = cb
|
|
94
111
|
if (!callback) {
|
|
95
112
|
if (typeof options === 'function') {
|
|
96
113
|
callback = options
|
|
97
114
|
} else {
|
|
98
|
-
callback =
|
|
115
|
+
callback = function __NR_defaultCb() {}
|
|
99
116
|
}
|
|
100
117
|
}
|
|
101
|
-
|
|
102
|
-
|
|
118
|
+
|
|
119
|
+
setImmediate(callback)
|
|
103
120
|
}
|
|
104
121
|
|
|
105
122
|
module.exports = Stub
|
package/lib/aws-info.js
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
var logger = require('./logger.js').child({component: 'aws-info'})
|
|
4
|
-
var http = require('http')
|
|
5
|
-
var NAMES = require('./metrics/names.js')
|
|
6
|
-
var concat = require('concat-stream')
|
|
7
|
-
|
|
8
|
-
module.exports = fetchAWSInfo
|
|
9
|
-
module.exports.clearCache = function clearAWSCache() {
|
|
10
|
-
resultDict = null
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
var resultDict
|
|
14
|
-
|
|
15
|
-
function fetchAWSInfo(agent, callback) {
|
|
16
|
-
if (!agent.config.utilization || !agent.config.utilization.detect_aws) {
|
|
17
|
-
return callback(null)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
if (resultDict) {
|
|
21
|
-
return callback(resultDict)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
var awsQuery = module.exports._awsQuery
|
|
25
|
-
|
|
26
|
-
awsQuery('instance-type', agent, function getInstanceType(type) {
|
|
27
|
-
if (!type) return callback(null)
|
|
28
|
-
awsQuery('instance-id', agent, function getInstanceId(id) {
|
|
29
|
-
if (!id) return callback(null)
|
|
30
|
-
awsQuery('placement/availability-zone', agent, function getZone(zone) {
|
|
31
|
-
if (!zone) return callback(null)
|
|
32
|
-
resultDict = {
|
|
33
|
-
type: type,
|
|
34
|
-
id: id,
|
|
35
|
-
zone: zone
|
|
36
|
-
}
|
|
37
|
-
return callback(resultDict)
|
|
38
|
-
})
|
|
39
|
-
})
|
|
40
|
-
})
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
module.exports._awsQuery = function awsQuery(key, agent, callback) {
|
|
45
|
-
var instanceHost = '169.254.169.254'
|
|
46
|
-
var apiVersion = '2008-02-01'
|
|
47
|
-
var url = ['http:/', instanceHost, apiVersion, 'meta-data', key].join('/')
|
|
48
|
-
var req = http.get(url, function awsRequest(res) {
|
|
49
|
-
res.pipe(concat(respond))
|
|
50
|
-
function respond(data) {
|
|
51
|
-
var valid = checkResponseString(data)
|
|
52
|
-
if (!valid) {
|
|
53
|
-
var awsError = agent.metrics.getOrCreateMetric(NAMES.UTILIZATION.AWS_ERROR)
|
|
54
|
-
awsError.incrementCallCount()
|
|
55
|
-
logger.debug('Response for attribute ' + key + ': %s'
|
|
56
|
-
, data)
|
|
57
|
-
data = null
|
|
58
|
-
} else {
|
|
59
|
-
data = data.toString('utf8')
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
agent.removeListener('errored', abortRequest)
|
|
63
|
-
agent.removeListener('stopped', abortRequest)
|
|
64
|
-
callback(data)
|
|
65
|
-
}
|
|
66
|
-
})
|
|
67
|
-
req.setTimeout(1000, function awsTimeout() {
|
|
68
|
-
logger.debug('Request for attribute %s timed out', key)
|
|
69
|
-
callback(null)
|
|
70
|
-
})
|
|
71
|
-
req.on('error', function awsError(err) {
|
|
72
|
-
logger.debug('Message for attribute %s: %s', key, err.message)
|
|
73
|
-
callback(null)
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
agent.once('errored', abortRequest)
|
|
77
|
-
agent.once('stopped', abortRequest)
|
|
78
|
-
|
|
79
|
-
function abortRequest() {
|
|
80
|
-
logger.debug('Abborting request for attribute %s', key)
|
|
81
|
-
req.abort()
|
|
82
|
-
agent.removeListener('errored', abortRequest)
|
|
83
|
-
agent.removeListener('stopped', abortRequest)
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function checkResponseString(str) {
|
|
88
|
-
var validCharacters = /[0-9a-zA-Z_ ./-]/
|
|
89
|
-
var valid = str.length <= 255 && str.length > 0
|
|
90
|
-
|
|
91
|
-
var i = 0
|
|
92
|
-
var len = str.length
|
|
93
|
-
|
|
94
|
-
while (valid && i < len) {
|
|
95
|
-
valid = valid && (str[i] > 127 || String.fromCharCode(str[i]).match(validCharacters))
|
|
96
|
-
i++
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return valid
|
|
100
|
-
}
|
package/lib/parse-dockerinfo.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
var logger = require('./logger.js').child({component: 'dockerinfo'})
|
|
4
|
-
var NAMES = require('./metrics/names.js')
|
|
5
|
-
module.exports = parseDockerInfo
|
|
6
|
-
|
|
7
|
-
function parseDockerInfo(agent, data) {
|
|
8
|
-
if (!agent.config.utilization || !agent.config.utilization.detect_docker) return null
|
|
9
|
-
var cpuCgroup = parseCgroupIds(data).cpu
|
|
10
|
-
// if we can't parse the cgroups, or if the cpu is not in a cgroup
|
|
11
|
-
var dockerError = agent.metrics.getOrCreateMetric(NAMES.UTILIZATION.DOCKER_ERROR)
|
|
12
|
-
if (!cpuCgroup) {
|
|
13
|
-
logger.debug('Could not parse cgroup data from: ' + data)
|
|
14
|
-
dockerError.incrementCallCount()
|
|
15
|
-
return null
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// if cpu isn't in a cgroup
|
|
19
|
-
if (cpuCgroup === '/') return null
|
|
20
|
-
|
|
21
|
-
var patterns = [
|
|
22
|
-
/^\/docker\/([0-9a-f]+)$/, // docker native driver w/out systemd
|
|
23
|
-
/^\/system\.slice\/docker-([0-9a-f]+)\.scope$/, // with systemd
|
|
24
|
-
/^\/lxc\/([0-9a-f]+)$/ // docker lxc driver
|
|
25
|
-
]
|
|
26
|
-
for (var i = 0; i < patterns.length; i++) {
|
|
27
|
-
var pattern = patterns[i]
|
|
28
|
-
var matches = cpuCgroup.match(pattern)
|
|
29
|
-
if (matches) {
|
|
30
|
-
var id = matches[1]
|
|
31
|
-
if (id.length !== 64) {
|
|
32
|
-
dockerError.incrementCallCount()
|
|
33
|
-
logger.debug('Encountered a malformed docker id: ', id)
|
|
34
|
-
return null
|
|
35
|
-
}
|
|
36
|
-
return id
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
logger.debug('Unable to recognise cgroup format')
|
|
41
|
-
|
|
42
|
-
return null
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function parseCgroupIds(cgroupInfo) {
|
|
46
|
-
var cgroupIds = {}
|
|
47
|
-
cgroupInfo.split('\n').forEach(function parseCgroupInfo(line) {
|
|
48
|
-
var parts = line.split(':')
|
|
49
|
-
if (parts.length !== 3) return
|
|
50
|
-
var subsystems = parts[1]
|
|
51
|
-
var cgroupId = parts[2]
|
|
52
|
-
subsystems.split(',').forEach(function assignGroupIds(subsystem) {
|
|
53
|
-
cgroupIds[subsystem] = cgroupId
|
|
54
|
-
})
|
|
55
|
-
})
|
|
56
|
-
return cgroupIds
|
|
57
|
-
}
|