Comparing version 9.7.5 to 9.8.0
232
api.js
@@ -43,3 +43,3 @@ /* | ||
'NREUM: no browser monitoring headers generated; disabled', | ||
'NREUM: transaction missing or ignored while generating browser monitoring headers', | ||
'NREUM: transaction ignored while generating browser monitoring headers', | ||
'NREUM: config.browser_monitoring missing, something is probably wrong', | ||
@@ -644,74 +644,32 @@ 'NREUM: browser_monitoring headers need a transaction name', | ||
/** | ||
* Get the script header necessary for Browser Monitoring | ||
* This script must be manually injected into your templates, as high as possible | ||
* in the header, but _after_ any X-UA-COMPATIBLE HTTP-EQUIV meta tags. | ||
* Otherwise you may hurt IE! | ||
* Helper method for determining if we have the minimum required | ||
* information to generate our Browser Agent script tag | ||
* | ||
* By default this method will return a script wrapped by `<script>` tags, but with | ||
* option `hasToRemoveScriptWrapper` it can send back only the script content | ||
* without the `<script>` wrapper. Useful for React component based frontend. | ||
* | ||
* This method must be called _during_ a transaction, and must be called every | ||
* time you want to generate the headers. | ||
* | ||
* Do *not* reuse the headers between users, or even between requests. | ||
* | ||
* @param {object} options configuration options | ||
* @param {string} [options.nonce] - Nonce to inject into `<script>` header. | ||
* @param {boolean} [options.hasToRemoveScriptWrapper] - Used to import agent script without `<script>` tag wrapper. | ||
* @returns {string} The script content to be injected in `<head>` or put inside `<script>` tag (depending on options) | ||
* @param {object} config agent configuration settings | ||
* @param {Transaction} transaction the active transaction or null | ||
* @param {boolean} allowTransactionlessInjection whether or not to allow the Browser Agent to be injected when there is no active transaction | ||
* @returns {{ isValidConfig: boolean, failureIdx?: number, quietMode?: boolean }} object containing validation results | ||
*/ | ||
API.prototype.getBrowserTimingHeader = function getBrowserTimingHeader(options) { | ||
const metric = this.agent.metrics.getOrCreateMetric( | ||
NAMES.SUPPORTABILITY.API + '/getBrowserTimingHeader' | ||
) | ||
metric.incrementCallCount() | ||
const config = this.agent.config | ||
const browserMonitoring = config.browser_monitoring | ||
// config.browser_monitoring should always exist, but we don't want the agent | ||
// to bail here if something goes wrong | ||
if (!browserMonitoring) { | ||
return _gracefail(2) | ||
function validateBrowserMonitoring(config, transaction, allowTransactionlessInjection) { | ||
/* | ||
* config.browser_monitoring should always exist, but we don't want the agent | ||
* to bail here if something goes wrong | ||
*/ | ||
if (!config.browser_monitoring) { | ||
return { isValidConfig: false, failureIdx: 2 } | ||
} | ||
/* Can control header generation with configuration this setting is only | ||
/* | ||
* Can control header generation with configuration this setting is only | ||
* available in the newrelic.js config file, it is not ever set by the | ||
* server. | ||
*/ | ||
if (!browserMonitoring.enable) { | ||
if (!config.browser_monitoring.enable) { | ||
// It has been disabled by the user; no need to warn them about their own | ||
// settings so fail quietly and gracefully. | ||
return _gracefail(0, true) | ||
return { isValidConfig: false, failureIdx: 0, quietMode: true } | ||
} | ||
const trans = this.agent.getTransaction() | ||
// bail gracefully outside a transaction | ||
if (!trans || trans.isIgnored()) { | ||
return _gracefail(1) | ||
} | ||
const name = trans.getFullName() | ||
/* If we're in an unnamed transaction, add a friendly warning this is to | ||
* avoid people going crazy, trying to figure out why browser monitoring is | ||
* not working when they're missing a transaction name. | ||
*/ | ||
if (!name) { | ||
return _gracefail(3) | ||
} | ||
const time = trans.timer.getDurationInMillis() | ||
/* | ||
* Only the first 13 chars of the license should be used for hashing with | ||
* the transaction name. | ||
*/ | ||
const key = config.license_key.substr(0, 13) | ||
const appid = config.application_id | ||
/* This is only going to work if the agent has successfully handshaked with | ||
* This is only going to work if the agent has successfully handshaked with | ||
* the collector. If the networks is bad, or there is no license key set in | ||
@@ -721,23 +679,24 @@ * newrelic.js, there will be no application_id set. We bail instead of | ||
*/ | ||
if (!appid) { | ||
return _gracefail(4) | ||
if (!config.application_id) { | ||
return { isValidConfig: false, failureIdx: 4 } | ||
} | ||
/* If there is no browser_key, the server has likely decided to disable | ||
/* | ||
* If there is no browser_key, the server has likely decided to disable | ||
* browser monitoring. | ||
*/ | ||
const licenseKey = browserMonitoring.browser_key | ||
if (!licenseKey) { | ||
return _gracefail(5) | ||
if (!config.browser_monitoring.browser_key) { | ||
return { isValidConfig: false, failureIdx: 5 } | ||
} | ||
/* If there is no agent_loader script, there is no point | ||
/* | ||
* If there is no agent_loader script, there is no point | ||
* in setting the rum data | ||
*/ | ||
const jsAgentLoader = browserMonitoring.js_agent_loader | ||
if (!jsAgentLoader) { | ||
return _gracefail(6) | ||
if (!config.browser_monitoring.js_agent_loader) { | ||
return { isValidConfig: false, failureIdx: 6 } | ||
} | ||
/* If rum is enabled, but then later disabled on the server, | ||
/* | ||
* If rum is enabled, but then later disabled on the server, | ||
* this is the only parameter that gets updated. | ||
@@ -749,18 +708,60 @@ * | ||
*/ | ||
const loader = browserMonitoring.loader | ||
if (loader === 'none') { | ||
return _gracefail(7) | ||
if (config.browser_monitoring.loader === 'none') { | ||
return { isValidConfig: false, failureIdx: 7 } | ||
} | ||
if (!allowTransactionlessInjection && !transaction) { | ||
return { isValidConfig: false, failureIdx: 1 } | ||
} | ||
return { isValidConfig: true } | ||
} | ||
/** | ||
* Get the script header necessary for Browser Monitoring | ||
* This script must be manually injected into your templates, as high as possible | ||
* in the header, but _after_ any X-UA-COMPATIBLE HTTP-EQUIV meta tags. | ||
* Otherwise you may hurt IE! | ||
* | ||
* By default this method will return a script wrapped by `<script>` tags, but with | ||
* option `hasToRemoveScriptWrapper` it can send back only the script content | ||
* without the `<script>` wrapper. Useful for React component based frontend. | ||
* | ||
* This method must be called every time you want to generate the headers. | ||
* | ||
* Do *not* reuse the headers between users, or even between requests. | ||
* | ||
* @param {object} options configuration options | ||
* @param {string} [options.nonce] - Nonce to inject into `<script>` header. | ||
* @param {boolean} [options.hasToRemoveScriptWrapper] - Used to import agent script without `<script>` tag wrapper. | ||
* @param {options} [options.allowTransactionlessInjection] Whether or not to allow the Browser Agent to be injected when there is no active transaction | ||
* @returns {string} The script content to be injected in `<head>` or put inside `<script>` tag (depending on options) | ||
*/ | ||
API.prototype.getBrowserTimingHeader = function getBrowserTimingHeader(options = {}) { | ||
const metric = this.agent.metrics.getOrCreateMetric( | ||
NAMES.SUPPORTABILITY.API + '/getBrowserTimingHeader' | ||
) | ||
metric.incrementCallCount() | ||
const trans = this.agent.getTransaction() | ||
const { isValidConfig, failureIdx, quietMode } = validateBrowserMonitoring( | ||
this.agent.config, | ||
trans, | ||
options.allowTransactionlessInjection | ||
) | ||
if (!isValidConfig) { | ||
return _gracefail(failureIdx, quietMode) | ||
} | ||
const config = this.agent.config | ||
// This hash gets written directly into the browser. | ||
const rumHash = { | ||
agent: browserMonitoring.js_agent_file, | ||
beacon: browserMonitoring.beacon, | ||
errorBeacon: browserMonitoring.error_beacon, | ||
licenseKey: licenseKey, | ||
applicationID: appid, | ||
applicationTime: time, | ||
transactionName: hashes.obfuscateNameUsingKey(name, key), | ||
queueTime: trans.queueTime, | ||
ttGuid: trans.id, | ||
agent: config.browser_monitoring.js_agent_file, | ||
beacon: config.browser_monitoring.beacon, | ||
errorBeacon: config.browser_monitoring.error_beacon, | ||
licenseKey: config.browser_monitoring.browser_key, | ||
applicationID: config.application_id, | ||
@@ -771,16 +772,51 @@ // we don't use these parameters yet | ||
const attrs = Object.create(null) | ||
const hasActiveTransaction = trans !== null | ||
const customAttrs = trans.trace.custom.get(ATTR_DEST.BROWSER_EVENT) | ||
if (!properties.isEmpty(customAttrs)) { | ||
attrs.u = customAttrs | ||
} | ||
if (hasActiveTransaction) { | ||
// bail gracefully outside an ignored transaction | ||
if (trans.isIgnored()) { | ||
return _gracefail(1) | ||
} | ||
const agentAttrs = trans.trace.attributes.get(ATTR_DEST.BROWSER_EVENT) | ||
if (!properties.isEmpty(agentAttrs)) { | ||
attrs.a = agentAttrs | ||
} | ||
/* If we're in an unnamed transaction, add a friendly warning this is to | ||
* avoid people going crazy, trying to figure out why browser monitoring is | ||
* not working when they're missing a transaction name. | ||
*/ | ||
const name = trans.getFullName() | ||
if (!name) { | ||
return _gracefail(3) | ||
} | ||
if (!properties.isEmpty(attrs)) { | ||
rumHash.atts = hashes.obfuscateNameUsingKey(JSON.stringify(attrs), key) | ||
const time = trans.timer.getDurationInMillis() | ||
rumHash.applicationTime = time | ||
/* | ||
* Only the first 13 chars of the license should be used for hashing with | ||
* the transaction name. | ||
*/ | ||
const key = config.license_key.substr(0, 13) | ||
rumHash.transactionName = hashes.obfuscateNameUsingKey(name, key) | ||
rumHash.queueTime = trans.queueTime | ||
rumHash.ttGuid = trans.id | ||
const attrs = Object.create(null) | ||
const customAttrs = trans.trace.custom.get(ATTR_DEST.BROWSER_EVENT) | ||
if (!properties.isEmpty(customAttrs)) { | ||
attrs.u = customAttrs | ||
} | ||
const agentAttrs = trans.trace.attributes.get(ATTR_DEST.BROWSER_EVENT) | ||
if (!properties.isEmpty(agentAttrs)) { | ||
attrs.a = agentAttrs | ||
} | ||
if (!properties.isEmpty(attrs)) { | ||
rumHash.atts = hashes.obfuscateNameUsingKey(JSON.stringify(attrs), key) | ||
} | ||
} else { | ||
logger.debug( | ||
'No transaction detected when generating RUM header, continuing without transaction info' | ||
) | ||
} | ||
@@ -793,3 +829,7 @@ | ||
// the complete header to be written to the browser | ||
const out = _generateRUMHeader(options, json, jsAgentLoader) | ||
const out = _generateRUMHeader( | ||
{ nonce: options.nonce, hasToRemoveScriptWrapper: options.hasToRemoveScriptWrapper }, | ||
json, | ||
config.browser_monitoring.js_agent_loader | ||
) | ||
@@ -796,0 +836,0 @@ logger.trace('generating RUM header', out) |
{ | ||
"name": "newrelic", | ||
"version": "9.7.5", | ||
"version": "9.8.0", | ||
"author": "New Relic Node.js agent team <nodejs@newrelic.com>", | ||
@@ -5,0 +5,0 @@ "license": "Apache-2.0", |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1964312
33532