newrelic 8.3.0 → 8.5.2
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 +76 -0
- package/README.md +7 -6
- package/THIRD_PARTY_NOTICES.md +95 -35
- 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 +1 -1
- 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 +12 -10
- package/lib/config/hsm.js +1 -1
- package/lib/config/index.js +82 -66
- 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 +85 -24
- 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 +16 -5
- 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/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/serverless/aws-lambda.js +8 -2
- 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.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 -6
- package/stub_api.js +8 -8
package/lib/util/cat.js
CHANGED
|
@@ -5,51 +5,296 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
+
const cat = module.exports
|
|
8
9
|
const hashes = require('./hashes')
|
|
9
10
|
const logger = require('../logger').child({ component: 'cat' })
|
|
11
|
+
const NAMES = require('../metrics/names')
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
const HTTP_CAT_ID_HEADER = 'X-NewRelic-Id'
|
|
14
|
+
const MQ_CAT_ID_HEADER = 'NewRelicID'
|
|
15
|
+
const MATCH_CAT_ID_HEADER = new RegExp(
|
|
16
|
+
'^(?:' + HTTP_CAT_ID_HEADER + '|' + MQ_CAT_ID_HEADER + ')$',
|
|
17
|
+
'i'
|
|
18
|
+
)
|
|
19
|
+
const HTTP_CAT_TRANSACTION_HEADER = 'X-NewRelic-Transaction'
|
|
20
|
+
const MQ_CAT_TRANSACTION_HEADER = 'NewRelicTransaction'
|
|
21
|
+
const MATCH_CAT_TRANSACTION_HEADER = new RegExp(
|
|
22
|
+
'^(?:' + HTTP_CAT_TRANSACTION_HEADER + '|' + MQ_CAT_TRANSACTION_HEADER + ')$',
|
|
23
|
+
'i'
|
|
24
|
+
)
|
|
25
|
+
const HTTP_CAT_APP_DATA_HEADER = 'X-NewRelic-App-Data'
|
|
26
|
+
const MQ_CAT_APP_DATA_HEADER = 'NewRelicAppData'
|
|
27
|
+
const MATCH_CAT_APP_DATA_HEADER = new RegExp(
|
|
28
|
+
'^(?:' + HTTP_CAT_APP_DATA_HEADER + '|' + MQ_CAT_APP_DATA_HEADER + ')$',
|
|
29
|
+
'i'
|
|
30
|
+
)
|
|
13
31
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Decodes the CAT id and transaction headers from incoming request
|
|
34
|
+
*
|
|
35
|
+
* @param {Object} headers incoming headers
|
|
36
|
+
* @param {string} encKey config.encoding_key used to decode CAT headers
|
|
37
|
+
* @param {Object} { externalId, externalTransaction }
|
|
38
|
+
*/
|
|
39
|
+
cat.parseCatData = function parseCatData(id, transactionId, encKey) {
|
|
40
|
+
if (!encKey) {
|
|
41
|
+
logger.warn('Missing encoding key, not extract CAT headers!')
|
|
42
|
+
return {}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let externalId = null
|
|
46
|
+
|
|
47
|
+
if (id) {
|
|
48
|
+
externalId = hashes.deobfuscateNameUsingKey(id, encKey)
|
|
18
49
|
}
|
|
19
50
|
|
|
20
|
-
|
|
21
|
-
if (
|
|
51
|
+
let externalTransaction = null
|
|
52
|
+
if (transactionId) {
|
|
22
53
|
try {
|
|
23
|
-
|
|
54
|
+
externalTransaction = JSON.parse(hashes.deobfuscateNameUsingKey(transactionId, encKey))
|
|
24
55
|
} catch (e) {
|
|
25
|
-
logger.trace(
|
|
56
|
+
logger.trace(`Got an unparsable CAT header ${HTTP_CAT_ID_HEADER} %s`, transactionId)
|
|
26
57
|
}
|
|
27
58
|
}
|
|
28
59
|
|
|
29
|
-
|
|
60
|
+
return { externalId, externalTransaction }
|
|
30
61
|
}
|
|
31
62
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
63
|
+
/**
|
|
64
|
+
* Adds the appropriate keys to transaction based on the incoming parsed CAT data
|
|
65
|
+
*
|
|
66
|
+
* @param {string} externalId decoded CAT id
|
|
67
|
+
* @param {Array} externalTransaction CAT transaction
|
|
68
|
+
* @param {Transaction} transaction active transaction
|
|
69
|
+
*/
|
|
70
|
+
cat.assignCatToTransaction = function assignCatToTransaction(
|
|
71
|
+
externalId,
|
|
72
|
+
externalTransaction,
|
|
73
|
+
transaction
|
|
74
|
+
) {
|
|
75
|
+
if (typeof externalId === 'string') {
|
|
76
|
+
transaction.incomingCatId = externalId
|
|
35
77
|
}
|
|
36
78
|
|
|
37
|
-
if (Array.isArray(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
79
|
+
if (Array.isArray(externalTransaction)) {
|
|
80
|
+
const [referringGuid, , tripId, referringPathHash] = externalTransaction
|
|
81
|
+
transaction.referringTransactionGuid = referringGuid
|
|
82
|
+
|
|
83
|
+
if (typeof tripId === 'string') {
|
|
84
|
+
transaction.tripId = tripId
|
|
85
|
+
} else if (tripId) {
|
|
42
86
|
transaction.invalidIncomingExternalTransaction = true
|
|
43
87
|
}
|
|
44
88
|
|
|
45
|
-
if (
|
|
46
|
-
transaction.referringPathHash =
|
|
47
|
-
} else if (
|
|
89
|
+
if (typeof referringPathHash === 'string') {
|
|
90
|
+
transaction.referringPathHash = referringPathHash
|
|
91
|
+
} else if (referringPathHash) {
|
|
48
92
|
transaction.invalidIncomingExternalTransaction = true
|
|
49
93
|
}
|
|
50
94
|
}
|
|
95
|
+
|
|
96
|
+
if (transaction.incomingCatId) {
|
|
97
|
+
logger.trace(
|
|
98
|
+
'Got inbound CAT headers in transaction %s from %s',
|
|
99
|
+
transaction.id,
|
|
100
|
+
transaction.incomingCatId
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Encodes the data to be set on the CAT app data header
|
|
107
|
+
* for incoming requests
|
|
108
|
+
*
|
|
109
|
+
* @param {Object} config agent config
|
|
110
|
+
* @param {Transaction} transaction
|
|
111
|
+
* @param {string} contentLength
|
|
112
|
+
* @param {Boolean} useMqHeaders flag to return proper headers for MQ compliance
|
|
113
|
+
* @return {Object} { key, data} to add as header
|
|
114
|
+
*/
|
|
115
|
+
cat.encodeAppData = function encodeAppData(config, transaction, contentLength, useMqHeaders) {
|
|
116
|
+
let appData = null
|
|
117
|
+
const transactionName = transaction.getFullName() || ''
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
appData = JSON.stringify([
|
|
121
|
+
config.cross_process_id, // cross_process_id
|
|
122
|
+
transactionName, // transaction name
|
|
123
|
+
transaction.queueTime / 1000, // queue time (s)
|
|
124
|
+
transaction.catResponseTime / 1000, // response time (s)
|
|
125
|
+
contentLength, // content length (if content-length header is also being sent)
|
|
126
|
+
transaction.id, // TransactionGuid
|
|
127
|
+
false // force a transaction trace to be recorded
|
|
128
|
+
])
|
|
129
|
+
} catch (err) {
|
|
130
|
+
logger.trace(
|
|
131
|
+
err,
|
|
132
|
+
'Failed to serialize transaction: %s - not adding CAT response headers',
|
|
133
|
+
transactionName
|
|
134
|
+
)
|
|
135
|
+
return
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const encKey = config.encoding_key
|
|
139
|
+
const obfAppData = hashes.obfuscateNameUsingKey(appData, encKey)
|
|
140
|
+
const key = useMqHeaders ? MQ_CAT_APP_DATA_HEADER : HTTP_CAT_APP_DATA_HEADER
|
|
141
|
+
return { key, data: obfAppData }
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Adds CAT headers to outbound request.
|
|
146
|
+
*
|
|
147
|
+
* @param {Object} config agent config
|
|
148
|
+
* @param {Transaction} transaction
|
|
149
|
+
* @param {Object} headers object that contains headers the agent is adding to client request
|
|
150
|
+
* @param {Boolean} useMqHeaders flag to return proper headers for MQ compliance
|
|
151
|
+
*/
|
|
152
|
+
cat.addCatHeaders = function addCatHeaders(config, transaction, headers, useMqHeaders) {
|
|
153
|
+
if (!config.encoding_key) {
|
|
154
|
+
logger.warn('Missing encoding key, not adding CAT headers!')
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const idHeader = useMqHeaders ? MQ_CAT_ID_HEADER : HTTP_CAT_ID_HEADER
|
|
159
|
+
const transactionHeader = useMqHeaders ? MQ_CAT_TRANSACTION_HEADER : HTTP_CAT_TRANSACTION_HEADER
|
|
160
|
+
|
|
161
|
+
// Add in the application ID
|
|
162
|
+
if (config.obfuscatedId) {
|
|
163
|
+
headers[idHeader] = config.obfuscatedId
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const transactionName = transaction.getFullName() || ''
|
|
167
|
+
|
|
168
|
+
const pathHash = hashes.calculatePathHash(
|
|
169
|
+
config.applications()[0],
|
|
170
|
+
transactionName,
|
|
171
|
+
transaction.referringPathHash
|
|
172
|
+
)
|
|
173
|
+
transaction.pushPathHash(pathHash)
|
|
174
|
+
|
|
175
|
+
try {
|
|
176
|
+
const transactionData = hashes.obfuscateNameUsingKey(
|
|
177
|
+
JSON.stringify([transaction.id, false, transaction.tripId || transaction.id, pathHash]),
|
|
178
|
+
config.encoding_key
|
|
179
|
+
)
|
|
180
|
+
headers[transactionHeader] = transactionData
|
|
181
|
+
|
|
182
|
+
logger.trace('Added outbound request CAT headers in transaction %s', transaction.id)
|
|
183
|
+
} catch (err) {
|
|
184
|
+
logger.trace(err, 'Failed to create CAT payload')
|
|
185
|
+
}
|
|
51
186
|
}
|
|
52
187
|
|
|
53
|
-
|
|
54
|
-
|
|
188
|
+
/**
|
|
189
|
+
* Find the CAT id, transaction, app data headers
|
|
190
|
+
* from the headers of either HTTP or MQ request
|
|
191
|
+
*
|
|
192
|
+
* @param {Object} headers
|
|
193
|
+
* @return {Object} { id, transactionId, appData }
|
|
194
|
+
*/
|
|
195
|
+
cat.extractCatHeaders = function extractCatHeaders(headers) {
|
|
196
|
+
// Hunt down the CAT headers.
|
|
197
|
+
let id = null
|
|
198
|
+
let transactionId = null
|
|
199
|
+
let appData = null
|
|
200
|
+
// eslint-disable-next-line guard-for-in
|
|
201
|
+
for (const key in headers) {
|
|
202
|
+
if (MATCH_CAT_ID_HEADER.test(key)) {
|
|
203
|
+
id = headers[key]
|
|
204
|
+
} else if (MATCH_CAT_TRANSACTION_HEADER.test(key)) {
|
|
205
|
+
transactionId = headers[key]
|
|
206
|
+
} else if (MATCH_CAT_APP_DATA_HEADER.test(key)) {
|
|
207
|
+
appData = headers[key]
|
|
208
|
+
}
|
|
209
|
+
if (id && transactionId && appData) {
|
|
210
|
+
break
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return { id, transactionId, appData }
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Extracts the account Id from CAT data and verifies if it is
|
|
219
|
+
* a trusted account id
|
|
220
|
+
*
|
|
221
|
+
* @param {Object} CAT data
|
|
222
|
+
* @param {Array} trustedAccounts from config
|
|
223
|
+
* @return {Boolean}
|
|
224
|
+
*/
|
|
225
|
+
cat.isTrustedAccountId = function isTrustedAccountId(data, trustedAccounts) {
|
|
226
|
+
const accountId = parseInt(data.split('#')[0], 10)
|
|
227
|
+
const trusted = trustedAccounts.includes(accountId)
|
|
228
|
+
if (!trusted) {
|
|
229
|
+
logger.trace('Response from untrusted CAT header account id: %s', accountId)
|
|
230
|
+
}
|
|
231
|
+
return trusted
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Decodes the CAT App Data header and extracts the downstream
|
|
236
|
+
* CAT id, transaction id
|
|
237
|
+
*
|
|
238
|
+
* @param {Object} config agent config
|
|
239
|
+
* @param {string} obfAppData encoded app data to parse and use
|
|
240
|
+
* @param {Array} decoded app data header
|
|
241
|
+
*/
|
|
242
|
+
cat.parseAppData = function parseAppData(config, obfAppData) {
|
|
243
|
+
if (!config.encoding_key) {
|
|
244
|
+
logger.trace('config.encoding_key is not set - not parsing response CAT headers')
|
|
245
|
+
return
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (!config.trusted_account_ids) {
|
|
249
|
+
logger.trace('config.trusted_account_ids is not set - not parsing response CAT headers')
|
|
250
|
+
return
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
let appData = null
|
|
254
|
+
try {
|
|
255
|
+
appData = JSON.parse(hashes.deobfuscateNameUsingKey(obfAppData, config.encoding_key))
|
|
256
|
+
} catch (e) {
|
|
257
|
+
logger.warn(`Got an unparsable CAT header ${HTTP_CAT_APP_DATA_HEADER}: %s`, obfAppData)
|
|
258
|
+
return
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Make sure it is a trusted account
|
|
262
|
+
if (!cat.isTrustedAccountId(appData && appData[0], config.trusted_account_ids)) {
|
|
263
|
+
return
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return appData
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Assigns the CAT id, transaction to segment and adds `transaction_guid` when it exists.
|
|
271
|
+
* It also renames the segment name based on the newly decoded app data when host is present
|
|
272
|
+
*
|
|
273
|
+
* @param {Array} appData decodes CAT app data
|
|
274
|
+
* @param {TraceSegment} segment
|
|
275
|
+
* @param {string} [host] if host is present it will rename segment with app data and host
|
|
276
|
+
*/
|
|
277
|
+
cat.assignCatToSegment = function assignCatToSegment(appData, segment, host) {
|
|
278
|
+
if (!Array.isArray(appData) || typeof appData[0] !== 'string') {
|
|
279
|
+
logger.trace(`Unknown format for CAT header ${HTTP_CAT_APP_DATA_HEADER}.`)
|
|
280
|
+
return
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
segment.catId = appData[0]
|
|
284
|
+
segment.catTransaction = appData[1]
|
|
285
|
+
|
|
286
|
+
if (host) {
|
|
287
|
+
segment.name = `${NAMES.EXTERNAL.TRANSACTION}${host}/${segment.catId}/${segment.catTransaction}`
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
let transactionGuid
|
|
291
|
+
if (appData.length >= 6) {
|
|
292
|
+
transactionGuid = appData[5]
|
|
293
|
+
segment.addAttribute('transaction_guid', transactionGuid)
|
|
294
|
+
}
|
|
295
|
+
logger.trace(
|
|
296
|
+
'Got inbound response CAT headers in transaction %s from %s',
|
|
297
|
+
segment.transaction.id,
|
|
298
|
+
transactionGuid
|
|
299
|
+
)
|
|
55
300
|
}
|
package/lib/util/codec.js
CHANGED
package/lib/util/copy.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const hasOwnProperty = require('./properties').hasOwn
|
|
9
9
|
|
|
10
10
|
exports.shallow = shallowCopy
|
|
11
11
|
|
|
@@ -19,7 +19,7 @@ exports.shallow = shallowCopy
|
|
|
19
19
|
*/
|
|
20
20
|
function shallowCopy(source, dest) {
|
|
21
21
|
dest = dest || Object.create(null)
|
|
22
|
-
for (
|
|
22
|
+
for (const k in source) {
|
|
23
23
|
if (hasOwnProperty(source, k)) {
|
|
24
24
|
dest[k] = source[k]
|
|
25
25
|
}
|
package/lib/util/deep-equal.js
CHANGED
|
@@ -11,9 +11,9 @@ function isArguments(object) {
|
|
|
11
11
|
|
|
12
12
|
function slice(args) {
|
|
13
13
|
// Array.prototype.slice on arguments array-like is expensive
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
const l = args.length
|
|
15
|
+
const a = []
|
|
16
|
+
let i
|
|
17
17
|
for (i = 0; i < l; i++) {
|
|
18
18
|
a[i] = args[i]
|
|
19
19
|
}
|
|
@@ -78,7 +78,7 @@ function deeper(a, b, ca, cb) {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
// potentially incredibly expensive
|
|
81
|
-
for (
|
|
81
|
+
for (let i = 0; i < a.length; i++) {
|
|
82
82
|
if (a[i] !== b[i]) {
|
|
83
83
|
return false
|
|
84
84
|
}
|
|
@@ -107,13 +107,13 @@ function deeper(a, b, ca, cb) {
|
|
|
107
107
|
return false
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
const ka = Object.keys(a)
|
|
111
|
+
const kb = Object.keys(b)
|
|
112
112
|
if (ka.length !== kb.length) {
|
|
113
113
|
return false
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
let cal = ca.length
|
|
117
117
|
while (cal--) {
|
|
118
118
|
if (ca[cal] === a) {
|
|
119
119
|
return cb[cal] === b
|
|
@@ -124,14 +124,14 @@ function deeper(a, b, ca, cb) {
|
|
|
124
124
|
|
|
125
125
|
ka.sort()
|
|
126
126
|
kb.sort()
|
|
127
|
-
for (
|
|
127
|
+
for (let j = ka.length - 1; j >= 0; j--) {
|
|
128
128
|
if (ka[j] !== kb[j]) {
|
|
129
129
|
return false
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
|
|
134
|
-
for (
|
|
133
|
+
let key
|
|
134
|
+
for (let k = ka.length - 1; k >= 0; k--) {
|
|
135
135
|
key = ka[k]
|
|
136
136
|
if (!deeper(a[key], b[key], ca, cb)) {
|
|
137
137
|
return false
|
package/lib/util/flatten.js
CHANGED
|
@@ -25,7 +25,7 @@ function flatten(result, prefix, obj, seen) {
|
|
|
25
25
|
seen = seen || []
|
|
26
26
|
seen.push(obj)
|
|
27
27
|
|
|
28
|
-
for (
|
|
28
|
+
for (const key in obj) {
|
|
29
29
|
if (seen.indexOf(obj[key]) > -1) {
|
|
30
30
|
continue
|
|
31
31
|
}
|
|
@@ -52,15 +52,15 @@ function flatten(result, prefix, obj, seen) {
|
|
|
52
52
|
* @return {array.<string>} An array of keys names.
|
|
53
53
|
*/
|
|
54
54
|
function flatKeys(obj, prefix, arrayIdxs) {
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
const keys = []
|
|
56
|
+
const seen = []
|
|
57
57
|
recurse(prefix || '', obj)
|
|
58
58
|
return keys
|
|
59
59
|
|
|
60
60
|
function recurse(p, o) {
|
|
61
61
|
seen.push(o)
|
|
62
62
|
|
|
63
|
-
for (
|
|
63
|
+
for (const key in o) {
|
|
64
64
|
if (seen.indexOf(o[key]) !== -1) {
|
|
65
65
|
continue
|
|
66
66
|
}
|
package/lib/util/hashes.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
const crypto = require('crypto')
|
|
9
9
|
|
|
10
10
|
function encode(bytes, keyBytes) {
|
|
11
|
-
for (
|
|
11
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
12
12
|
// This is really dense but happens commonly so I'm in-lining some of what
|
|
13
13
|
// could be tossed into variables. It takes the current byte of bytes, then
|
|
14
14
|
// XORs it with the current byte of the key (which uses modulo to make sure
|
|
@@ -19,14 +19,14 @@ function encode(bytes, keyBytes) {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
function obfuscateNameUsingKey(name, key) {
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
const encodedBytes = Buffer.from(name, 'utf-8')
|
|
23
|
+
const keyBytes = Buffer.from(key)
|
|
24
24
|
return encode(encodedBytes, keyBytes).toString('base64')
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
function deobfuscateNameUsingKey(name, key) {
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
const bytes = Buffer.from(name, 'base64')
|
|
29
|
+
const keyBytes = Buffer.from(key)
|
|
30
30
|
|
|
31
31
|
return encode(bytes, keyBytes).toString('utf-8')
|
|
32
32
|
}
|
|
@@ -35,21 +35,21 @@ function calculatePathHash(appName, pathName, referingPathHash) {
|
|
|
35
35
|
if (typeof referingPathHash === 'string') {
|
|
36
36
|
referingPathHash = parseInt(referingPathHash, 16)
|
|
37
37
|
}
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
const rotated = ((referingPathHash << 1) | (referingPathHash >>> 31)) >>> 0
|
|
39
|
+
const hash = getHash(appName, pathName)
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
const result = (rotated ^ hash) >>> 0
|
|
42
42
|
|
|
43
43
|
// This is a trick to pad it out to 8 chars regardless of length.
|
|
44
|
-
|
|
44
|
+
const retval = ('00000000' + result.toString(16)).substr(-8)
|
|
45
45
|
|
|
46
46
|
return retval
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
function getHash(appName, txName) {
|
|
50
|
-
|
|
50
|
+
const md5sum = crypto.createHash('md5')
|
|
51
51
|
md5sum.update(appName + ';' + txName, 'utf8')
|
|
52
|
-
|
|
52
|
+
let buf = md5sum.digest()
|
|
53
53
|
if (!(buf instanceof Buffer)) {
|
|
54
54
|
buf = Buffer.from(buf)
|
|
55
55
|
}
|
|
@@ -66,10 +66,10 @@ function randInt32() {
|
|
|
66
66
|
|
|
67
67
|
function int32ToByteArray(int32) {
|
|
68
68
|
// we want to represent the input as a 4-bytes array
|
|
69
|
-
|
|
69
|
+
const byteArray = new Uint8Array(4)
|
|
70
70
|
|
|
71
71
|
for (let i = 0; i < byteArray.length; i++) {
|
|
72
|
-
|
|
72
|
+
const byte = int32 & 0xff
|
|
73
73
|
byteArray[i] = byte
|
|
74
74
|
int32 = (int32 - byte) / 256
|
|
75
75
|
}
|
|
@@ -87,7 +87,7 @@ function makeId(length = 16) {
|
|
|
87
87
|
// length is number of hex characters, which multiplied by 4 is the number of
|
|
88
88
|
// bits, then divided by 8 is number of bytes. Or just divide by 2
|
|
89
89
|
const numBytes = Math.ceil(length / 2)
|
|
90
|
-
|
|
90
|
+
const randBytes = new Uint8Array(numBytes)
|
|
91
91
|
|
|
92
92
|
// Generate random bytes one 32-bit integer at a time
|
|
93
93
|
const numInts = Math.ceil(numBytes / 4) // 32 bit integers are 4 bytes
|
package/lib/util/label-parser.js
CHANGED
|
@@ -10,12 +10,12 @@ module.exports.fromString = fromString
|
|
|
10
10
|
module.exports.fromMap = fromMap
|
|
11
11
|
|
|
12
12
|
// this creates a copy of trim that can be used with map
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
const trim = Function.prototype.call.bind(String.prototype.trim)
|
|
14
|
+
const logger = require('../logger').child({ component: 'label-parser' })
|
|
15
|
+
const stringify = require('json-stringify-safe')
|
|
16
16
|
|
|
17
17
|
function parse(labels) {
|
|
18
|
-
|
|
18
|
+
let results
|
|
19
19
|
|
|
20
20
|
if (!labels) {
|
|
21
21
|
return []
|
|
@@ -33,14 +33,14 @@ function parse(labels) {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
function fromString(raw) {
|
|
36
|
-
|
|
36
|
+
const map = Object.create(null)
|
|
37
37
|
|
|
38
38
|
if (!raw) {
|
|
39
39
|
return { labels: [], warnings: [] }
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
const pairs = raw.split(';').map(trim)
|
|
43
|
+
let parts
|
|
44
44
|
|
|
45
45
|
while (!pairs[pairs.length - 1]) {
|
|
46
46
|
pairs.pop()
|
|
@@ -50,7 +50,7 @@ function fromString(raw) {
|
|
|
50
50
|
pairs.shift()
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
for (
|
|
53
|
+
for (let i = 0, l = pairs.length; i < l; ++i) {
|
|
54
54
|
parts = pairs[i].split(':').map(trim)
|
|
55
55
|
|
|
56
56
|
if (parts.length !== 2) {
|
|
@@ -72,11 +72,11 @@ function fromString(raw) {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
function fromMap(map) {
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
const warnings = []
|
|
76
|
+
let labels = []
|
|
77
77
|
|
|
78
78
|
Object.keys(map).forEach(function processKeys(key) {
|
|
79
|
-
|
|
79
|
+
const type = truncate(key, 255)
|
|
80
80
|
|
|
81
81
|
if (!map[key] || typeof map[key] !== 'string') {
|
|
82
82
|
return warnings.push(
|
|
@@ -84,7 +84,7 @@ function fromMap(map) {
|
|
|
84
84
|
)
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
const value = truncate(map[key], 255)
|
|
88
88
|
|
|
89
89
|
if (type !== key) {
|
|
90
90
|
warnings.push('Label key too long: ' + type)
|
|
@@ -114,11 +114,11 @@ function fromMap(map) {
|
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
function truncate(str, max) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
for (
|
|
120
|
-
chr = str.charCodeAt(i)
|
|
121
|
-
if (chr >= 0xd800 && chr <= 0xdbff && i !==
|
|
117
|
+
let len = 0
|
|
118
|
+
let i
|
|
119
|
+
for (i = 0; i < str.length; ++i) {
|
|
120
|
+
const chr = str.charCodeAt(i)
|
|
121
|
+
if (chr >= 0xd800 && chr <= 0xdbff && i !== str.length) {
|
|
122
122
|
i += 1
|
|
123
123
|
}
|
|
124
124
|
|