newrelic 8.2.0 → 8.5.1
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/NEWS.md +5061 -4963
- package/README.md +7 -6
- package/THIRD_PARTY_NOTICES.md +95 -68
- package/api.js +74 -68
- package/bin/test-naming-rules.js +22 -22
- package/lib/agent.js +4 -4
- package/lib/attributes.js +2 -2
- package/lib/collector/api.js +12 -12
- package/lib/collector/facts.js +2 -3
- package/lib/collector/http-agents.js +12 -11
- package/lib/collector/key-parser.js +1 -1
- package/lib/collector/remote-method.js +27 -26
- package/lib/config/attribute-filter.js +23 -23
- package/lib/config/default.js +26 -9
- package/lib/config/env.js +14 -4
- package/lib/config/hsm.js +1 -1
- package/lib/config/index.js +90 -69
- package/lib/config/lasp.js +3 -3
- package/lib/config/merge-server-config.js +1 -1
- package/lib/db/parse-sql.js +8 -8
- package/lib/db/parsed-statement.js +9 -8
- package/lib/db/query-parsers/sql.js +7 -7
- package/lib/db/query-sample.js +9 -9
- package/lib/db/query-trace-aggregator.js +4 -4
- package/lib/db/statement-matcher.js +5 -5
- package/lib/db/utils.js +1 -1
- package/lib/environment.js +43 -43
- package/lib/errors/error-collector.js +2 -2
- package/lib/errors/error-trace-aggregator.js +1 -1
- package/lib/errors/helper.js +3 -3
- package/lib/errors/index.js +17 -17
- package/lib/feature_flags.js +7 -5
- package/lib/header-attributes.js +6 -6
- package/lib/header-processing.js +1 -1
- package/lib/instrumentation/amqplib.js +26 -26
- package/lib/instrumentation/bluebird.js +3 -3
- package/lib/instrumentation/cassandra-driver.js +7 -3
- package/lib/instrumentation/connect.js +4 -4
- package/lib/instrumentation/core/async_hooks.js +6 -6
- package/lib/instrumentation/core/domain.js +2 -2
- package/lib/instrumentation/core/globals.js +1 -1
- package/lib/instrumentation/core/http-outbound.js +15 -84
- package/lib/instrumentation/core/http.js +34 -67
- package/lib/instrumentation/core/inspector.js +2 -2
- package/lib/instrumentation/core/timers.js +7 -7
- package/lib/instrumentation/core/zlib.js +2 -2
- package/lib/instrumentation/director.js +4 -4
- package/lib/instrumentation/express.js +8 -8
- package/lib/instrumentation/fastify/spec-builders.js +57 -47
- package/lib/instrumentation/fastify.js +111 -28
- package/lib/instrumentation/generic-pool.js +1 -1
- package/lib/instrumentation/hapi/hapi-17.js +11 -11
- package/lib/instrumentation/hapi/shared.js +1 -1
- package/lib/instrumentation/hapi.js +22 -22
- package/lib/instrumentation/ioredis.js +7 -7
- package/lib/instrumentation/memcached.js +7 -7
- package/lib/instrumentation/mongodb/common.js +73 -23
- package/lib/instrumentation/mongodb/v3-mongo.js +20 -1
- package/lib/instrumentation/mongodb/v4-mongo.js +6 -7
- package/lib/instrumentation/mysql.js +19 -19
- package/lib/instrumentation/oracle.js +15 -15
- package/lib/instrumentation/pg.js +4 -4
- package/lib/instrumentation/promise.js +46 -46
- package/lib/instrumentation/q.js +2 -2
- package/lib/instrumentation/redis.js +11 -11
- package/lib/instrumentation/restify.js +1 -1
- package/lib/instrumentation/undici.js +242 -0
- package/lib/instrumentation/vision.js +4 -4
- package/lib/instrumentation/when.js +3 -3
- package/lib/instrumentations.js +2 -1
- package/lib/logger.js +5 -5
- package/lib/metrics/index.js +15 -15
- package/lib/metrics/mapper.js +7 -7
- package/lib/metrics/names.js +6 -3
- package/lib/metrics/normalizer/rule.js +9 -9
- package/lib/metrics/normalizer/tx_segment.js +17 -17
- package/lib/metrics/normalizer.js +22 -22
- package/lib/metrics/recorders/custom.js +5 -5
- package/lib/metrics/recorders/generic.js +3 -3
- package/lib/metrics/recorders/http.js +7 -7
- package/lib/metrics/recorders/http_external.js +7 -7
- package/lib/metrics/recorders/message-transaction.js +5 -6
- package/lib/metrics/recorders/other.js +5 -5
- package/lib/parse-proc-cpuinfo.js +25 -19
- package/lib/parse-proc-meminfo.js +8 -2
- package/lib/prioritized-attributes.js +2 -2
- package/lib/priority-queue.js +10 -10
- package/lib/reservoir.js +3 -3
- package/lib/sampler.js +26 -26
- package/lib/shim/datastore-shim.js +35 -32
- package/lib/shim/index.js +2 -2
- package/lib/shim/message-shim.js +47 -47
- package/lib/shim/promise-shim.js +1 -1
- package/lib/shim/shim.js +61 -61
- package/lib/shim/specs/index.js +3 -3
- package/lib/shim/transaction-shim.js +44 -192
- package/lib/shim/webframework-shim.js +52 -52
- package/lib/spans/span-event-aggregator.js +62 -10
- package/lib/spans/span-event.js +1 -1
- package/lib/spans/streaming-span-attributes.js +1 -1
- package/lib/stats/apdex.js +2 -2
- package/lib/stats/index.js +2 -2
- package/lib/system-info.js +23 -23
- package/lib/timer.js +5 -5
- package/lib/transaction/dt-payload.js +1 -1
- package/lib/transaction/index.js +40 -40
- package/lib/transaction/name-state.js +14 -14
- package/lib/transaction/trace/exclusive-time-calculator.js +6 -6
- package/lib/transaction/trace/index.js +14 -14
- package/lib/transaction/trace/segment.js +18 -18
- package/lib/transaction/tracecontext.js +1 -1
- package/lib/transaction/tracer/index.js +53 -49
- package/lib/uninstrumented.js +7 -7
- package/lib/util/arity.js +2 -2
- package/lib/util/byte-limit.js +4 -4
- package/lib/util/cat.js +269 -24
- package/lib/util/codec.js +2 -2
- package/lib/util/copy.js +2 -2
- package/lib/util/deep-equal.js +10 -10
- package/lib/util/flatten.js +4 -4
- package/lib/util/hashes.js +14 -14
- package/lib/util/label-parser.js +17 -17
- package/lib/util/logger.js +24 -24
- package/lib/util/process-version.js +2 -2
- package/lib/util/properties.js +4 -4
- package/lib/util/sql/obfuscate.js +15 -15
- package/lib/util/stream-sink.js +3 -3
- package/lib/util/unwrapped-core.js +2 -2
- package/lib/util/urltils.js +16 -16
- package/lib/utilization/aws-info.js +7 -7
- package/lib/utilization/azure-info.js +6 -6
- package/lib/utilization/common.js +13 -13
- package/lib/utilization/docker-info.js +11 -11
- package/lib/utilization/gcp-info.js +4 -4
- package/lib/utilization/index.js +5 -5
- package/lib/utilization/pcf-info.js +9 -9
- package/package.json +13 -7
- package/stub_api.js +8 -8
package/lib/config/index.js
CHANGED
|
@@ -29,7 +29,6 @@ const mergeServerConfig = new MergeServerConfig()
|
|
|
29
29
|
const AZURE_APP_NAME = 'APP_POOL_ID'
|
|
30
30
|
const DEFAULT_MAX_PAYLOAD_SIZE_IN_BYTES = 1000000
|
|
31
31
|
const DEFAULT_CONFIG_PATH = require.resolve('./default')
|
|
32
|
-
const SPAN_EVENT_LIMIT = 1000
|
|
33
32
|
const BASE_CONFIG_PATH = require.resolve('../../newrelic')
|
|
34
33
|
const HAS_ARBITRARY_KEYS = new Set(['ignore_messages', 'expected_messages', 'labels'])
|
|
35
34
|
|
|
@@ -62,7 +61,7 @@ function isTruthular(setting) {
|
|
|
62
61
|
return false
|
|
63
62
|
}
|
|
64
63
|
|
|
65
|
-
|
|
64
|
+
const normalized = setting.toString().toLowerCase()
|
|
66
65
|
switch (normalized) {
|
|
67
66
|
case 'false':
|
|
68
67
|
case 'f':
|
|
@@ -183,7 +182,7 @@ function Config(config) {
|
|
|
183
182
|
analytic_event_data: this.transaction_events.max_samples_stored,
|
|
184
183
|
custom_event_data: this.custom_insights_events.max_samples_stored,
|
|
185
184
|
error_event_data: this.error_collector.max_event_samples_stored,
|
|
186
|
-
span_event_data:
|
|
185
|
+
span_event_data: this.span_events.max_samples_stored
|
|
187
186
|
}
|
|
188
187
|
}
|
|
189
188
|
}
|
|
@@ -246,11 +245,13 @@ Config.prototype.onConnect = function onConnect(json, recursion) {
|
|
|
246
245
|
this._fromServer(json, key)
|
|
247
246
|
}, this)
|
|
248
247
|
|
|
248
|
+
this._warnDeprecations()
|
|
249
|
+
|
|
249
250
|
this.emit('change', this)
|
|
250
251
|
}
|
|
251
252
|
|
|
252
253
|
Config.prototype._getMostSecure = function getMostSecure(key, currentVal, newVal) {
|
|
253
|
-
|
|
254
|
+
const filter = LASP_MAP[key] && LASP_MAP[key].filter
|
|
254
255
|
if (!this.security_policies_token || !filter) {
|
|
255
256
|
// If we aren't applying something vetted by security policies we
|
|
256
257
|
// just return the new value.
|
|
@@ -544,6 +545,13 @@ Config.prototype._fromServer = function _fromServer(params, key) {
|
|
|
544
545
|
this.logUnsupported(params, key)
|
|
545
546
|
break
|
|
546
547
|
|
|
548
|
+
// DT span event harvest config limits
|
|
549
|
+
case 'span_event_harvest_config':
|
|
550
|
+
this.span_event_harvest_config = {
|
|
551
|
+
...params[key]
|
|
552
|
+
}
|
|
553
|
+
break
|
|
554
|
+
|
|
547
555
|
// These settings are not allowed from the server.
|
|
548
556
|
case 'attributes.enabled':
|
|
549
557
|
case 'attributes.exclude':
|
|
@@ -578,7 +586,7 @@ Config.prototype._fromServer = function _fromServer(params, key) {
|
|
|
578
586
|
* @param {string} key Value we're looking to set.
|
|
579
587
|
*/
|
|
580
588
|
Config.prototype._alwaysUpdateIfChanged = function _alwaysUpdateIfChanged(json, key) {
|
|
581
|
-
|
|
589
|
+
const value = json[key]
|
|
582
590
|
if (value != null && this[key] !== value) {
|
|
583
591
|
if (Array.isArray(value) && Array.isArray(this[key])) {
|
|
584
592
|
value.forEach(function pushIfNew(element) {
|
|
@@ -622,7 +630,7 @@ Config.prototype._updateIfChanged = function _updateIfChanged(json, key) {
|
|
|
622
630
|
*/
|
|
623
631
|
Config.prototype._validateThenUpdateStatusCodes = _validateThenUpdateStatusCodes
|
|
624
632
|
function _validateThenUpdateStatusCodes(remote, local, remoteKey, localKey) {
|
|
625
|
-
|
|
633
|
+
const valueToTest = remote[remoteKey]
|
|
626
634
|
if (!Array.isArray(valueToTest)) {
|
|
627
635
|
logger.warn(
|
|
628
636
|
'Saw SSC (ignore|expect)_status_codes that is not an array, will not merge: %s',
|
|
@@ -666,7 +674,7 @@ function _validateThenUpdateStatusCodes(remote, local, remoteKey, localKey) {
|
|
|
666
674
|
Config.prototype._validateThenUpdateErrorClasses = _validateThenUpdateErrorClasses
|
|
667
675
|
|
|
668
676
|
function _validateThenUpdateErrorClasses(remote, local, remoteKey, localKey) {
|
|
669
|
-
|
|
677
|
+
const valueToTest = remote[remoteKey]
|
|
670
678
|
if (!Array.isArray(valueToTest)) {
|
|
671
679
|
logger.warn(
|
|
672
680
|
'Saw SSC (ignore|expect)_classes that is not an array, will not merge: %s',
|
|
@@ -677,7 +685,7 @@ function _validateThenUpdateErrorClasses(remote, local, remoteKey, localKey) {
|
|
|
677
685
|
|
|
678
686
|
let valid = true
|
|
679
687
|
Object.keys(valueToTest).forEach(function validateArray(key) {
|
|
680
|
-
|
|
688
|
+
const thingToTest = valueToTest[key]
|
|
681
689
|
if ('string' !== typeof thingToTest) {
|
|
682
690
|
logger.warn(
|
|
683
691
|
'Saw SSC (ignore|expect)_class that is not a string, will not merge: %s',
|
|
@@ -710,7 +718,7 @@ function _validateThenUpdateErrorClasses(remote, local, remoteKey, localKey) {
|
|
|
710
718
|
Config.prototype._validateThenUpdateErrorMessages = _validateThenUpdateErrorMessages
|
|
711
719
|
|
|
712
720
|
function _validateThenUpdateErrorMessages(remote, local, remoteKey, localKey) {
|
|
713
|
-
|
|
721
|
+
const valueToTest = remote[remoteKey]
|
|
714
722
|
if (Array.isArray(valueToTest)) {
|
|
715
723
|
logger.warn('Saw SSC (ignore|expect)_message that is an Array, will not merge: %s', valueToTest)
|
|
716
724
|
return
|
|
@@ -736,7 +744,7 @@ function _validateThenUpdateErrorMessages(remote, local, remoteKey, localKey) {
|
|
|
736
744
|
|
|
737
745
|
let valid = true
|
|
738
746
|
Object.keys(valueToTest).forEach(function validateArray(key) {
|
|
739
|
-
|
|
747
|
+
const arrayToTest = valueToTest[key]
|
|
740
748
|
if (!Array.isArray(arrayToTest)) {
|
|
741
749
|
logger.warn('Saw SSC message array that is not an array, will not merge: %s', arrayToTest)
|
|
742
750
|
valid = false
|
|
@@ -787,7 +795,7 @@ function _updateNestedIfChangedRaw(remote, local, remoteKey, localKey) {
|
|
|
787
795
|
* @param {string} key Value we're looking to set.
|
|
788
796
|
*/
|
|
789
797
|
Config.prototype._emitIfSet = function _emitIfSet(json, key) {
|
|
790
|
-
|
|
798
|
+
const value = json[key]
|
|
791
799
|
if (value != null) {
|
|
792
800
|
this.emit(key, value)
|
|
793
801
|
}
|
|
@@ -801,7 +809,7 @@ Config.prototype._emitIfSet = function _emitIfSet(json, key) {
|
|
|
801
809
|
* @param {string} key Value the agent won't set.
|
|
802
810
|
*/
|
|
803
811
|
Config.prototype.logDisabled = function logDisabled(json, key) {
|
|
804
|
-
|
|
812
|
+
const value = json[key]
|
|
805
813
|
if (value != null) {
|
|
806
814
|
logger.debug(
|
|
807
815
|
'Server-side configuration of %s is currently disabled by local configuration. ' +
|
|
@@ -820,7 +828,7 @@ Config.prototype.logDisabled = function logDisabled(json, key) {
|
|
|
820
828
|
* @param {string} key Value the agent doesn't set.
|
|
821
829
|
*/
|
|
822
830
|
Config.prototype.logUnsupported = function logUnsupported(json, key) {
|
|
823
|
-
|
|
831
|
+
const value = json[key]
|
|
824
832
|
if (value !== null && value !== undefined) {
|
|
825
833
|
logger.debug(
|
|
826
834
|
'Server-side configuration of %s is currently not supported by the ' +
|
|
@@ -839,7 +847,7 @@ Config.prototype.logUnsupported = function logUnsupported(json, key) {
|
|
|
839
847
|
* @param {string} key Value the agent knows nothing about.
|
|
840
848
|
*/
|
|
841
849
|
Config.prototype.logUnknown = function logUnknown(json, key) {
|
|
842
|
-
|
|
850
|
+
const value = json[key]
|
|
843
851
|
logger.debug('New Relic sent unknown configuration parameter %s with value %s.', key, value)
|
|
844
852
|
}
|
|
845
853
|
|
|
@@ -866,7 +874,7 @@ Config.prototype.clearDisplayHostCache = function clearDisplayHostCache() {
|
|
|
866
874
|
}
|
|
867
875
|
|
|
868
876
|
function getDisplayHost() {
|
|
869
|
-
|
|
877
|
+
let _displayHost
|
|
870
878
|
this.getDisplayHost = function getCachedDisplayHost() {
|
|
871
879
|
return _displayHost
|
|
872
880
|
}
|
|
@@ -874,8 +882,8 @@ function getDisplayHost() {
|
|
|
874
882
|
_displayHost = this.getHostnameSafe()
|
|
875
883
|
return _displayHost
|
|
876
884
|
}
|
|
877
|
-
|
|
878
|
-
|
|
885
|
+
const stringBuffer = Buffer.from(this.process_host.display_name, 'utf8')
|
|
886
|
+
const numBytes = stringBuffer.length
|
|
879
887
|
|
|
880
888
|
if (numBytes > 255) {
|
|
881
889
|
logger.warn('Custom host display name must be less than 255 bytes')
|
|
@@ -904,18 +912,18 @@ Config.prototype.clearHostnameCache = function clearHostnameCache() {
|
|
|
904
912
|
}
|
|
905
913
|
|
|
906
914
|
Config.prototype.getIPAddresses = function getIPAddresses() {
|
|
907
|
-
|
|
908
|
-
|
|
915
|
+
const addresses = Object.create(null)
|
|
916
|
+
const interfaces = os.networkInterfaces()
|
|
909
917
|
|
|
910
|
-
for (
|
|
918
|
+
for (const interfaceKey in interfaces) {
|
|
911
919
|
if (interfaceKey.match(/^lo/)) {
|
|
912
920
|
continue
|
|
913
921
|
}
|
|
914
922
|
|
|
915
|
-
|
|
916
|
-
for (
|
|
917
|
-
|
|
918
|
-
|
|
923
|
+
const interfaceDescriptions = interfaces[interfaceKey]
|
|
924
|
+
for (let i = 0; i < interfaceDescriptions.length; i++) {
|
|
925
|
+
const description = interfaceDescriptions[i]
|
|
926
|
+
const family = description.family.toLowerCase()
|
|
919
927
|
addresses[family] = description.address
|
|
920
928
|
}
|
|
921
929
|
}
|
|
@@ -923,7 +931,7 @@ Config.prototype.getIPAddresses = function getIPAddresses() {
|
|
|
923
931
|
}
|
|
924
932
|
|
|
925
933
|
function getHostnameSafe() {
|
|
926
|
-
|
|
934
|
+
let _hostname
|
|
927
935
|
this.getHostnameSafe = function getCachedHostname() {
|
|
928
936
|
return _hostname
|
|
929
937
|
}
|
|
@@ -931,7 +939,7 @@ function getHostnameSafe() {
|
|
|
931
939
|
_hostname = os.hostname()
|
|
932
940
|
return _hostname
|
|
933
941
|
} catch (e) {
|
|
934
|
-
|
|
942
|
+
const addresses = this.getIPAddresses()
|
|
935
943
|
|
|
936
944
|
if (this.process_host.ipv_preference === '6' && addresses.ipv6) {
|
|
937
945
|
_hostname = addresses.ipv6
|
|
@@ -954,7 +962,7 @@ function getHostnameSafe() {
|
|
|
954
962
|
* Ensure that the apps names are always returned as a list.
|
|
955
963
|
*/
|
|
956
964
|
Config.prototype.applications = function applications() {
|
|
957
|
-
|
|
965
|
+
const apps = this.app_name
|
|
958
966
|
|
|
959
967
|
if (Array.isArray(apps) && apps.length > 0) {
|
|
960
968
|
return apps
|
|
@@ -992,8 +1000,9 @@ Config.prototype._fromPassed = function _fromPassed(external, internal, arbitrar
|
|
|
992
1000
|
return
|
|
993
1001
|
}
|
|
994
1002
|
|
|
1003
|
+
let node = null
|
|
995
1004
|
try {
|
|
996
|
-
|
|
1005
|
+
node = external[key]
|
|
997
1006
|
} catch (err) {
|
|
998
1007
|
logger.warn('Error thrown on access of user config for key: %s', key)
|
|
999
1008
|
return
|
|
@@ -1001,7 +1010,7 @@ Config.prototype._fromPassed = function _fromPassed(external, internal, arbitrar
|
|
|
1001
1010
|
|
|
1002
1011
|
if (typeof node === 'object' && !Array.isArray(node)) {
|
|
1003
1012
|
// is top level and can have arbitrary keys
|
|
1004
|
-
|
|
1013
|
+
const allowArbitrary = internal === this || HAS_ARBITRARY_KEYS.has(key)
|
|
1005
1014
|
this._fromPassed(node, internal[key], allowArbitrary)
|
|
1006
1015
|
} else {
|
|
1007
1016
|
internal[key] = node
|
|
@@ -1018,14 +1027,14 @@ Config.prototype._fromPassed = function _fromPassed(external, internal, arbitrar
|
|
|
1018
1027
|
* of configuration.
|
|
1019
1028
|
*/
|
|
1020
1029
|
Config.prototype._fromSpecial = function _fromSpecial() {
|
|
1021
|
-
|
|
1030
|
+
const name = this.app_name
|
|
1022
1031
|
if (
|
|
1023
1032
|
name === null ||
|
|
1024
1033
|
name === undefined ||
|
|
1025
1034
|
name === '' ||
|
|
1026
1035
|
(Array.isArray(name) && name.length === 0)
|
|
1027
1036
|
) {
|
|
1028
|
-
|
|
1037
|
+
const azureName = process.env[AZURE_APP_NAME]
|
|
1029
1038
|
if (azureName) {
|
|
1030
1039
|
this.app_name = azureName.split(',')
|
|
1031
1040
|
}
|
|
@@ -1071,14 +1080,14 @@ Config.prototype._fromEnvironment = function _fromEnvironment(metadata, data) {
|
|
|
1071
1080
|
return
|
|
1072
1081
|
}
|
|
1073
1082
|
|
|
1074
|
-
|
|
1083
|
+
const node = metadata[value]
|
|
1075
1084
|
if (typeof node === 'string') {
|
|
1076
|
-
|
|
1085
|
+
const setting = process.env[node]
|
|
1077
1086
|
if (setting) {
|
|
1078
1087
|
logger.debug(`${node} environment variable set.`)
|
|
1079
1088
|
|
|
1080
1089
|
if (ENV.LIST_VARS.has(node)) {
|
|
1081
|
-
|
|
1090
|
+
const split = ENV.LIST_VARS_CUSTOM_DELIMITERS[node] || /,/
|
|
1082
1091
|
data[value] = setting.split(split).map(function trimVal(k) {
|
|
1083
1092
|
return k.trim()
|
|
1084
1093
|
})
|
|
@@ -1267,7 +1276,7 @@ Config.prototype._enforceServerless = function _enforceServerless(inputConfig) {
|
|
|
1267
1276
|
* based on special properties of configuration values should go here as well.
|
|
1268
1277
|
*/
|
|
1269
1278
|
Config.prototype._canonicalize = function _canonicalize() {
|
|
1270
|
-
|
|
1279
|
+
const statusCodes = this.error_collector && this.error_collector.ignore_status_codes
|
|
1271
1280
|
if (statusCodes) {
|
|
1272
1281
|
this.error_collector.ignore_status_codes = _parseCodes(statusCodes)
|
|
1273
1282
|
}
|
|
@@ -1277,17 +1286,17 @@ Config.prototype._canonicalize = function _canonicalize() {
|
|
|
1277
1286
|
this.error_collector.expected_status_codes = _parseCodes(expectedCodes)
|
|
1278
1287
|
}
|
|
1279
1288
|
|
|
1280
|
-
|
|
1289
|
+
const logAliases = {
|
|
1281
1290
|
verbose: 'trace',
|
|
1282
1291
|
debugging: 'debug',
|
|
1283
1292
|
warning: 'warn',
|
|
1284
1293
|
err: 'error'
|
|
1285
1294
|
}
|
|
1286
|
-
|
|
1295
|
+
const level = this.logging.level
|
|
1287
1296
|
this.logging.level = logAliases[level] || level
|
|
1288
1297
|
|
|
1289
1298
|
if (this.host === '') {
|
|
1290
|
-
|
|
1299
|
+
const region = parseKey(this.license_key)
|
|
1291
1300
|
if (region) {
|
|
1292
1301
|
this.host = 'collector.' + region + '.nr-data.net'
|
|
1293
1302
|
} else {
|
|
@@ -1312,7 +1321,7 @@ Config.prototype._canonicalize = function _canonicalize() {
|
|
|
1312
1321
|
function _parseCodes(codes) {
|
|
1313
1322
|
// range does not support negative values
|
|
1314
1323
|
function parseRange(range, parsed) {
|
|
1315
|
-
|
|
1324
|
+
const split = range.split('-')
|
|
1316
1325
|
if (split.length !== 2) {
|
|
1317
1326
|
logger.warn('Failed to parse range %s', range)
|
|
1318
1327
|
return parsed
|
|
@@ -1321,8 +1330,8 @@ function _parseCodes(codes) {
|
|
|
1321
1330
|
// catch negative code. ex. -7
|
|
1322
1331
|
return parsed.push(parseInt(range, 10))
|
|
1323
1332
|
}
|
|
1324
|
-
|
|
1325
|
-
|
|
1333
|
+
const lower = parseInt(split[0], 10)
|
|
1334
|
+
const upper = parseInt(split[1], 10)
|
|
1326
1335
|
if (Number.isNaN(lower) || Number.isNaN(upper)) {
|
|
1327
1336
|
logger.warn('Range must contain two numbers %s', range)
|
|
1328
1337
|
return parsed
|
|
@@ -1333,21 +1342,21 @@ function _parseCodes(codes) {
|
|
|
1333
1342
|
logger.warn('Range must be between 0 and 1000 %s', range)
|
|
1334
1343
|
} else {
|
|
1335
1344
|
// success
|
|
1336
|
-
for (
|
|
1345
|
+
for (let i = lower; i <= upper; i++) {
|
|
1337
1346
|
parsed.push(i)
|
|
1338
1347
|
}
|
|
1339
1348
|
}
|
|
1340
1349
|
return parsed
|
|
1341
1350
|
}
|
|
1342
1351
|
|
|
1343
|
-
|
|
1344
|
-
for (
|
|
1345
|
-
|
|
1346
|
-
|
|
1352
|
+
const parsedCodes = []
|
|
1353
|
+
for (let i = 0; i < codes.length; i++) {
|
|
1354
|
+
const code = codes[i]
|
|
1355
|
+
|
|
1347
1356
|
if (typeof code === 'string' && code.indexOf('-') !== -1) {
|
|
1348
1357
|
parseRange(code, parsedCodes)
|
|
1349
1358
|
} else {
|
|
1350
|
-
parsedCode = parseInt(code, 10)
|
|
1359
|
+
const parsedCode = parseInt(code, 10)
|
|
1351
1360
|
if (!Number.isNaN(parsedCode)) {
|
|
1352
1361
|
parsedCodes.push(parsedCode)
|
|
1353
1362
|
} else {
|
|
@@ -1363,7 +1372,7 @@ function _parseCodes(codes) {
|
|
|
1363
1372
|
* them to be correct.
|
|
1364
1373
|
*/
|
|
1365
1374
|
Config.prototype._applyHighSecurity = function _applyHighSecurity() {
|
|
1366
|
-
|
|
1375
|
+
const config = this
|
|
1367
1376
|
checkNode('', this, HSM.HIGH_SECURITY_SETTINGS)
|
|
1368
1377
|
// as a one off, we add a global exclude rule to the list to keep from
|
|
1369
1378
|
// clobbering user defined rules
|
|
@@ -1375,7 +1384,7 @@ Config.prototype._applyHighSecurity = function _applyHighSecurity() {
|
|
|
1375
1384
|
}
|
|
1376
1385
|
|
|
1377
1386
|
function checkKey(base, target, settings, key) {
|
|
1378
|
-
|
|
1387
|
+
const hsValue = settings[key]
|
|
1379
1388
|
|
|
1380
1389
|
if (hsValue && typeof hsValue === 'object' && !(hsValue instanceof Array)) {
|
|
1381
1390
|
if (typeof target[key] !== 'object') {
|
|
@@ -1406,8 +1415,8 @@ Config.prototype._applyHighSecurity = function _applyHighSecurity() {
|
|
|
1406
1415
|
* policies as the response payload.
|
|
1407
1416
|
*/
|
|
1408
1417
|
Config.prototype.applyLasp = function applyLasp(agent, policies) {
|
|
1409
|
-
|
|
1410
|
-
|
|
1418
|
+
const config = this
|
|
1419
|
+
const keys = Object.keys(policies)
|
|
1411
1420
|
|
|
1412
1421
|
if (!config.security_policies_token) {
|
|
1413
1422
|
if (keys.length) {
|
|
@@ -1419,12 +1428,12 @@ Config.prototype.applyLasp = function applyLasp(agent, policies) {
|
|
|
1419
1428
|
return CollectorResponse.success(null)
|
|
1420
1429
|
}
|
|
1421
1430
|
|
|
1422
|
-
|
|
1423
|
-
|
|
1431
|
+
const missingLASP = []
|
|
1432
|
+
const missingRequired = []
|
|
1424
1433
|
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1434
|
+
const finalPolicies = keys.reduce(function applyPolicy(obj, name) {
|
|
1435
|
+
const policy = policies[name]
|
|
1436
|
+
const localMapping = LASP_MAP[name]
|
|
1428
1437
|
|
|
1429
1438
|
if (!localMapping) {
|
|
1430
1439
|
if (!policy.required) {
|
|
@@ -1434,22 +1443,22 @@ Config.prototype.applyLasp = function applyLasp(agent, policies) {
|
|
|
1434
1443
|
// policy is required but does not exist in agent -- fail
|
|
1435
1444
|
missingRequired.push(name)
|
|
1436
1445
|
} else {
|
|
1437
|
-
|
|
1438
|
-
|
|
1446
|
+
const splitConfigName = localMapping.path.split('.')
|
|
1447
|
+
let settingBlock = config[splitConfigName[0]]
|
|
1439
1448
|
// pull out the configuration subsection that the option lives in
|
|
1440
|
-
for (
|
|
1449
|
+
for (let i = 1; i < splitConfigName.length - 1; ++i) {
|
|
1441
1450
|
settingBlock = settingBlock[splitConfigName[i]]
|
|
1442
1451
|
}
|
|
1443
|
-
|
|
1444
|
-
|
|
1452
|
+
const valueName = splitConfigName[splitConfigName.length - 1]
|
|
1453
|
+
const localVal = settingBlock[valueName]
|
|
1445
1454
|
|
|
1446
1455
|
// Indexes into "allowed values" based on "enabled" setting
|
|
1447
1456
|
// to retrieve proper mapping.
|
|
1448
|
-
|
|
1449
|
-
|
|
1457
|
+
const policyValues = localMapping.allowedValues
|
|
1458
|
+
const policyValue = policyValues[policy.enabled ? 1 : 0]
|
|
1450
1459
|
|
|
1451
1460
|
// get the most secure setting between local config and the policy
|
|
1452
|
-
|
|
1461
|
+
const finalValue = (settingBlock[valueName] = config._getMostSecure(
|
|
1453
1462
|
name,
|
|
1454
1463
|
localVal,
|
|
1455
1464
|
policyValue
|
|
@@ -1534,9 +1543,9 @@ function redactValue(value) {
|
|
|
1534
1543
|
* @return Object containing simple key-value pairs of settings
|
|
1535
1544
|
*/
|
|
1536
1545
|
Config.prototype.publicSettings = function publicSettings() {
|
|
1537
|
-
|
|
1546
|
+
let settings = Object.create(null)
|
|
1538
1547
|
|
|
1539
|
-
for (
|
|
1548
|
+
for (const key in this) {
|
|
1540
1549
|
if (this.hasOwnProperty(key) && !REMOVE_BEFORE_SEND.has(key)) {
|
|
1541
1550
|
if (HSM.REDACT_BEFORE_SEND.has(key)) {
|
|
1542
1551
|
const value = this[key]
|
|
@@ -1574,6 +1583,19 @@ Config.prototype.getAggregatorConfig = function getAggregatorConfig(method) {
|
|
|
1574
1583
|
}
|
|
1575
1584
|
}
|
|
1576
1585
|
|
|
1586
|
+
Config.prototype._warnDeprecations = function _warnDeprecations() {
|
|
1587
|
+
// DT overrides CAT so only warn when CAT is actually used.
|
|
1588
|
+
if (this.cross_application_tracer.enabled && !this.distributed_tracing.enabled) {
|
|
1589
|
+
const deprecationWarning = [
|
|
1590
|
+
'[Deprecation Warning]: Cross Application Tracing (CAT) has been deprecated and will be ',
|
|
1591
|
+
'removed in a future major release. CAT has been replaced by Distributed Tracing (DT). ',
|
|
1592
|
+
'Enable DT by setting distributed_tracing: { enabled: true }.'
|
|
1593
|
+
].join('')
|
|
1594
|
+
|
|
1595
|
+
logger.infoOnce('Deprecation:CAT', deprecationWarning)
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1577
1599
|
/**
|
|
1578
1600
|
* Create a configuration, either from a configuration file or the node
|
|
1579
1601
|
* process's environment.
|
|
@@ -1614,7 +1636,7 @@ function initialize(config) {
|
|
|
1614
1636
|
return createNewConfigObject(config)
|
|
1615
1637
|
}
|
|
1616
1638
|
|
|
1617
|
-
|
|
1639
|
+
const filepath = _findConfigFile()
|
|
1618
1640
|
if (!filepath) {
|
|
1619
1641
|
logger.info(
|
|
1620
1642
|
[
|
|
@@ -1630,7 +1652,7 @@ function initialize(config) {
|
|
|
1630
1652
|
return createNewConfigObject(config)
|
|
1631
1653
|
}
|
|
1632
1654
|
|
|
1633
|
-
|
|
1655
|
+
let userConf
|
|
1634
1656
|
try {
|
|
1635
1657
|
userConf = require(filepath).config
|
|
1636
1658
|
} catch (error) {
|
|
@@ -1711,6 +1733,5 @@ Config.initialize = initialize
|
|
|
1711
1733
|
Config.getOrCreateInstance = getOrCreateInstance
|
|
1712
1734
|
Config.getInstance = getInstance
|
|
1713
1735
|
Config.createInstance = createInstance
|
|
1714
|
-
Config.SPAN_EVENT_LIMIT = SPAN_EVENT_LIMIT
|
|
1715
1736
|
|
|
1716
1737
|
module.exports = Config
|
package/lib/config/lasp.js
CHANGED
|
@@ -29,9 +29,9 @@ const LASP_MAP = {
|
|
|
29
29
|
// Tracks the precedent of settings controlled by LASP.
|
|
30
30
|
filter: function mostSecureRecordSQL(first, second) {
|
|
31
31
|
// Ordered from least to most secure
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
const recordSQLSettings = ['obfuscated', 'off']
|
|
33
|
+
const firstIdx = recordSQLSettings.indexOf(first)
|
|
34
|
+
const secondIdx = recordSQLSettings.indexOf(second)
|
|
35
35
|
if (firstIdx < 0 && secondIdx < 0) {
|
|
36
36
|
// Return the most secure possible
|
|
37
37
|
return recordSQLSettings[recordSQLSettings.length - 1]
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
class MergeServerConfig {
|
|
9
9
|
// eslint-disable-next-line max-params
|
|
10
10
|
updateNestedIfChanged(config, remote, local, remoteKey, localKey, logger) {
|
|
11
|
-
|
|
11
|
+
const value = remote[remoteKey]
|
|
12
12
|
|
|
13
13
|
// if the value hasn't changed, skip this work.
|
|
14
14
|
// currently, this will always treat objects as
|
package/lib/db/parse-sql.js
CHANGED
|
@@ -8,18 +8,18 @@
|
|
|
8
8
|
// TODO: remove in favor of /lib/db/query-parsers/sql.js
|
|
9
9
|
// This module is currently used only in the Oracle instrumentation
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
const logger = require('../logger').child({ component: 'parse_sql' })
|
|
12
|
+
const StatementMatcher = require('./statement-matcher')
|
|
13
|
+
const ParsedStatement = require('./parsed-statement')
|
|
14
|
+
const stringify = require('json-stringify-safe')
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
const OPERATIONS = [
|
|
17
17
|
new StatementMatcher('select', /^\s*select[\S\s]*from[\s\[]+([^\]\s,)(;]*).*/gi),
|
|
18
18
|
new StatementMatcher('update', /^\s*update\s+([^\s,;]*).*/gi),
|
|
19
19
|
new StatementMatcher('insert', /^\s*insert(?:\s+ignore)?\s+into\s+([^\s(,;]*).*/gi),
|
|
20
20
|
new StatementMatcher('delete', /^\s*delete\s+from\s+([^\s,(;]*).*/gi)
|
|
21
21
|
]
|
|
22
|
-
|
|
22
|
+
const COMMENT_PATTERN = /\/\\*.*?\\*\//
|
|
23
23
|
|
|
24
24
|
// This must be called synchronously after the initial db call for backtraces to
|
|
25
25
|
// work correctly
|
|
@@ -44,9 +44,9 @@ module.exports = function parseSql(type, sql) {
|
|
|
44
44
|
|
|
45
45
|
sql = sql.replace(COMMENT_PATTERN, '').trim()
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
let parsedStatement
|
|
48
48
|
|
|
49
|
-
for (
|
|
49
|
+
for (let i = 0, l = OPERATIONS.length; i < l; i++) {
|
|
50
50
|
parsedStatement = OPERATIONS[i].getParsedStatement(sql)
|
|
51
51
|
if (parsedStatement) {
|
|
52
52
|
return new ParsedStatement(
|
|
@@ -22,12 +22,12 @@ function ParsedStatement(type, operation, collection, raw) {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
ParsedStatement.prototype.recordMetrics = function recordMetrics(segment, scope) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
const duration = segment.getDurationInMillis()
|
|
26
|
+
const exclusive = segment.getExclusiveDurationInMillis()
|
|
27
|
+
const transaction = segment.transaction
|
|
28
|
+
const type = transaction.isWeb() ? DB.WEB : DB.OTHER
|
|
29
|
+
const thisTypeSlash = this.type + '/'
|
|
30
|
+
const operation = DB.OPERATION + '/' + thisTypeSlash + this.operation
|
|
31
31
|
|
|
32
32
|
// Note, an operation metric should _always_ be created even if the action was
|
|
33
33
|
// a statement. This is part of the spec.
|
|
@@ -43,8 +43,9 @@ ParsedStatement.prototype.recordMetrics = function recordMetrics(segment, scope)
|
|
|
43
43
|
// as the scoped metric for transaction breakdowns. Otherwise, skip the
|
|
44
44
|
// 'statement' metric and use the 'operation' metric as the scoped metric for
|
|
45
45
|
// transaction breakdowns.
|
|
46
|
+
let collection
|
|
46
47
|
if (this.collection) {
|
|
47
|
-
|
|
48
|
+
collection = DB.STATEMENT + '/' + thisTypeSlash + this.collection + '/' + this.operation
|
|
48
49
|
transaction.measure(collection, null, duration, exclusive)
|
|
49
50
|
if (scope) {
|
|
50
51
|
transaction.measure(collection, scope, duration, exclusive)
|
|
@@ -61,7 +62,7 @@ ParsedStatement.prototype.recordMetrics = function recordMetrics(segment, scope)
|
|
|
61
62
|
// Datastore instance metrics.
|
|
62
63
|
const attributes = segment.attributes.get(DESTINATIONS.TRANS_SEGMENT)
|
|
63
64
|
if (attributes.host && attributes.port_path_or_id) {
|
|
64
|
-
|
|
65
|
+
const instanceName =
|
|
65
66
|
DB.INSTANCE + '/' + thisTypeSlash + attributes.host + '/' + attributes.port_path_or_id
|
|
66
67
|
transaction.measure(instanceName, null, duration, exclusive)
|
|
67
68
|
}
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
const logger = require('../../logger').child({ component: 'sql_query_parser' })
|
|
9
|
+
const StatementMatcher = require('../statement-matcher')
|
|
10
|
+
const stringify = require('json-stringify-safe')
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
const OPERATIONS = [
|
|
13
13
|
new StatementMatcher(
|
|
14
14
|
'select',
|
|
15
15
|
/^[^\S]*?select\b[\s\S]+?\bfrom[\s\n\r\[\(]+([^\]\s\n\r,)(;]*)/gim
|
|
@@ -21,7 +21,7 @@ var OPERATIONS = [
|
|
|
21
21
|
),
|
|
22
22
|
new StatementMatcher('delete', /^[^\S]*?delete[^\S]+?from[^\S]+([^\s\n\r,(;]+)/gim)
|
|
23
23
|
]
|
|
24
|
-
|
|
24
|
+
const COMMENT_PATTERN = /\/\\*.*?\\*\//g
|
|
25
25
|
|
|
26
26
|
// This must be called synchronously after the initial db call for backtraces to
|
|
27
27
|
// work correctly
|
|
@@ -50,9 +50,9 @@ module.exports = function parseSql(sql) {
|
|
|
50
50
|
|
|
51
51
|
sql = sql.replace(COMMENT_PATTERN, '').trim()
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
let parsedStatement
|
|
54
54
|
|
|
55
|
-
for (
|
|
55
|
+
for (let i = 0, l = OPERATIONS.length; i < l; i++) {
|
|
56
56
|
parsedStatement = OPERATIONS[i].getParsedStatement(sql)
|
|
57
57
|
if (parsedStatement) {
|
|
58
58
|
break
|
package/lib/db/query-sample.js
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
const codec = require('../util/codec')
|
|
9
|
+
const Stats = require('../stats')
|
|
10
|
+
const util = require('util')
|
|
11
11
|
|
|
12
12
|
function QuerySample(tracer, slowQuery) {
|
|
13
13
|
Stats.call(this)
|
|
@@ -34,11 +34,11 @@ QuerySample.prototype.merge = function merge(sample) {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
QuerySample.prototype.prepareJSON = function prepareJSON(done) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
const transaction = this.trace.segment.transaction
|
|
38
|
+
const sample = this
|
|
39
|
+
const trace = sample.trace
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
const params = sample.getParams()
|
|
42
42
|
|
|
43
43
|
if (!this.tracer.config.simple_compression) {
|
|
44
44
|
codec.encode(params, respond)
|
|
@@ -81,8 +81,8 @@ function _getJSON(sample, trace, transaction, data) {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
QuerySample.prototype.getParams = function getParams() {
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
const segmentAttrs = this.trace.segment.getAttributes()
|
|
85
|
+
const params = {
|
|
86
86
|
backtrace: this.trace.trace
|
|
87
87
|
}
|
|
88
88
|
|