newrelic 6.7.0 → 6.10.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.
@@ -381,8 +381,10 @@ Transaction.prototype.isIgnored = function getIgnore() {
381
381
  */
382
382
  Transaction.prototype.finalizeNameFromUri = finalizeNameFromUri
383
383
  function finalizeNameFromUri(requestURL, statusCode) {
384
- logger.trace({requestURL: requestURL, statusCode: statusCode, transactionId: this.id,
385
- transactionName: this.name}, 'Setting transaction name')
384
+ if (logger.traceEnabled()) {
385
+ logger.trace({requestURL: requestURL, statusCode: statusCode, transactionId: this.id,
386
+ transactionName: this.name}, 'Setting transaction name')
387
+ }
386
388
 
387
389
  this.url = urltils.scrub(requestURL)
388
390
  this.statusCode = statusCode
@@ -404,6 +406,20 @@ function finalizeNameFromUri(requestURL, statusCode) {
404
406
  'request.parameters.' + key,
405
407
  params[key]
406
408
  )
409
+
410
+ const segment = this.agent.tracer.getSegment()
411
+
412
+ if (!segment) {
413
+ logger
414
+ .trace('Active segment not available, not adding request.parameters attribute for %s',
415
+ key)
416
+ } else {
417
+ segment.attributes.addAttribute(
418
+ DESTS.NONE,
419
+ 'request.parameters.' + key,
420
+ params[key]
421
+ )
422
+ }
407
423
  }
408
424
  }
409
425
  }, this)
@@ -426,11 +442,26 @@ function finalizeNameFromUri(requestURL, statusCode) {
426
442
  }
427
443
 
428
444
  this.baseSegment && this._markAsWeb(requestURL)
429
- logger.trace({
430
- transactionId: this.id,
431
- transactionName: this.name,
432
- ignore: this.ignore
433
- }, 'Finished setting transaction name from Uri')
445
+
446
+ this._copyNameToActiveSpan(this.name)
447
+
448
+ if (logger.traceEnabled()) {
449
+ logger.trace({
450
+ transactionId: this.id,
451
+ transactionName: this.name,
452
+ ignore: this.ignore
453
+ }, 'Finished setting transaction name from Uri')
454
+ }
455
+ }
456
+
457
+ Transaction.prototype._copyNameToActiveSpan = function _copyNameToActiveSpan(name) {
458
+ const spanContext = this.agent.tracer.getSpanContext()
459
+ if (!spanContext) {
460
+ logger.trace('Span context not available, not adding transaction.name attribute for %s', name)
461
+ return
462
+ }
463
+
464
+ spanContext.addIntrinsicAttribute('transaction.name', name)
434
465
  }
435
466
 
436
467
  /**
@@ -449,6 +480,21 @@ Transaction.prototype._markAsWeb = function _markAsWeb(rawURL) {
449
480
  'request.parameters.' + key,
450
481
  params[key]
451
482
  )
483
+
484
+ const segment = this.agent.tracer.getSegment()
485
+
486
+ if (!segment) {
487
+ logger
488
+ .trace(
489
+ 'Active segment not available, not adding request.parameters span attribute for %s',
490
+ key)
491
+ } else {
492
+ segment.attributes.addAttribute(
493
+ DESTS.NONE,
494
+ 'request.parameters.' + key,
495
+ params[key]
496
+ )
497
+ }
452
498
  }
453
499
  }
454
500
  this.baseSegment.markAsWeb()
@@ -490,11 +536,15 @@ Transaction.prototype.finalizeName = function finalizeName(name) {
490
536
 
491
537
  this.baseSegment && this.baseSegment.setNameFromTransaction()
492
538
 
493
- logger.trace({
494
- transactionId: this.id,
495
- transactionName: this.name,
496
- ignore: this.ignore
497
- }, 'Finished setting transaction name from string')
539
+ this._copyNameToActiveSpan(this.name)
540
+
541
+ if (logger.traceEnabled()) {
542
+ logger.trace({
543
+ transactionId: this.id,
544
+ transactionName: this.name,
545
+ ignore: this.ignore
546
+ }, 'Finished setting transaction name from string')
547
+ }
498
548
  }
499
549
 
500
550
  /**
@@ -692,10 +742,20 @@ function _linkExceptionToSegment(exception) {
692
742
  return
693
743
  }
694
744
 
745
+ const config = this.agent.config
746
+
695
747
  // Add error attributes to the span
696
- const details = exception.getErrorDetails(this.agent.config)
697
- segment.addAttribute('error.message', details.message)
698
- segment.addAttribute('error.class', details.type)
748
+ const details = exception.getErrorDetails(config)
749
+ segment.addSpanAttribute('error.message', details.message)
750
+ segment.addSpanAttribute('error.class', details.type)
751
+
752
+ const isExpected =
753
+ errorHelper.isExpectedErrorClass(config, details.type) ||
754
+ errorHelper.isExpectedErrorMessage(config, details.type, details.message)
755
+
756
+ if (isExpected) {
757
+ segment.addSpanAttribute('error.expected', isExpected)
758
+ }
699
759
 
700
760
  // Add the span/segment ID to the exception as agent attributes
701
761
  exception.agentAttributes.spanId = segment.id
@@ -1233,6 +1293,14 @@ function addRequestParameters(requestParameters) {
1233
1293
  'request.parameters.' + key,
1234
1294
  requestParameters[key]
1235
1295
  )
1296
+
1297
+ const segment = this.baseSegment
1298
+
1299
+ segment.attributes.addAttribute(
1300
+ DESTS.NONE,
1301
+ 'request.parameters.' + key,
1302
+ requestParameters[key]
1303
+ )
1236
1304
  }
1237
1305
  }
1238
1306
  }
@@ -41,6 +41,8 @@ function Trace(transaction) {
41
41
  'host.displayName',
42
42
  displayName
43
43
  )
44
+
45
+ this.displayName = displayName
44
46
  }
45
47
  this.domain = null
46
48
  }
@@ -82,6 +84,26 @@ Trace.prototype.generateSpanEvents = function generateSpanEvents() {
82
84
  const spanAggregator = this.transaction.agent.spanEventAggregator
83
85
 
84
86
  const children = this.root.getChildren()
87
+
88
+ if (children.length > 0) {
89
+ // At the point where these attributes are available, we only have a
90
+ // root span. Adding attributes to first non-root span here.
91
+ const attributeMap = {
92
+ 'host.displayName': this.displayName,
93
+ 'parent.type': this.transaction.parentType,
94
+ 'parent.app': this.transaction.parentApp,
95
+ 'parent.account': this.transaction.parentAcct,
96
+ 'parent.transportType': this.transaction.parentTransportType,
97
+ 'parent.transportDuration': this.transaction.parentTransportDuration
98
+ }
99
+
100
+ for (const [key, value] of Object.entries(attributeMap)) {
101
+ if (value !== null) {
102
+ children[0].addSpanAttribute(key, value)
103
+ }
104
+ }
105
+ }
106
+
85
107
  for (let i = 0; i < children.length; ++i) {
86
108
  toProcess.push(new DTTraceNode(children[i], this.transaction.parentSpanId, true))
87
109
  }
@@ -6,8 +6,9 @@ const Timer = require('../../timer')
6
6
  const urltils = require('../../util/urltils')
7
7
  const hashes = require('../../util/hashes')
8
8
 
9
- const {Attributes, MAXIMUM_CUSTOM_ATTRIBUTES} = require('../../attributes')
9
+ const {Attributes} = require('../../attributes')
10
10
  const ExclusiveCalculator = require('./exclusive-time-calculator')
11
+ const SpanContext = require('../../spans/span-context')
11
12
 
12
13
  const NAMES = require('../../metrics/names')
13
14
  const INSTANCE_UNKNOWN = 'unknown'
@@ -52,7 +53,6 @@ function TraceSegment(transaction, name, recorder) {
52
53
  }
53
54
 
54
55
  this.attributes = new Attributes(ATTRIBUTE_SCOPE)
55
- this.customAttributes = new Attributes(ATTRIBUTE_SCOPE, MAXIMUM_CUSTOM_ATTRIBUTES)
56
56
 
57
57
  this.children = []
58
58
 
@@ -77,6 +77,17 @@ function TraceSegment(transaction, name, recorder) {
77
77
  this.probe('new TraceSegment')
78
78
  }
79
79
 
80
+ TraceSegment.prototype.getSpanContext = function getSpanContext() {
81
+ const config = this.transaction.agent.config
82
+ const spansEnabled = config.distributed_tracing.enabled && config.span_events.enabled
83
+
84
+ if (!this._spanContext && spansEnabled) {
85
+ this._spanContext = new SpanContext()
86
+ }
87
+
88
+ return this._spanContext
89
+ }
90
+
80
91
  TraceSegment.prototype.addAttribute =
81
92
  function addAttribute(key, value, truncateExempt = false) {
82
93
  this.attributes.addAttribute(
@@ -87,13 +98,9 @@ function addAttribute(key, value, truncateExempt = false) {
87
98
  )
88
99
  }
89
100
 
90
- TraceSegment.prototype.getAttributes = function getAttributes() {
91
- return this.attributes.get(DESTINATIONS.TRANS_SEGMENT)
92
- }
93
-
94
- TraceSegment.prototype.addCustomSpanAttribute =
95
- function addCustomSpanAttribute(key, value, truncateExempt = false) {
96
- this.customAttributes.addAttribute(
101
+ TraceSegment.prototype.addSpanAttribute =
102
+ function addSpanAttribute(key, value, truncateExempt = false) {
103
+ this.attributes.addAttribute(
97
104
  DESTINATIONS.SPAN_EVENT,
98
105
  key,
99
106
  value,
@@ -101,6 +108,18 @@ function addCustomSpanAttribute(key, value, truncateExempt = false) {
101
108
  )
102
109
  }
103
110
 
111
+ TraceSegment.prototype.addSpanAttributes =
112
+ function addSpanAttributes(attributes) {
113
+ this.attributes.addAttributes(
114
+ DESTINATIONS.SPAN_EVENT,
115
+ attributes
116
+ )
117
+ }
118
+
119
+ TraceSegment.prototype.getAttributes = function getAttributes() {
120
+ return this.attributes.get(DESTINATIONS.TRANS_SEGMENT)
121
+ }
122
+
104
123
  TraceSegment.prototype.getSpanId = function getSpanId() {
105
124
  const conf = this.transaction.agent.config
106
125
  const enabled = conf.span_events.enabled && conf.distributed_tracing.enabled
@@ -21,6 +21,7 @@ function Tracer(agent) {
21
21
 
22
22
  Tracer.prototype.getTransaction = getTransaction
23
23
  Tracer.prototype.getSegment = getSegment
24
+ Tracer.prototype.getSpanContext = getSpanContext
24
25
  Tracer.prototype.createSegment = createSegment
25
26
  Tracer.prototype.addSegment = addSegment
26
27
  Tracer.prototype.transactionProxy = transactionProxy
@@ -61,6 +62,10 @@ function getSegment() {
61
62
  return this.segment
62
63
  }
63
64
 
65
+ function getSpanContext() {
66
+ return this.segment && this.segment.getSpanContext()
67
+ }
68
+
64
69
  function createSegment(name, recorder, _parent) {
65
70
  var parent = _parent || this.segment
66
71
  if (!parent || !parent.transaction.isActive()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "newrelic",
3
- "version": "6.7.0",
3
+ "version": "6.10.0",
4
4
  "author": "New Relic Node.js agent team <nodejs@newrelic.com>",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "contributors": [
@@ -83,6 +83,21 @@
83
83
  "name": "Michael Goin",
84
84
  "email": "mgoin@newrelic.com",
85
85
  "web": "https://newrelic.com"
86
+ },
87
+ {
88
+ "name": "Alan Storm",
89
+ "email": "astorm@newrelic.com",
90
+ "web": "https://newrelic.com"
91
+ },
92
+ {
93
+ "name": "Carlo Pearson",
94
+ "email": "cpearson@newrelic.com",
95
+ "web": "https://newrelic.com"
96
+ },
97
+ {
98
+ "name": "Nick Tzaperas",
99
+ "email": "ntzaperas@newrelic.com",
100
+ "web": "https://newrelic.com"
86
101
  }
87
102
  ],
88
103
  "description": "New Relic agent",
@@ -108,7 +123,7 @@
108
123
  "clean": "./bin/clean.sh",
109
124
  "docker-env": "./bin/docker-env-vars.sh",
110
125
  "docs": "npm ci && jsdoc -c ./jsdoc-conf.json --private -r .",
111
- "integration": "npm run prepare-test && npm run sub-install && time tap --no-esm test/integration/**/**/*.tap.js --timeout=120 --no-coverage",
126
+ "integration": "npm run prepare-test && npm run sub-install && time tap --no-esm test/integration/**/**/*.tap.js --timeout=180 --no-coverage",
112
127
  "prepare-test": "npm ci && npm run ca-gen && npm run ssl && npm run docker-env",
113
128
  "lint": "eslint ./*.js lib test",
114
129
  "public-docs": "npm ci && jsdoc -c ./jsdoc-conf.json --tutorials examples/shim api.js lib/shim/ lib/transaction/handle.js && cp examples/shim/*.png out/",
@@ -118,7 +133,7 @@
118
133
  "ssl": "./bin/ssl.sh",
119
134
  "sub-install": "node test/bin/install_sub_deps",
120
135
  "test": "npm run integration && npm run unit",
121
- "unit": "rm -f newrelic_agent.log && time tap --test-regex='(\\/|^test\\/unit\\/.*\\.test\\.js)$' --timeout=120 --no-coverage",
136
+ "unit": "rm -f newrelic_agent.log && time tap --test-regex='(\\/|^test\\/unit\\/.*\\.test\\.js)$' --timeout=180 --no-coverage",
122
137
  "update-cross-agent-tests": "./bin/update-cats.sh",
123
138
  "versioned-tests": "./bin/run-versioned-tests.sh",
124
139
  "versioned": "npm run prepare-test && time ./bin/run-versioned-tests.sh"
@@ -127,27 +142,27 @@
127
142
  "newrelic-naming-rules": "./bin/test-naming-rules.js"
128
143
  },
129
144
  "dependencies": {
130
- "@grpc/grpc-js": "1.0.3",
131
- "@grpc/proto-loader": "^0.5.3",
145
+ "@grpc/grpc-js": "1.0.4",
146
+ "@grpc/proto-loader": "^0.5.4",
132
147
  "@newrelic/aws-sdk": "^1.1.1",
133
148
  "@newrelic/koa": "^3.0.0",
134
149
  "@newrelic/superagent": "^2.0.1",
135
150
  "@tyriar/fibonacci-heap": "^2.0.7",
136
151
  "async": "^2.1.4",
137
152
  "concat-stream": "^2.0.0",
138
- "escodegen": "^1.11.1",
153
+ "escodegen": "^1.14.1",
139
154
  "esprima": "^4.0.1",
140
155
  "https-proxy-agent": "^4.0.0",
141
156
  "json-stringify-safe": "^5.0.0",
142
- "readable-stream": "^3.1.1",
157
+ "readable-stream": "^3.6.0",
143
158
  "semver": "^5.3.0"
144
159
  },
145
160
  "optionalDependencies": {
146
- "@newrelic/native-metrics": "^5.0.0"
161
+ "@newrelic/native-metrics": "^5.1.0"
147
162
  },
148
163
  "devDependencies": {
149
164
  "@newrelic/proxy": "^2.0.0",
150
- "@newrelic/test-utilities": "^3.1.0",
165
+ "@newrelic/test-utilities": "^3.3.0",
151
166
  "JSV": "~4.0.2",
152
167
  "architect": "*",
153
168
  "benchmark": "^2.1.4",
package/.eslintignore DELETED
@@ -1 +0,0 @@
1
- **/node_modules/**
package/.eslintrc.js DELETED
@@ -1,67 +0,0 @@
1
- module.exports = {
2
- "env": {
3
- "es6": true,
4
- "node": true,
5
- "browser": false
6
- },
7
- "parserOptions": {
8
- "ecmaVersion": 6
9
- },
10
- "ignorePatterns": ["invalid-json/"],
11
- "rules": {
12
- "indent": ["warn", 2, {"SwitchCase": 1}],
13
- "brace-style": "error",
14
- "comma-dangle": "off",
15
- "comma-style": ["error", "last"],
16
- "consistent-return": "off",
17
- "curly": "off",
18
- "eol-last": "error",
19
- "eqeqeq": ["error", "smart"],
20
- "camelcase": ["off", {"properties": "never"}],
21
- "dot-notation": "error",
22
- "func-names": "error",
23
- "guard-for-in": "error",
24
- "key-spacing": ["off", { "beforeColon": false }],
25
- "max-len": ["error", 100, { "ignoreUrls": true }],
26
- "max-nested-callbacks": ["error", 3],
27
- "max-params": ["error", 5],
28
- "new-cap": "error",
29
- "no-console": "warn",
30
- "no-debugger": "error",
31
- "no-else-return": "error",
32
- "no-floating-decimal": "error",
33
- "no-lonely-if": "error",
34
- "no-mixed-requires": "error",
35
- "no-multiple-empty-lines": "error",
36
- "no-multi-spaces": ["off", { "ignoreEOLComments": true }],
37
- "no-new": "error",
38
- "no-new-func": "warn",
39
- "no-shadow": ["warn", {"allow": ["shim"]}],
40
- "no-undef": "error",
41
- "no-unused-vars": "error",
42
- "no-use-before-define": ["off", {"functions": false}],
43
- "one-var": ["off", "never"],
44
- "padded-blocks": ["error", "never"],
45
- "radix": "error",
46
- "semi": ["error", "never"],
47
- "space-before-function-paren": ["error", "never"],
48
- "keyword-spacing": "error",
49
- "space-before-blocks": "error",
50
- "space-infix-ops": "error",
51
- "spaced-comment": "error",
52
- "space-unary-ops": "error",
53
- "strict": "error",
54
- "quote-props": [ "off", "consistent-as-needed" ],
55
- "quotes": ["off", "single"],
56
- "use-isnan": "error",
57
- "wrap-iife": "error"
58
- },
59
- "overrides": [
60
- {
61
- "files": ["test/integration/*.tap.js", "test/integration/*/*.tap.js", "test/integration/core/exec-me.js"],
62
- "rules": {
63
- "no-console": ["off"]
64
- }
65
- }
66
- ]
67
- }
@@ -1,5 +0,0 @@
1
- ## CHANGE LOG
2
-
3
- ## INTERNAL LINKS
4
-
5
- ## NOTES
package/.travis.yml DELETED
@@ -1,40 +0,0 @@
1
- language: generic
2
- env:
3
- global:
4
- - MONGODB=2.6.11
5
- matrix:
6
- # NODE 8
7
- - NR_NODE_VERSION=8 SUITE=smoke
8
- - NR_NODE_VERSION=8 SUITE=unit
9
- - NR_NODE_VERSION=8 SUITE=integration
10
- - NR_NODE_VERSION=8 SUITE=versioned
11
- # NODE 10
12
- - NR_NODE_VERSION=10 SUITE=smoke
13
- - NR_NODE_VERSION=10 SUITE=unit
14
- - NR_NODE_VERSION=10 SUITE=integration
15
- - NR_NODE_VERSION=10 SUITE=versioned
16
- # NODE 12 --
17
- - NR_NODE_VERSION=12 SUITE=smoke
18
- - NR_NODE_VERSION=12 SUITE=unit
19
- - NR_NODE_VERSION=12 SUITE=integration
20
- - NR_NODE_VERSION=12 SUITE=lint
21
- - NR_NODE_VERSION=12 SUITE=versioned
22
- services:
23
- - memcached
24
- - mysql
25
- - redis
26
- - postgresql
27
- - rabbitmq
28
- addons:
29
- apt:
30
- packages:
31
- - rabbitmq-server
32
- before_install:
33
- - source ./bin/travis-node.sh
34
- - ./bin/travis-setup.sh
35
- install: if [ "$SUITE" != "smoke" ]; then npm ci; fi
36
- cache:
37
- directories:
38
- - "$HOME/.npm"
39
- script: npm run $SUITE
40
- after_script: find /home/travis/.npm/_logs -type f -exec cat '{}' +