Skip to content

Commit 6ab7d2b

Browse files
feat: Optimize bundle size with warning codes (#1111)
1 parent f25d1f3 commit 6ab7d2b

File tree

26 files changed

+165
-91
lines changed

26 files changed

+165
-91
lines changed

docs/warning-codes.md

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<a href="https://opensource.newrelic.com/oss-category/#community-plus"><picture><source media="(prefers-color-scheme: dark)" srcset="https://github.com/newrelic/opensource-website/raw/main/src/images/categories/dark/Community_Plus.png"><source media="(prefers-color-scheme: light)" srcset="https://github.com/newrelic/opensource-website/raw/main/src/images/categories/Community_Plus.png"><img alt="New Relic Open Source community plus project banner." src="https://github.com/newrelic/opensource-website/raw/main/src/images/categories/Community_Plus.png"></picture></a>
2+
# New Relic Browser Agent Warning Codes
3+
4+
### 1
5+
`An error occurred while setting a property of a Configurable`
6+
### 2
7+
`An error occured while setting a Configurable`
8+
### 3
9+
`Setting a Configurable requires an object as input`
10+
### 4
11+
`Setting a Configurable requires a model to set its initial properties`
12+
### 5
13+
`An invalid session_replay.mask_selector was provided. * will be used.`
14+
### 6
15+
`An invalid session_replay.block_selector was provided and will not be used`
16+
### 7
17+
`An invalid session_replay.mask_input_option was provided and will not be used`
18+
### 8
19+
`Shared context requires an object as input`
20+
### 9
21+
`An error occurred while setting SharedContext`
22+
### 10
23+
`Failed to read from storage API`
24+
### 11
25+
`Failed to write to the storage API`
26+
### 12
27+
`An obfuscation replacement rule was detected missing a "regex" value.`
28+
### 13
29+
`An obfuscation replacement rule contains a "regex" value with an invalid type (must be a string or RegExp)`
30+
### 14
31+
`An obfuscation replacement rule contains a "replacement" value with an invalid type (must be a string)`
32+
### 15
33+
`An error occurred while intercepting XHR`
34+
### 16
35+
`Could not cast log message to string`
36+
### 17
37+
`Could not calculate New Relic server time. Agent shutting down.`
38+
### 18
39+
`RUM call failed. Agent shutting down.`
40+
### 19
41+
`SPA scheduler is not initialized. Saved interaction is not sent!`
42+
### 20
43+
`A problem occurred when starting up session manager. This page will not start or extend any session.`
44+
### 21
45+
`Failed to initialize the agent. Could not determine the runtime environment.`
46+
### 22
47+
`Failed to initialize all enabled instrument classes (agent aborted) -`
48+
### 23
49+
`An unexpected issue occurred`
50+
### 24
51+
`Something prevented the agent from instrumenting.`
52+
### 25
53+
`Something prevented the agent from being downloaded.`
54+
### 26
55+
`Failed to initialize instrument classes.`
56+
### 27
57+
`Downloading runtime APIs failed...`
58+
### 28
59+
`The Browser Agent is attempting to send a very large payload. This is usually tied to large amounts of custom attributes. Please check your configurations.`
60+
### 29
61+
`Failed to wrap logger: invalid argument(s)`
62+
### 30
63+
`Invalid log level`
64+
### 31
65+
`Ignored log: Log is larger than maximum payload size`
66+
### 32
67+
`Ignored log: Invalid message`
68+
### 33
69+
`Session Replay Aborted`
70+
### 34
71+
`Downloading and initializing a feature failed...`
72+
### 35
73+
`Call to agent api failed. The API is not currently initialized.`
74+
### 36
75+
`A feature is enabled but one or more dependent features have not been initialized. This may cause unintended consequences or missing data...`
76+
### 37
77+
`Invalid feature name supplie.`
78+
### 38
79+
`Call to api was made before agent fully initialized.`
80+
### 39
81+
`Failed to execute setCustomAttribute. Name must be a string type.`
82+
### 40
83+
`Failed to execute setCustomAttribute. Non-null value must be a string, number or boolean type.`
84+
### 41
85+
`Failed to execute setUserId. Non-null value must be a string type.`
86+
### 42
87+
`Failed to execute setApplicationVersion. Expected <String | null>`

src/common/config/state/configurable.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { warn } from '../../util/console'
22

33
export function getModeledObject (obj, model) {
44
try {
5-
if (!obj || typeof obj !== 'object') return warn('Setting a Configurable requires an object as input')
6-
if (!model || typeof model !== 'object') return warn('Setting a Configurable requires a model to set its initial properties')
5+
if (!obj || typeof obj !== 'object') return warn(3)
6+
if (!model || typeof model !== 'object') return warn(4)
77
// allow getters and setters to pass from model to target
88
const output = Object.create(
99
Object.getPrototypeOf(model),
@@ -19,11 +19,11 @@ export function getModeledObject (obj, model) {
1919
else if (typeof obj[key] === 'object' && typeof model[key] === 'object') output[key] = getModeledObject(obj[key], model[key])
2020
else output[key] = obj[key]
2121
} catch (e) {
22-
warn('An error occurred while setting a property of a Configurable', e)
22+
warn(1, e)
2323
}
2424
}
2525
return output
2626
} catch (err) {
27-
warn('An error occured while setting a Configurable', err)
27+
warn(2, err)
2828
}
2929
}

src/common/config/state/init.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ const model = () => {
7676
set mask_text_selector (val) {
7777
if (isValidSelector(val)) hiddenState.mask_selector = `${val},${nrMask}`
7878
else if (val === '' || val === null) hiddenState.mask_selector = nrMask
79-
else warn('An invalid session_replay.mask_selector was provided. \'*\' will be used.', val)
79+
else warn(5, val)
8080
},
8181
// these properties only have getters because they are enforcable constants and should error if someone tries to override them
8282
get block_class () { return 'nr-block' },
@@ -89,15 +89,15 @@ const model = () => {
8989
},
9090
set block_selector (val) {
9191
if (isValidSelector(val)) hiddenState.block_selector += `,${val}`
92-
else if (val !== '') warn('An invalid session_replay.block_selector was provided and will not be used', val)
92+
else if (val !== '') warn(6, val)
9393
},
9494
// password: must always be present and true no matter what customer sets
9595
get mask_input_options () {
9696
return hiddenState.mask_input_options
9797
},
9898
set mask_input_options (val) {
9999
if (val && typeof val === 'object') hiddenState.mask_input_options = { ...val, password: true }
100-
else warn('An invalid session_replay.mask_input_option was provided and will not be used', val)
100+
else warn(7, val)
101101
}
102102
},
103103
session_trace: { enabled: true, harvestTimeSeconds: 10, autoStart: true },

src/common/context/shared-context.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ const model = {
88
export class SharedContext {
99
constructor (context) {
1010
try {
11-
if (typeof context !== 'object') return warn('shared context requires an object as input')
11+
if (typeof context !== 'object') return warn(8)
1212
this.sharedContext = {}
1313
Object.assign(this.sharedContext, model)
1414
Object.entries(context).forEach(([key, value]) => {
1515
if (Object.keys(model).includes(key)) this.sharedContext[key] = value
1616
})
1717
} catch (err) {
18-
warn('An error occurred while setting SharedContext', err)
18+
warn(9, err)
1919
}
2020
}
2121
}

src/common/harvest/harvest.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ export class Harvest extends SharedContext {
122122
body = stringify(body)
123123
}
124124
/** Warn --once per endpoint-- if the agent tries to send large payloads */
125-
if (body.length > 750000 && (warnings[endpoint] = (warnings?.[endpoint] || 0) + 1) === 1) warn(`The Browser Agent is attempting to send a very large payload to /${endpoint}. This is usually tied to large amounts of custom attributes. Please check your configurations.`)
125+
if (body.length > 750000 && (warnings[endpoint] = (warnings?.[endpoint] || 0) + 1) === 1) warn(28, endpoint)
126126
}
127127

128128
if (!body || body.length === 0 || body === '{}' || body === '[]') {

src/common/session/session-entity.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ export class SessionEntity {
182182

183183
return obj
184184
} catch (e) {
185-
warn('Failed to read from storage API', e)
185+
warn(10, e)
186186
// storage is inaccessible
187187
return {}
188188
}
@@ -208,7 +208,7 @@ export class SessionEntity {
208208
return data
209209
} catch (e) {
210210
// storage is inaccessible
211-
warn('Failed to write to the storage API', e)
211+
warn(11, e)
212212
return null
213213
}
214214
}

src/common/util/console.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
* @param {*} [secondary] Secondary data to include, usually an error or object
55
* @returns
66
*/
7-
export function warn (message, secondary) {
8-
if (typeof console.warn !== 'function') return
9-
console.warn(`New Relic: ${message}`)
10-
if (secondary) console.warn(secondary)
7+
export function warn (code, secondary) {
8+
if (typeof console.debug !== 'function') return
9+
console.debug(`New Relic Warning: https://github.com/newrelic/newrelic-browser-agent/blob/main/warning-codes.md#${code}`, secondary)
1110
}

src/common/util/obfuscate.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,16 @@ export function validateRules (rules) {
4949
var invalidRegexDetected = false
5050
for (var i = 0; i < rules.length; i++) {
5151
if (!('regex' in rules[i])) {
52-
warn('An obfuscation replacement rule was detected missing a "regex" value.')
52+
warn(12)
5353
invalidRegexDetected = true
5454
} else if (typeof rules[i].regex !== 'string' && !(rules[i].regex instanceof RegExp)) {
55-
warn('An obfuscation replacement rule contains a "regex" value with an invalid type (must be a string or RegExp)')
55+
warn(13)
5656
invalidRegexDetected = true
5757
}
5858

5959
var replacement = rules[i].replacement
6060
if (replacement && typeof replacement !== 'string') {
61-
warn('An obfuscation replacement rule contains a "replacement" value with an invalid type (must be a string)')
61+
warn(14)
6262
invalidReplacementDetected = true
6363
}
6464
}

src/common/wrap/wrap-logger.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
* This module is used by: jserrors, spa.
88
*/
99

10-
import { LOGGING_FAILURE_MESSAGE } from '../../features/logging/constants'
1110
import { ee as baseEE, contextId } from '../event-emitter/contextual-ee'
1211
import { EventContext } from '../event-emitter/event-context'
1312
import { warn } from '../util/console'
@@ -22,7 +21,7 @@ import { createWrapperWithEmitter as wfn } from './wrap-function'
2221
*/
2322
// eslint-disable-next-line
2423
export function wrapLogger(sharedEE, parent, loggerFn, context) {
25-
if (!(typeof parent === 'object' && !!parent && typeof loggerFn === 'string' && !!loggerFn && typeof parent[loggerFn] === 'function')) return warn(LOGGING_FAILURE_MESSAGE + 'invalid argument(s)')
24+
if (!(typeof parent === 'object' && !!parent && typeof loggerFn === 'string' && !!loggerFn && typeof parent[loggerFn] === 'function')) return warn(29)
2625
const ee = scopedEE(sharedEE)
2726
const wrapFn = wfn(ee)
2827

src/common/wrap/wrap-xhr.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export function wrapXhr (sharedEE) {
5656
ee.emit('new-xhr', [xhr], context)
5757
xhr.addEventListener(READY_STATE_CHANGE, wrapXHR(context), eventListenerOpts(false))
5858
} catch (e) {
59-
warn('An error occurred while intercepting XHR', e)
59+
warn(15, e)
6060
try {
6161
ee.emit('internal-error', [e])
6262
} catch (err) {

src/features/logging/aggregate/index.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { warn } from '../../../common/util/console'
66
import { stringify } from '../../../common/util/stringify'
77
import { SUPPORTABILITY_METRIC_CHANNEL } from '../../metrics/constants'
88
import { AggregateBase } from '../../utils/aggregate-base'
9-
import { FEATURE_NAME, LOGGING_EVENT_EMITTER_CHANNEL, LOGGING_IGNORED, LOGGING_LEVEL_FAILURE_MESSAGE, LOG_LEVELS, MAX_PAYLOAD_SIZE } from '../constants'
9+
import { FEATURE_NAME, LOGGING_EVENT_EMITTER_CHANNEL, LOG_LEVELS, MAX_PAYLOAD_SIZE } from '../constants'
1010
import { Log } from '../shared/log'
1111
import { isValidLogLevel } from '../shared/utils'
1212

@@ -49,7 +49,7 @@ export class Aggregate extends AggregateBase {
4949

5050
if (!attributes || typeof attributes !== 'object') attributes = {}
5151
if (typeof level === 'string') level = level.toUpperCase()
52-
if (!isValidLogLevel(level)) return warn(LOGGING_LEVEL_FAILURE_MESSAGE + level, Object.values(LOG_LEVELS))
52+
if (!isValidLogLevel(level)) return warn(30, level)
5353

5454
try {
5555
if (typeof message !== 'string') {
@@ -63,13 +63,13 @@ export class Aggregate extends AggregateBase {
6363
else message = String(message)
6464
}
6565
} catch (err) {
66-
warn('could not cast log message to string', message)
66+
warn(16, message)
6767
return
6868
}
69-
if (typeof message !== 'string' || !message) return warn(LOGGING_IGNORED + 'invalid message')
69+
if (typeof message !== 'string' || !message) return warn(32)
7070
if (message.length > MAX_PAYLOAD_SIZE) {
7171
handle(SUPPORTABILITY_METRIC_CHANNEL, ['Logging/Harvest/Failed/Seen', message.length])
72-
return warn(LOGGING_IGNORED + '> ' + MAX_PAYLOAD_SIZE + ' bytes: ', message.slice(0, 25) + '...')
72+
return warn(31, message.slice(0, 25) + '...')
7373
}
7474

7575
const log = new Log(
@@ -81,7 +81,7 @@ export class Aggregate extends AggregateBase {
8181
const logBytes = log.message.length + stringify(log.attributes).length + log.level.length + 10 // timestamp == 10 chars
8282
if (logBytes > MAX_PAYLOAD_SIZE) {
8383
handle(SUPPORTABILITY_METRIC_CHANNEL, ['Logging/Harvest/Failed/Seen', logBytes])
84-
return warn(LOGGING_IGNORED + '> ' + MAX_PAYLOAD_SIZE + ' bytes: ', log.message.slice(0, 25) + '...')
84+
return warn(31, log.message.slice(0, 25) + '...')
8585
}
8686

8787
if (this.estimatedBytes + logBytes >= MAX_PAYLOAD_SIZE) {

src/features/logging/constants.js

-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,3 @@ export const LOGGING_EVENT_EMITTER_CHANNEL = 'log'
1313
export const FEATURE_NAME = FEATURE_NAMES.logging
1414

1515
export const MAX_PAYLOAD_SIZE = 1000000
16-
17-
export const LOGGING_FAILURE_MESSAGE = 'failed to wrap logger: '
18-
export const LOGGING_LEVEL_FAILURE_MESSAGE = 'invalid log level: '
19-
export const LOGGING_IGNORED = 'ignored log: '

src/features/page_view_event/aggregate/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ export class Aggregate extends AggregateBase {
130130
handle(SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/Failed'], undefined, FEATURE_NAMES.metrics, this.ee)
131131
drain(this.agentIdentifier, FEATURE_NAMES.metrics, true)
132132
this.ee.abort()
133-
warn('Could not calculate New Relic server time. Agent shutting down.', error)
133+
warn(17, error)
134134
return
135135
}
136136

@@ -141,7 +141,7 @@ export class Aggregate extends AggregateBase {
141141
this.drain()
142142
} catch (err) {
143143
this.ee.abort()
144-
warn('RUM call failed. Agent shutting down.', err)
144+
warn(18, err)
145145
}
146146
}
147147
})

src/features/session_replay/aggregate/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ export class Aggregate extends AggregateBase {
394394

395395
/** Abort the feature, once aborted it will not resume */
396396
abort (reason = {}, data) {
397-
warn(`SR aborted -- ${reason.message}`)
397+
warn(33, reason.message)
398398
handle(SUPPORTABILITY_METRIC_CHANNEL, [`SessionReplay/Abort/${reason.sm}`, data], undefined, FEATURE_NAMES.metrics, this.ee)
399399
this.blocked = true
400400
this.mode = MODE.OFF

src/features/spa/aggregate/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -757,7 +757,7 @@ export class Aggregate extends AggregateBase {
757757
handle(SUPPORTABILITY_METRIC_CHANNEL, [`Spa/Interaction/${smCategory}/Duration/Ms`, Math.max((interaction.root?.end || 0) - (interaction.root?.start || 0), 0)], undefined, FEATURE_NAMES.metrics, baseEE)
758758

759759
scheduler?.scheduleHarvest(0)
760-
if (!scheduler) warn('SPA scheduler is not initialized. Saved interaction is not sent!')
760+
if (!scheduler) warn(19)
761761
}
762762

763763
function isEnabled () {

src/features/utils/instrument-base.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export class InstrumentBase extends FeatureBase {
8585
session = setupAgentSession(this.agentIdentifier)
8686
}
8787
} catch (e) {
88-
warn('A problem occurred when starting up session manager. This page will not start or extend any session.', e)
88+
warn(20, e)
8989
this.ee.emit('internal-error', [e])
9090
if (this.featureName === FEATURE_NAMES.sessionReplay) this.abortHandler?.() // SR should stop recording if session DNE
9191
}
@@ -105,7 +105,7 @@ export class InstrumentBase extends FeatureBase {
105105
this.featAggregate = new Aggregate(this.agentIdentifier, this.aggregator, argsObjFromInstrument)
106106
loadedSuccessfully(true)
107107
} catch (e) {
108-
warn(`Downloading and initializing ${this.featureName} failed...`, e)
108+
warn(34, e)
109109
this.abortHandler?.() // undo any important alterations made to the page
110110
// not supported yet but nice to do: "abort" this agent's EE for this feature specifically
111111
drain(this.agentIdentifier, this.featureName, true)

src/loaders/agent-base.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export class AgentBase {
2525
* @param {...any} args
2626
*/
2727
#callMethod (methodName, ...args) {
28-
if (typeof this.api?.[methodName] !== 'function') warn(`Call to agent api ${methodName} failed. The API is not currently initialized.`)
28+
if (typeof this.api?.[methodName] !== 'function') warn(35, methodName)
2929
else return this.api[methodName](...args)
3030
}
3131

src/loaders/agent.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import { Instrument as PageViewEvent } from '../features/page_view_event/instrum
1313
import { Aggregator } from '../common/aggregate/aggregator'
1414
import { gosNREUM, setNREUMInitializedAgent } from '../common/window/nreum'
1515
import { warn } from '../common/util/console'
16-
import { stringify } from '../common/util/stringify'
1716
import { globalScope } from '../common/constants/runtime'
1817

1918
/**
@@ -31,7 +30,7 @@ export class Agent extends AgentBase {
3130
if (!globalScope) {
3231
// We could not determine the runtime environment. Short-circuite the agent here
3332
// to avoid possible exceptions later that may cause issues with customer's application.
34-
warn('Failed to initialize the agent. Could not determine the runtime environment.')
33+
warn(21)
3534
return
3635
}
3736

@@ -74,12 +73,12 @@ export class Agent extends AgentBase {
7473

7574
const dependencies = getFeatureDependencyNames(InstrumentCtor.featureName)
7675
const hasAllDeps = dependencies.every(featName => featName in this.features) // any other feature(s) this depends on should've been initialized on prior iterations by priority order
77-
if (!hasAllDeps) warn(`${InstrumentCtor.featureName} is enabled but one or more dependent features has not been initialized (${stringify(dependencies)}). This may cause unintended consequences or missing data...`)
76+
if (!hasAllDeps) warn(36, InstrumentCtor.featureName)
7877

7978
this.features[InstrumentCtor.featureName] = new InstrumentCtor(this.agentIdentifier, this.sharedAggregator)
8079
})
8180
} catch (err) {
82-
warn('Failed to initialize all enabled instrument classes (agent aborted) -', err)
81+
warn(22, err)
8382
for (const featName in this.features) { // this.features hold only features that have been instantiated
8483
this.features[featName].abortHandler?.()
8584
}

0 commit comments

Comments
 (0)