@newrelic/browser-agent 1.279.0 → 1.280.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/cjs/common/constants/env.cdn.js +1 -1
  3. package/dist/cjs/common/constants/env.npm.js +1 -1
  4. package/dist/cjs/common/vitals/constants.js +2 -5
  5. package/dist/cjs/common/vitals/first-input-delay.js +36 -0
  6. package/dist/cjs/features/generic_events/aggregate/index.js +11 -10
  7. package/dist/cjs/features/logging/aggregate/index.js +4 -3
  8. package/dist/cjs/features/page_view_timing/aggregate/index.js +3 -3
  9. package/dist/cjs/features/session_trace/aggregate/trace/storage.js +7 -0
  10. package/dist/cjs/loaders/agent.js +2 -3
  11. package/dist/cjs/loaders/micro-agent-base.js +2 -2
  12. package/dist/cjs/loaders/micro-agent.js +2 -3
  13. package/dist/esm/common/constants/env.cdn.js +1 -1
  14. package/dist/esm/common/constants/env.npm.js +1 -1
  15. package/dist/esm/common/vitals/constants.js +1 -4
  16. package/dist/esm/common/vitals/first-input-delay.js +29 -0
  17. package/dist/esm/features/generic_events/aggregate/index.js +11 -10
  18. package/dist/esm/features/logging/aggregate/index.js +4 -3
  19. package/dist/esm/features/page_view_timing/aggregate/index.js +3 -3
  20. package/dist/esm/features/session_trace/aggregate/trace/storage.js +7 -0
  21. package/dist/esm/loaders/agent.js +2 -3
  22. package/dist/esm/loaders/micro-agent-base.js +2 -2
  23. package/dist/esm/loaders/micro-agent.js +2 -3
  24. package/dist/types/common/vitals/constants.d.ts +1 -4
  25. package/dist/types/common/vitals/first-input-delay.d.ts +3 -0
  26. package/dist/types/common/vitals/first-input-delay.d.ts.map +1 -0
  27. package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
  28. package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
  29. package/dist/types/features/session_trace/aggregate/trace/storage.d.ts.map +1 -1
  30. package/dist/types/loaders/agent.d.ts +1 -2
  31. package/dist/types/loaders/agent.d.ts.map +1 -1
  32. package/dist/types/loaders/micro-agent-base.d.ts +0 -1
  33. package/dist/types/loaders/micro-agent-base.d.ts.map +1 -1
  34. package/dist/types/loaders/micro-agent.d.ts +1 -2
  35. package/dist/types/loaders/micro-agent.d.ts.map +1 -1
  36. package/package.json +2 -2
  37. package/src/common/vitals/constants.js +1 -5
  38. package/src/common/vitals/first-input-delay.js +28 -0
  39. package/src/features/generic_events/aggregate/index.js +11 -10
  40. package/src/features/logging/aggregate/index.js +4 -3
  41. package/src/features/page_view_timing/aggregate/index.js +3 -3
  42. package/src/features/session_trace/aggregate/trace/storage.js +5 -0
  43. package/src/loaders/agent.js +2 -3
  44. package/src/loaders/micro-agent-base.js +2 -2
  45. package/src/loaders/micro-agent.js +2 -3
  46. package/dist/cjs/common/vitals/first-interaction.js +0 -44
  47. package/dist/esm/common/vitals/first-interaction.js +0 -38
  48. package/dist/types/common/vitals/first-interaction.d.ts +0 -3
  49. package/dist/types/common/vitals/first-interaction.d.ts.map +0 -1
  50. package/src/common/vitals/first-interaction.js +0 -38
package/CHANGELOG.md CHANGED
@@ -3,6 +3,25 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.280.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.279.1...v1.280.0) (2025-01-31)
7
+
8
+
9
+ ### Features
10
+
11
+ * Remove agentIdentifier argument from agent constructors ([#1353](https://github.com/newrelic/newrelic-browser-agent/issues/1353)) ([cb866e5](https://github.com/newrelic/newrelic-browser-agent/commit/cb866e5678bf6aa898c082f2be83145a5014fd0e))
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * Roll back to previous FirstInteraction implementation ([#1359](https://github.com/newrelic/newrelic-browser-agent/issues/1359)) ([c2e22ab](https://github.com/newrelic/newrelic-browser-agent/commit/c2e22ab49b00e9cfbeb54664a820e1aa4ed28a53))
17
+
18
+ ## [1.279.1](https://github.com/newrelic/newrelic-browser-agent/compare/v1.279.0...v1.279.1) (2025-01-28)
19
+
20
+
21
+ ### Bug Fixes
22
+
23
+ * CLS timing node not being reported post new Harvester ([#1352](https://github.com/newrelic/newrelic-browser-agent/issues/1352)) ([5db1d97](https://github.com/newrelic/newrelic-browser-agent/commit/5db1d97a147c78bf93dee669ff9da95bb560d1db))
24
+
6
25
  ## [1.279.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.278.3...v1.279.0) (2025-01-24)
7
26
 
8
27
 
@@ -17,7 +17,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.DIST_METHOD = exports.BUILD_EN
17
17
  /**
18
18
  * Exposes the version of the agent
19
19
  */
20
- const VERSION = exports.VERSION = "1.279.0";
20
+ const VERSION = exports.VERSION = "1.280.0";
21
21
 
22
22
  /**
23
23
  * Exposes the build type of the agent
@@ -17,7 +17,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.DIST_METHOD = exports.BUILD_EN
17
17
  /**
18
18
  * Exposes the version of the agent
19
19
  */
20
- const VERSION = exports.VERSION = "1.279.0";
20
+ const VERSION = exports.VERSION = "1.280.0";
21
21
 
22
22
  /**
23
23
  * Exposes the build type of the agent
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.VITAL_NAMES = exports.PERFORMANCE_ENTRY_TYPE = void 0;
6
+ exports.VITAL_NAMES = void 0;
7
7
  /**
8
8
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
9
9
  * SPDX-License-Identifier: Apache-2.0
@@ -11,12 +11,9 @@ exports.VITAL_NAMES = exports.PERFORMANCE_ENTRY_TYPE = void 0;
11
11
  const VITAL_NAMES = exports.VITAL_NAMES = {
12
12
  FIRST_PAINT: 'fp',
13
13
  FIRST_CONTENTFUL_PAINT: 'fcp',
14
- FIRST_INTERACTION: 'fi',
14
+ FIRST_INPUT_DELAY: 'fi',
15
15
  LARGEST_CONTENTFUL_PAINT: 'lcp',
16
16
  CUMULATIVE_LAYOUT_SHIFT: 'cls',
17
17
  INTERACTION_TO_NEXT_PAINT: 'inp',
18
18
  TIME_TO_FIRST_BYTE: 'ttfb'
19
- };
20
- const PERFORMANCE_ENTRY_TYPE = exports.PERFORMANCE_ENTRY_TYPE = {
21
- FIRST_INPUT: 'first-input'
22
19
  };
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.firstInputDelay = void 0;
7
+ var _attribution = require("web-vitals/attribution");
8
+ var _vitalMetric = require("./vital-metric");
9
+ var _constants = require("./constants");
10
+ var _runtime = require("../constants/runtime");
11
+ /**
12
+ * Copyright 2020-2025 New Relic, Inc. All rights reserved.
13
+ * SPDX-License-Identifier: Apache-2.0
14
+ */
15
+
16
+ const firstInputDelay = exports.firstInputDelay = new _vitalMetric.VitalMetric(_constants.VITAL_NAMES.FIRST_INPUT_DELAY);
17
+ if (_runtime.isBrowserScope) {
18
+ (0, _attribution.onFID)(({
19
+ value,
20
+ attribution
21
+ }) => {
22
+ if (_runtime.initiallyHidden || firstInputDelay.isValid) return;
23
+ const attrs = {
24
+ type: attribution.eventType,
25
+ fid: Math.round(value),
26
+ eventTarget: attribution.eventTarget,
27
+ loadState: attribution.loadState
28
+ };
29
+
30
+ // CWV will only report one (THE) first-input entry to us; fid isn't reported if there are no user interactions occurs before the *first* page hiding.
31
+ firstInputDelay.update({
32
+ value: attribution.eventTime,
33
+ attrs
34
+ });
35
+ });
36
+ }
@@ -18,6 +18,7 @@ var _userActionsAggregator = require("./user-actions/user-actions-aggregator");
18
18
  var _iframe = require("../../../common/dom/iframe");
19
19
  var _handle = require("../../../common/event-emitter/handle");
20
20
  var _typeCheck = require("../../../common/util/type-check");
21
+ var _features = require("../../../loaders/features/features");
21
22
  /**
22
23
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
23
24
  * SPDX-License-Identifier: Apache-2.0
@@ -134,7 +135,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
134
135
  const observer = new PerformanceObserver(list => {
135
136
  list.getEntries().forEach(entry => {
136
137
  try {
137
- (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/' + type + '/Seen']);
138
+ (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/' + type + '/Seen'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
138
139
  const detailObj = agentRef.init.performance.capture_detail ? createDetailAttrs(entry.detail) : {};
139
140
  this.addEvent({
140
141
  ...detailObj,
@@ -196,12 +197,12 @@ class Aggregate extends _aggregateBase.AggregateBase {
196
197
  if (this.agentRef.init.performance.resources.asset_types.length && !this.agentRef.init.performance.resources.asset_types.includes(entryObject.initiatorType)) return;
197
198
  /** decide if the entryDomain is a first party domain */
198
199
  firstParty = entryDomain === _runtime.globalScope?.location.hostname || agentRef.init.performance.resources.first_party_domains.includes(entryDomain);
199
- if (firstParty) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/FirstPartyResource/Seen']);
200
- if (isNr) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/NrResource/Seen']);
200
+ if (firstParty) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/FirstPartyResource/Seen'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
201
+ if (isNr) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/NrResource/Seen'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
201
202
  } catch (err) {
202
203
  // couldnt parse the URL, so firstParty will just default to false
203
204
  }
204
- (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/Resource/Seen']);
205
+ (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/Resource/Seen'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
205
206
  const event = {
206
207
  ...entryObject,
207
208
  eventType: 'BrowserPerformance',
@@ -287,12 +288,12 @@ class Aggregate extends _aggregateBase.AggregateBase {
287
288
  trackSupportabilityMetrics() {
288
289
  /** track usage SMs to improve these experimental features */
289
290
  const configPerfTag = 'Config/Performance/';
290
- if (this.agentRef.init.performance.capture_marks) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'CaptureMarks/Enabled']);
291
- if (this.agentRef.init.performance.capture_measures) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'CaptureMeasures/Enabled']);
292
- if (this.agentRef.init.performance.resources.enabled) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/Enabled']);
293
- if (this.agentRef.init.performance.resources.asset_types?.length !== 0) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/AssetTypes/Changed']);
294
- if (this.agentRef.init.performance.resources.first_party_domains?.length !== 0) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/FirstPartyDomains/Changed']);
295
- if (this.agentRef.init.performance.resources.ignore_newrelic === false) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/IgnoreNewrelic/Changed']);
291
+ if (this.agentRef.init.performance.capture_marks) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'CaptureMarks/Enabled'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
292
+ if (this.agentRef.init.performance.capture_measures) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'CaptureMeasures/Enabled'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
293
+ if (this.agentRef.init.performance.resources.enabled) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/Enabled'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
294
+ if (this.agentRef.init.performance.resources.asset_types?.length !== 0) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/AssetTypes/Changed'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
295
+ if (this.agentRef.init.performance.resources.first_party_domains?.length !== 0) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/FirstPartyDomains/Changed'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
296
+ if (this.agentRef.init.performance.resources.ignore_newrelic === false) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/IgnoreNewrelic/Changed'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
296
297
  }
297
298
  }
298
299
  exports.Aggregate = Aggregate;
@@ -15,6 +15,7 @@ var _log = require("../shared/log");
15
15
  var _utils = require("../shared/utils");
16
16
  var _traverse = require("../../../common/util/traverse");
17
17
  var _agentConstants = require("../../../common/constants/agent-constants");
18
+ var _features = require("../../../loaders/features/features");
18
19
  /**
19
20
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
20
21
  * SPDX-License-Identifier: Apache-2.0
@@ -59,17 +60,17 @@ class Aggregate extends _aggregateBase.AggregateBase {
59
60
  const failToHarvestMessage = 'Logging/Harvest/Failed/Seen';
60
61
  if (logBytes > _agentConstants.MAX_PAYLOAD_SIZE) {
61
62
  // cannot possibly send this, even with an empty buffer
62
- (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, [failToHarvestMessage, logBytes]);
63
+ (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, [failToHarvestMessage, logBytes], undefined, _features.FEATURE_NAMES.metrics, this.ee);
63
64
  (0, _console.warn)(31, log.message.slice(0, 25) + '...');
64
65
  return;
65
66
  }
66
67
  if (this.events.wouldExceedMaxSize(logBytes)) {
67
- (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['Logging/Harvest/Early/Seen', this.events.byteSize() + logBytes]);
68
+ (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['Logging/Harvest/Early/Seen', this.events.byteSize() + logBytes], undefined, _features.FEATURE_NAMES.metrics, this.ee);
68
69
  this.agentRef.runtime.harvester.triggerHarvestFor(this); // force a harvest synchronously to try adding again
69
70
  }
70
71
  if (!this.events.add(log)) {
71
72
  // still failed after a harvest attempt despite not being too large would mean harvest failed with options.retry
72
- (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, [failToHarvestMessage, logBytes]);
73
+ (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, [failToHarvestMessage, logBytes], undefined, _features.FEATURE_NAMES.metrics, this.ee);
73
74
  (0, _console.warn)(31, log.message.slice(0, 25) + '...');
74
75
  }
75
76
  }
@@ -12,8 +12,8 @@ var _features = require("../../../loaders/features/features");
12
12
  var _aggregateBase = require("../../utils/aggregate-base");
13
13
  var _cumulativeLayoutShift = require("../../../common/vitals/cumulative-layout-shift");
14
14
  var _firstContentfulPaint = require("../../../common/vitals/first-contentful-paint");
15
+ var _firstInputDelay = require("../../../common/vitals/first-input-delay");
15
16
  var _firstPaint = require("../../../common/vitals/first-paint");
16
- var _firstInteraction = require("../../../common/vitals/first-interaction");
17
17
  var _interactionToNextPaint = require("../../../common/vitals/interaction-to-next-paint");
18
18
  var _largestContentfulPaint = require("../../../common/vitals/largest-contentful-paint");
19
19
  var _timeToFirstByte = require("../../../common/vitals/time-to-first-byte");
@@ -42,8 +42,8 @@ class Aggregate extends _aggregateBase.AggregateBase {
42
42
  this.waitForFlags([]).then(() => {
43
43
  _firstPaint.firstPaint.subscribe(this.#handleVitalMetric);
44
44
  _firstContentfulPaint.firstContentfulPaint.subscribe(this.#handleVitalMetric);
45
+ _firstInputDelay.firstInputDelay.subscribe(this.#handleVitalMetric);
45
46
  _largestContentfulPaint.largestContentfulPaint.subscribe(this.#handleVitalMetric);
46
- _firstInteraction.firstInteraction.subscribe(this.#handleVitalMetric);
47
47
  _interactionToNextPaint.interactionToNextPaint.subscribe(this.#handleVitalMetric);
48
48
  _timeToFirstByte.timeToFirstByte.subscribe(({
49
49
  attrs
@@ -61,7 +61,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
61
61
  } = _cumulativeLayoutShift.cumulativeLayoutShift.current;
62
62
  if (value === undefined) return;
63
63
  this.addTiming(name, value * 1000, attrs);
64
- }, true); // CLS node should only reports on vis change rather than on every change
64
+ }, true, true); // CLS node should only reports on vis change rather than on every change
65
65
 
66
66
  this.drain();
67
67
  });
@@ -144,6 +144,13 @@ class TraceStorage {
144
144
  this.storeTiming({
145
145
  [name]: value
146
146
  });
147
+ if (hasFID(name, attrs)) this.storeEvent({
148
+ type: 'fid',
149
+ target: 'document'
150
+ }, 'document', value, value + attrs.fid);
151
+ function hasFID(name, attrs) {
152
+ return name === 'fi' && !!attrs && typeof attrs.fid === 'number';
153
+ }
147
154
  }
148
155
  storeTiming(timingEntry, isAbsoluteTimestamp = false) {
149
156
  if (!timingEntry) return;
@@ -35,10 +35,9 @@ var _runtime = require("../common/constants/runtime");
35
35
  class Agent extends _agentBase.AgentBase {
36
36
  /**
37
37
  * @param {Object} options Options to initialize agent with
38
- * @param {string} [agentIdentifier] Optional identifier of agent
39
38
  */
40
- constructor(options, agentIdentifier) {
41
- super(agentIdentifier);
39
+ constructor(options) {
40
+ super();
42
41
  if (!_runtime.globalScope) {
43
42
  // We could not determine the runtime environment. Short-circuite the agent here
44
43
  // to avoid possible exceptions later that may cause issues with customer's application.
@@ -13,8 +13,8 @@ var _uniqueId = require("../common/ids/unique-id");
13
13
 
14
14
  class MicroAgentBase {
15
15
  agentIdentifier;
16
- constructor(agentIdentifier = (0, _uniqueId.generateRandomHexString)(16)) {
17
- this.agentIdentifier = agentIdentifier;
16
+ constructor() {
17
+ this.agentIdentifier = (0, _uniqueId.generateRandomHexString)(16);
18
18
  }
19
19
 
20
20
  /**
@@ -27,10 +27,9 @@ const nonAutoFeatures = [_features.FEATURE_NAMES.jserrors, _features.FEATURE_NAM
27
27
  class MicroAgent extends _microAgentBase.MicroAgentBase {
28
28
  /**
29
29
  * @param {Object} options - Specifies features and runtime configuration,
30
- * @param {string=} agentIdentifier - The optional unique ID of the agent.
31
30
  */
32
- constructor(options, agentIdentifier) {
33
- super(agentIdentifier);
31
+ constructor(options) {
32
+ super();
34
33
  this.features = {};
35
34
  (0, _nreum.setNREUMInitializedAgent)(this.agentIdentifier, this);
36
35
  (0, _configure.configure)(this, {
@@ -11,7 +11,7 @@
11
11
  /**
12
12
  * Exposes the version of the agent
13
13
  */
14
- export const VERSION = "1.279.0";
14
+ export const VERSION = "1.280.0";
15
15
 
16
16
  /**
17
17
  * Exposes the build type of the agent
@@ -11,7 +11,7 @@
11
11
  /**
12
12
  * Exposes the version of the agent
13
13
  */
14
- export const VERSION = "1.279.0";
14
+ export const VERSION = "1.280.0";
15
15
 
16
16
  /**
17
17
  * Exposes the build type of the agent
@@ -5,12 +5,9 @@
5
5
  export const VITAL_NAMES = {
6
6
  FIRST_PAINT: 'fp',
7
7
  FIRST_CONTENTFUL_PAINT: 'fcp',
8
- FIRST_INTERACTION: 'fi',
8
+ FIRST_INPUT_DELAY: 'fi',
9
9
  LARGEST_CONTENTFUL_PAINT: 'lcp',
10
10
  CUMULATIVE_LAYOUT_SHIFT: 'cls',
11
11
  INTERACTION_TO_NEXT_PAINT: 'inp',
12
12
  TIME_TO_FIRST_BYTE: 'ttfb'
13
- };
14
- export const PERFORMANCE_ENTRY_TYPE = {
15
- FIRST_INPUT: 'first-input'
16
13
  };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Copyright 2020-2025 New Relic, Inc. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { onFID } from 'web-vitals/attribution';
6
+ import { VitalMetric } from './vital-metric';
7
+ import { VITAL_NAMES } from './constants';
8
+ import { initiallyHidden, isBrowserScope } from '../constants/runtime';
9
+ export const firstInputDelay = new VitalMetric(VITAL_NAMES.FIRST_INPUT_DELAY);
10
+ if (isBrowserScope) {
11
+ onFID(({
12
+ value,
13
+ attribution
14
+ }) => {
15
+ if (initiallyHidden || firstInputDelay.isValid) return;
16
+ const attrs = {
17
+ type: attribution.eventType,
18
+ fid: Math.round(value),
19
+ eventTarget: attribution.eventTarget,
20
+ loadState: attribution.loadState
21
+ };
22
+
23
+ // CWV will only report one (THE) first-input entry to us; fid isn't reported if there are no user interactions occurs before the *first* page hiding.
24
+ firstInputDelay.update({
25
+ value: attribution.eventTime,
26
+ attrs
27
+ });
28
+ });
29
+ }
@@ -16,6 +16,7 @@ import { UserActionsAggregator } from './user-actions/user-actions-aggregator';
16
16
  import { isIFrameWindow } from '../../../common/dom/iframe';
17
17
  import { handle } from '../../../common/event-emitter/handle';
18
18
  import { isPureObject } from '../../../common/util/type-check';
19
+ import { FEATURE_NAMES } from '../../../loaders/features/features';
19
20
  export class Aggregate extends AggregateBase {
20
21
  static featureName = FEATURE_NAME;
21
22
  constructor(agentRef) {
@@ -127,7 +128,7 @@ export class Aggregate extends AggregateBase {
127
128
  const observer = new PerformanceObserver(list => {
128
129
  list.getEntries().forEach(entry => {
129
130
  try {
130
- handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/' + type + '/Seen']);
131
+ handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/' + type + '/Seen'], undefined, FEATURE_NAMES.metrics, this.ee);
131
132
  const detailObj = agentRef.init.performance.capture_detail ? createDetailAttrs(entry.detail) : {};
132
133
  this.addEvent({
133
134
  ...detailObj,
@@ -189,12 +190,12 @@ export class Aggregate extends AggregateBase {
189
190
  if (this.agentRef.init.performance.resources.asset_types.length && !this.agentRef.init.performance.resources.asset_types.includes(entryObject.initiatorType)) return;
190
191
  /** decide if the entryDomain is a first party domain */
191
192
  firstParty = entryDomain === globalScope?.location.hostname || agentRef.init.performance.resources.first_party_domains.includes(entryDomain);
192
- if (firstParty) handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/FirstPartyResource/Seen']);
193
- if (isNr) handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/NrResource/Seen']);
193
+ if (firstParty) handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/FirstPartyResource/Seen'], undefined, FEATURE_NAMES.metrics, this.ee);
194
+ if (isNr) handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/NrResource/Seen'], undefined, FEATURE_NAMES.metrics, this.ee);
194
195
  } catch (err) {
195
196
  // couldnt parse the URL, so firstParty will just default to false
196
197
  }
197
- handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/Resource/Seen']);
198
+ handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/Resource/Seen'], undefined, FEATURE_NAMES.metrics, this.ee);
198
199
  const event = {
199
200
  ...entryObject,
200
201
  eventType: 'BrowserPerformance',
@@ -280,11 +281,11 @@ export class Aggregate extends AggregateBase {
280
281
  trackSupportabilityMetrics() {
281
282
  /** track usage SMs to improve these experimental features */
282
283
  const configPerfTag = 'Config/Performance/';
283
- if (this.agentRef.init.performance.capture_marks) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'CaptureMarks/Enabled']);
284
- if (this.agentRef.init.performance.capture_measures) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'CaptureMeasures/Enabled']);
285
- if (this.agentRef.init.performance.resources.enabled) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/Enabled']);
286
- if (this.agentRef.init.performance.resources.asset_types?.length !== 0) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/AssetTypes/Changed']);
287
- if (this.agentRef.init.performance.resources.first_party_domains?.length !== 0) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/FirstPartyDomains/Changed']);
288
- if (this.agentRef.init.performance.resources.ignore_newrelic === false) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/IgnoreNewrelic/Changed']);
284
+ if (this.agentRef.init.performance.capture_marks) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'CaptureMarks/Enabled'], undefined, FEATURE_NAMES.metrics, this.ee);
285
+ if (this.agentRef.init.performance.capture_measures) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'CaptureMeasures/Enabled'], undefined, FEATURE_NAMES.metrics, this.ee);
286
+ if (this.agentRef.init.performance.resources.enabled) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/Enabled'], undefined, FEATURE_NAMES.metrics, this.ee);
287
+ if (this.agentRef.init.performance.resources.asset_types?.length !== 0) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/AssetTypes/Changed'], undefined, FEATURE_NAMES.metrics, this.ee);
288
+ if (this.agentRef.init.performance.resources.first_party_domains?.length !== 0) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/FirstPartyDomains/Changed'], undefined, FEATURE_NAMES.metrics, this.ee);
289
+ if (this.agentRef.init.performance.resources.ignore_newrelic === false) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/IgnoreNewrelic/Changed'], undefined, FEATURE_NAMES.metrics, this.ee);
289
290
  }
290
291
  }
@@ -13,6 +13,7 @@ import { Log } from '../shared/log';
13
13
  import { isValidLogLevel } from '../shared/utils';
14
14
  import { applyFnToProps } from '../../../common/util/traverse';
15
15
  import { MAX_PAYLOAD_SIZE } from '../../../common/constants/agent-constants';
16
+ import { FEATURE_NAMES } from '../../../loaders/features/features';
16
17
  export class Aggregate extends AggregateBase {
17
18
  static featureName = FEATURE_NAME;
18
19
  constructor(agentRef) {
@@ -52,17 +53,17 @@ export class Aggregate extends AggregateBase {
52
53
  const failToHarvestMessage = 'Logging/Harvest/Failed/Seen';
53
54
  if (logBytes > MAX_PAYLOAD_SIZE) {
54
55
  // cannot possibly send this, even with an empty buffer
55
- handle(SUPPORTABILITY_METRIC_CHANNEL, [failToHarvestMessage, logBytes]);
56
+ handle(SUPPORTABILITY_METRIC_CHANNEL, [failToHarvestMessage, logBytes], undefined, FEATURE_NAMES.metrics, this.ee);
56
57
  warn(31, log.message.slice(0, 25) + '...');
57
58
  return;
58
59
  }
59
60
  if (this.events.wouldExceedMaxSize(logBytes)) {
60
- handle(SUPPORTABILITY_METRIC_CHANNEL, ['Logging/Harvest/Early/Seen', this.events.byteSize() + logBytes]);
61
+ handle(SUPPORTABILITY_METRIC_CHANNEL, ['Logging/Harvest/Early/Seen', this.events.byteSize() + logBytes], undefined, FEATURE_NAMES.metrics, this.ee);
61
62
  this.agentRef.runtime.harvester.triggerHarvestFor(this); // force a harvest synchronously to try adding again
62
63
  }
63
64
  if (!this.events.add(log)) {
64
65
  // still failed after a harvest attempt despite not being too large would mean harvest failed with options.retry
65
- handle(SUPPORTABILITY_METRIC_CHANNEL, [failToHarvestMessage, logBytes]);
66
+ handle(SUPPORTABILITY_METRIC_CHANNEL, [failToHarvestMessage, logBytes], undefined, FEATURE_NAMES.metrics, this.ee);
66
67
  warn(31, log.message.slice(0, 25) + '...');
67
68
  }
68
69
  }
@@ -11,8 +11,8 @@ import { FEATURE_NAMES } from '../../../loaders/features/features';
11
11
  import { AggregateBase } from '../../utils/aggregate-base';
12
12
  import { cumulativeLayoutShift } from '../../../common/vitals/cumulative-layout-shift';
13
13
  import { firstContentfulPaint } from '../../../common/vitals/first-contentful-paint';
14
+ import { firstInputDelay } from '../../../common/vitals/first-input-delay';
14
15
  import { firstPaint } from '../../../common/vitals/first-paint';
15
- import { firstInteraction } from '../../../common/vitals/first-interaction';
16
16
  import { interactionToNextPaint } from '../../../common/vitals/interaction-to-next-paint';
17
17
  import { largestContentfulPaint } from '../../../common/vitals/largest-contentful-paint';
18
18
  import { timeToFirstByte } from '../../../common/vitals/time-to-first-byte';
@@ -36,8 +36,8 @@ export class Aggregate extends AggregateBase {
36
36
  this.waitForFlags([]).then(() => {
37
37
  firstPaint.subscribe(this.#handleVitalMetric);
38
38
  firstContentfulPaint.subscribe(this.#handleVitalMetric);
39
+ firstInputDelay.subscribe(this.#handleVitalMetric);
39
40
  largestContentfulPaint.subscribe(this.#handleVitalMetric);
40
- firstInteraction.subscribe(this.#handleVitalMetric);
41
41
  interactionToNextPaint.subscribe(this.#handleVitalMetric);
42
42
  timeToFirstByte.subscribe(({
43
43
  attrs
@@ -55,7 +55,7 @@ export class Aggregate extends AggregateBase {
55
55
  } = cumulativeLayoutShift.current;
56
56
  if (value === undefined) return;
57
57
  this.addTiming(name, value * 1000, attrs);
58
- }, true); // CLS node should only reports on vis change rather than on every change
58
+ }, true, true); // CLS node should only reports on vis change rather than on every change
59
59
 
60
60
  this.drain();
61
61
  });
@@ -137,6 +137,13 @@ export class TraceStorage {
137
137
  this.storeTiming({
138
138
  [name]: value
139
139
  });
140
+ if (hasFID(name, attrs)) this.storeEvent({
141
+ type: 'fid',
142
+ target: 'document'
143
+ }, 'document', value, value + attrs.fid);
144
+ function hasFID(name, attrs) {
145
+ return name === 'fi' && !!attrs && typeof attrs.fid === 'number';
146
+ }
140
147
  }
141
148
  storeTiming(timingEntry, isAbsoluteTimestamp = false) {
142
149
  if (!timingEntry) return;
@@ -26,10 +26,9 @@ import { globalScope } from '../common/constants/runtime';
26
26
  export class Agent extends AgentBase {
27
27
  /**
28
28
  * @param {Object} options Options to initialize agent with
29
- * @param {string} [agentIdentifier] Optional identifier of agent
30
29
  */
31
- constructor(options, agentIdentifier) {
32
- super(agentIdentifier);
30
+ constructor(options) {
31
+ super();
33
32
  if (!globalScope) {
34
33
  // We could not determine the runtime environment. Short-circuite the agent here
35
34
  // to avoid possible exceptions later that may cause issues with customer's application.
@@ -6,8 +6,8 @@ import { warn } from '../common/util/console';
6
6
  import { generateRandomHexString } from '../common/ids/unique-id';
7
7
  export class MicroAgentBase {
8
8
  agentIdentifier;
9
- constructor(agentIdentifier = generateRandomHexString(16)) {
10
- this.agentIdentifier = agentIdentifier;
9
+ constructor() {
10
+ this.agentIdentifier = generateRandomHexString(16);
11
11
  }
12
12
 
13
13
  /**
@@ -22,10 +22,9 @@ const nonAutoFeatures = [FEATURE_NAMES.jserrors, FEATURE_NAMES.genericEvents, FE
22
22
  export class MicroAgent extends MicroAgentBase {
23
23
  /**
24
24
  * @param {Object} options - Specifies features and runtime configuration,
25
- * @param {string=} agentIdentifier - The optional unique ID of the agent.
26
25
  */
27
- constructor(options, agentIdentifier) {
28
- super(agentIdentifier);
26
+ constructor(options) {
27
+ super();
29
28
  this.features = {};
30
29
  setNREUMInitializedAgent(this.agentIdentifier, this);
31
30
  configure(this, {
@@ -1,13 +1,10 @@
1
1
  export namespace VITAL_NAMES {
2
2
  let FIRST_PAINT: string;
3
3
  let FIRST_CONTENTFUL_PAINT: string;
4
- let FIRST_INTERACTION: string;
4
+ let FIRST_INPUT_DELAY: string;
5
5
  let LARGEST_CONTENTFUL_PAINT: string;
6
6
  let CUMULATIVE_LAYOUT_SHIFT: string;
7
7
  let INTERACTION_TO_NEXT_PAINT: string;
8
8
  let TIME_TO_FIRST_BYTE: string;
9
9
  }
10
- export namespace PERFORMANCE_ENTRY_TYPE {
11
- let FIRST_INPUT: string;
12
- }
13
10
  //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1,3 @@
1
+ export const firstInputDelay: VitalMetric;
2
+ import { VitalMetric } from './vital-metric';
3
+ //# sourceMappingURL=first-input-delay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"first-input-delay.d.ts","sourceRoot":"","sources":["../../../../src/common/vitals/first-input-delay.js"],"names":[],"mappings":"AASA,0CAA6E;4BAJjD,gBAAgB"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/generic_events/aggregate/index.js"],"names":[],"mappings":"AAmBA;IACE,2BAAiC;IACjC,2BA4LC;IA1LC,yBAA4B;IAC5B,gCAAkG;IAuC9F,4CAAuD;IAqJ7D;;;;;;;;;;;OAWG;IACH,eAHW,MAAM,YAAC,QA0CjB;IAED,qCAEC;IAED;;;MAEC;IAED,gCAEC;IAED,mCASC;CACF;8BAvR6B,4BAA4B;sCAMpB,wCAAwC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/generic_events/aggregate/index.js"],"names":[],"mappings":"AAoBA;IACE,2BAAiC;IACjC,2BA4LC;IA1LC,yBAA4B;IAC5B,gCAAkG;IAuC9F,4CAAuD;IAqJ7D;;;;;;;;;;;OAWG;IACH,eAHW,MAAM,YAAC,QA0CjB;IAED,qCAEC;IAED;;;MAEC;IAED,gCAEC;IAED,mCASC;CACF;8BAxR6B,4BAA4B;sCAMpB,wCAAwC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/logging/aggregate/index.js"],"names":[],"mappings":"AAgBA;IACE,2BAAiC;IACjC,2BAWC;IAED,+EAgDC;IAED;;YAIM,0FAA0F;;;QAkB5F,0DAA0D;;QAM7D;IAED;;MAEC;CACF;8BAzG6B,4BAA4B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/logging/aggregate/index.js"],"names":[],"mappings":"AAiBA;IACE,2BAAiC;IACjC,2BAWC;IAED,+EAgDC;IAED;;YAIM,0FAA0F;;;QAkB5F,0DAA0D;;QAM7D;IAED;;MAEC;CACF;8BA1G6B,4BAA4B"}
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../../../../src/features/session_trace/aggregate/trace/storage.js"],"names":[],"mappings":"AA6BA,+HAA+H;AAC/H;IAQE,yBAEC;IATD,kBAAa;IACb,UAAU;IACV,0BAA4B;IAC5B,wBAAmB;IACnB,2BAA4B;IAI1B,YAAoB;IAGtB,gGAAgG;IAChG,yBAcC;IAED;;;;OAIG;IACH,2BAHW,MAAM,GACJ,MAAM,CAsBlB;IAED,oEAAoE;IACpE;;;;MAgBC;IAED,mEA6BC;IAED,oDAEC;IAED,mEAuBC;IAGD,uEAcC;IAED,oDAKC;IAED,wBAwBC;IAED,uCAuBC;IAGD,gDAEC;IAID,qCAaC;IAGD,qEAGC;IAGD,mEAGC;IAID,mBAEC;IAED,aAEC;IAED;;;;;;;QAEC;IAED,cAMC;IAED,mBAEC;IAED,kBAEC;;CACF"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../../../../src/features/session_trace/aggregate/trace/storage.js"],"names":[],"mappings":"AA6BA,+HAA+H;AAC/H;IAQE,yBAEC;IATD,kBAAa;IACb,UAAU;IACV,0BAA4B;IAC5B,wBAAmB;IACnB,2BAA4B;IAI1B,YAAoB;IAGtB,gGAAgG;IAChG,yBAcC;IAED;;;;OAIG;IACH,2BAHW,MAAM,GACJ,MAAM,CAsBlB;IAED,oEAAoE;IACpE;;;;MAgBC;IAED,mEA6BC;IAED,oDAOC;IAED,mEAuBC;IAGD,uEAcC;IAED,oDAKC;IAED,wBAwBC;IAED,uCAuBC;IAGD,gDAEC;IAID,qCAaC;IAGD,qEAGC;IAGD,mEAGC;IAID,mBAEC;IAED,aAEC;IAED;;;;;;;QAEC;IAED,cAMC;IAED,mBAEC;IAED,kBAEC;;CACF"}
@@ -5,9 +5,8 @@
5
5
  export class Agent extends AgentBase {
6
6
  /**
7
7
  * @param {Object} options Options to initialize agent with
8
- * @param {string} [agentIdentifier] Optional identifier of agent
9
8
  */
10
- constructor(options: Object, agentIdentifier?: string | undefined);
9
+ constructor(options: Object);
11
10
  features: {} | undefined;
12
11
  desiredFeatures: Set<any> | undefined;
13
12
  runSoftNavOverSpa: boolean | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/agent.js"],"names":[],"mappings":"AAqBA;;;GAGG;AACH;IACE;;;OAGG;IACH,qBAHW,MAAM,wCA0BhB;IAbC,yBAAkB;IAGlB,sCAAsD;IAMtD,uCAA6G;IAM/G;;;;;MAOC;IAED,yBAsCC;CACF;0BA9FyB,cAAc"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/agent.js"],"names":[],"mappings":"AAqBA;;;GAGG;AACH;IACE;;OAEG;IACH,qBAFW,MAAM,EAyBhB;IAbC,yBAAkB;IAGlB,sCAAsD;IAMtD,uCAA6G;IAM/G;;;;;MAOC;IAED,yBAsCC;CACF;0BA7FyB,cAAc"}
@@ -1,5 +1,4 @@
1
1
  export class MicroAgentBase {
2
- constructor(agentIdentifier?: string);
3
2
  agentIdentifier: string;
4
3
  /**
5
4
  * Reports a browser PageAction event along with a name and optional attributes.
@@ -1 +1 @@
1
- {"version":3,"file":"micro-agent-base.d.ts","sourceRoot":"","sources":["../../../src/loaders/micro-agent-base.js"],"names":[],"mappings":"AAOA;IAGE,sCAEC;IAJD,wBAAe;IAkBf;;;;;OAKG;IACH,oBAHW,MAAM,wCAKhB;IAED;;;;;OAKG;IACH,6BAHW,MAAM,wCAKhB;IAED;;;;;OAKG;IACH,sBAHW,MAAM,kCAKhB;IAED;;;;;;OAMG;IACH,yBAJW,MAAM,SACN,MAAM,GAAC,MAAM,GAAC,OAAO,GAAC,IAAI,sCAKpC;IAED;;;;;OAKG;IACH,mBAHW,KAAK,GAAC,MAAM,8CAKtB;IAED;;;;OAIG;IACH,iBAFW,MAAM,GAAC,IAAI,OAIrB;IAED;;;;;;;OAOG;IACH,6BAJW,MAAM,GAAC,IAAI,OAMrB;IAED;;;;OAIG;IACH,0BAFW,CAAC,KAAK,EAAE,KAAK,GAAC,MAAM,KAAK,OAAO,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,OAI9D;IAED;;;;;OAKG;IACH,iBAHW,MAAM,MACN,MAAM,OAIhB;IAED;;;;;MAKE;IACF,aAHW,MAAM;2BACc,MAAM;gBAAU,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,MAAM,GAAC,MAAM;wBAInF;;CACF"}
1
+ {"version":3,"file":"micro-agent-base.d.ts","sourceRoot":"","sources":["../../../src/loaders/micro-agent-base.js"],"names":[],"mappings":"AAOA;IACE,wBAAe;IAkBf;;;;;OAKG;IACH,oBAHW,MAAM,wCAKhB;IAED;;;;;OAKG;IACH,6BAHW,MAAM,wCAKhB;IAED;;;;;OAKG;IACH,sBAHW,MAAM,kCAKhB;IAED;;;;;;OAMG;IACH,yBAJW,MAAM,SACN,MAAM,GAAC,MAAM,GAAC,OAAO,GAAC,IAAI,sCAKpC;IAED;;;;;OAKG;IACH,mBAHW,KAAK,GAAC,MAAM,8CAKtB;IAED;;;;OAIG;IACH,iBAFW,MAAM,GAAC,IAAI,OAIrB;IAED;;;;;;;OAOG;IACH,6BAJW,MAAM,GAAC,IAAI,OAMrB;IAED;;;;OAIG;IACH,0BAFW,CAAC,KAAK,EAAE,KAAK,GAAC,MAAM,KAAK,OAAO,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,OAI9D;IAED;;;;;OAKG;IACH,iBAHW,MAAM,MACN,MAAM,OAIhB;IAED;;;;;MAKE;IACF,aAHW,MAAM;2BACc,MAAM;gBAAU,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,MAAM,GAAC,MAAM;wBAInF;;CACF"}
@@ -6,9 +6,8 @@
6
6
  export class MicroAgent extends MicroAgentBase {
7
7
  /**
8
8
  * @param {Object} options - Specifies features and runtime configuration,
9
- * @param {string=} agentIdentifier - The optional unique ID of the agent.
10
9
  */
11
- constructor(options: Object, agentIdentifier?: string | undefined);
10
+ constructor(options: Object);
12
11
  features: {};
13
12
  /**
14
13
  * Starts a set of agent features if not running in "autoStart" mode
@@ -1 +1 @@
1
- {"version":3,"file":"micro-agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/micro-agent.js"],"names":[],"mappings":"AAsBA;;;;GAIG;AACH;IACE;;;OAGG;IACH,qBAHW,MAAM,oBACN,MAAM,YAAC,EAsDjB;IAjDC,aAAkB;IAMlB;;;;OAIG;IACH,iEAmCC;IAKH;;;;;MAOC;CACF;+BAjF8B,oBAAoB"}
1
+ {"version":3,"file":"micro-agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/micro-agent.js"],"names":[],"mappings":"AAsBA;;;;GAIG;AACH;IACE;;OAEG;IACH,qBAFW,MAAM,EAsDhB;IAjDC,aAAkB;IAMlB;;;;OAIG;IACH,iEAmCC;IAKH;;;;;MAOC;CACF;+BAhF8B,oBAAoB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newrelic/browser-agent",
3
- "version": "1.279.0",
3
+ "version": "1.280.0",
4
4
  "private": false,
5
5
  "author": "New Relic Browser Agent Team <browser-agent@newrelic.com>",
6
6
  "description": "New Relic Browser Agent",
@@ -270,7 +270,7 @@
270
270
  "wdio-lambdatest-service": "^4.0.0",
271
271
  "webpack": "^5.89.0",
272
272
  "webpack-bundle-analyzer": "^4.10.1",
273
- "webpack-cli": "^5.1.4",
273
+ "webpack-cli": "^6.0.1",
274
274
  "yargs": "^17.7.2"
275
275
  },
276
276
  "files": [
@@ -5,13 +5,9 @@
5
5
  export const VITAL_NAMES = {
6
6
  FIRST_PAINT: 'fp',
7
7
  FIRST_CONTENTFUL_PAINT: 'fcp',
8
- FIRST_INTERACTION: 'fi',
8
+ FIRST_INPUT_DELAY: 'fi',
9
9
  LARGEST_CONTENTFUL_PAINT: 'lcp',
10
10
  CUMULATIVE_LAYOUT_SHIFT: 'cls',
11
11
  INTERACTION_TO_NEXT_PAINT: 'inp',
12
12
  TIME_TO_FIRST_BYTE: 'ttfb'
13
13
  }
14
-
15
- export const PERFORMANCE_ENTRY_TYPE = {
16
- FIRST_INPUT: 'first-input'
17
- }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Copyright 2020-2025 New Relic, Inc. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { onFID } from 'web-vitals/attribution'
6
+ import { VitalMetric } from './vital-metric'
7
+ import { VITAL_NAMES } from './constants'
8
+ import { initiallyHidden, isBrowserScope } from '../constants/runtime'
9
+
10
+ export const firstInputDelay = new VitalMetric(VITAL_NAMES.FIRST_INPUT_DELAY)
11
+
12
+ if (isBrowserScope) {
13
+ onFID(({ value, attribution }) => {
14
+ if (initiallyHidden || firstInputDelay.isValid) return
15
+ const attrs = {
16
+ type: attribution.eventType,
17
+ fid: Math.round(value),
18
+ eventTarget: attribution.eventTarget,
19
+ loadState: attribution.loadState
20
+ }
21
+
22
+ // CWV will only report one (THE) first-input entry to us; fid isn't reported if there are no user interactions occurs before the *first* page hiding.
23
+ firstInputDelay.update({
24
+ value: attribution.eventTime,
25
+ attrs
26
+ })
27
+ })
28
+ }
@@ -16,6 +16,7 @@ import { UserActionsAggregator } from './user-actions/user-actions-aggregator'
16
16
  import { isIFrameWindow } from '../../../common/dom/iframe'
17
17
  import { handle } from '../../../common/event-emitter/handle'
18
18
  import { isPureObject } from '../../../common/util/type-check'
19
+ import { FEATURE_NAMES } from '../../../loaders/features/features'
19
20
 
20
21
  export class Aggregate extends AggregateBase {
21
22
  static featureName = FEATURE_NAME
@@ -121,7 +122,7 @@ export class Aggregate extends AggregateBase {
121
122
  const observer = new PerformanceObserver((list) => {
122
123
  list.getEntries().forEach(entry => {
123
124
  try {
124
- handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/' + type + '/Seen'])
125
+ handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/' + type + '/Seen'], undefined, FEATURE_NAMES.metrics, this.ee)
125
126
  const detailObj = agentRef.init.performance.capture_detail ? createDetailAttrs(entry.detail) : {}
126
127
  this.addEvent({
127
128
  ...detailObj,
@@ -181,13 +182,13 @@ export class Aggregate extends AggregateBase {
181
182
  if (this.agentRef.init.performance.resources.asset_types.length && !this.agentRef.init.performance.resources.asset_types.includes(entryObject.initiatorType)) return
182
183
  /** decide if the entryDomain is a first party domain */
183
184
  firstParty = entryDomain === globalScope?.location.hostname || agentRef.init.performance.resources.first_party_domains.includes(entryDomain)
184
- if (firstParty) handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/FirstPartyResource/Seen'])
185
- if (isNr) handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/NrResource/Seen'])
185
+ if (firstParty) handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/FirstPartyResource/Seen'], undefined, FEATURE_NAMES.metrics, this.ee)
186
+ if (isNr) handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/NrResource/Seen'], undefined, FEATURE_NAMES.metrics, this.ee)
186
187
  } catch (err) {
187
188
  // couldnt parse the URL, so firstParty will just default to false
188
189
  }
189
190
 
190
- handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/Resource/Seen'])
191
+ handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/Performance/Resource/Seen'], undefined, FEATURE_NAMES.metrics, this.ee)
191
192
  const event = {
192
193
  ...entryObject,
193
194
  eventType: 'BrowserPerformance',
@@ -278,11 +279,11 @@ export class Aggregate extends AggregateBase {
278
279
  trackSupportabilityMetrics () {
279
280
  /** track usage SMs to improve these experimental features */
280
281
  const configPerfTag = 'Config/Performance/'
281
- if (this.agentRef.init.performance.capture_marks) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'CaptureMarks/Enabled'])
282
- if (this.agentRef.init.performance.capture_measures) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'CaptureMeasures/Enabled'])
283
- if (this.agentRef.init.performance.resources.enabled) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/Enabled'])
284
- if (this.agentRef.init.performance.resources.asset_types?.length !== 0) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/AssetTypes/Changed'])
285
- if (this.agentRef.init.performance.resources.first_party_domains?.length !== 0) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/FirstPartyDomains/Changed'])
286
- if (this.agentRef.init.performance.resources.ignore_newrelic === false) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/IgnoreNewrelic/Changed'])
282
+ if (this.agentRef.init.performance.capture_marks) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'CaptureMarks/Enabled'], undefined, FEATURE_NAMES.metrics, this.ee)
283
+ if (this.agentRef.init.performance.capture_measures) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'CaptureMeasures/Enabled'], undefined, FEATURE_NAMES.metrics, this.ee)
284
+ if (this.agentRef.init.performance.resources.enabled) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/Enabled'], undefined, FEATURE_NAMES.metrics, this.ee)
285
+ if (this.agentRef.init.performance.resources.asset_types?.length !== 0) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/AssetTypes/Changed'], undefined, FEATURE_NAMES.metrics, this.ee)
286
+ if (this.agentRef.init.performance.resources.first_party_domains?.length !== 0) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/FirstPartyDomains/Changed'], undefined, FEATURE_NAMES.metrics, this.ee)
287
+ if (this.agentRef.init.performance.resources.ignore_newrelic === false) handle(SUPPORTABILITY_METRIC_CHANNEL, [configPerfTag + 'Resources/IgnoreNewrelic/Changed'], undefined, FEATURE_NAMES.metrics, this.ee)
287
288
  }
288
289
  }
@@ -13,6 +13,7 @@ import { Log } from '../shared/log'
13
13
  import { isValidLogLevel } from '../shared/utils'
14
14
  import { applyFnToProps } from '../../../common/util/traverse'
15
15
  import { MAX_PAYLOAD_SIZE } from '../../../common/constants/agent-constants'
16
+ import { FEATURE_NAMES } from '../../../loaders/features/features'
16
17
 
17
18
  export class Aggregate extends AggregateBase {
18
19
  static featureName = FEATURE_NAME
@@ -63,18 +64,18 @@ export class Aggregate extends AggregateBase {
63
64
 
64
65
  const failToHarvestMessage = 'Logging/Harvest/Failed/Seen'
65
66
  if (logBytes > MAX_PAYLOAD_SIZE) { // cannot possibly send this, even with an empty buffer
66
- handle(SUPPORTABILITY_METRIC_CHANNEL, [failToHarvestMessage, logBytes])
67
+ handle(SUPPORTABILITY_METRIC_CHANNEL, [failToHarvestMessage, logBytes], undefined, FEATURE_NAMES.metrics, this.ee)
67
68
  warn(31, log.message.slice(0, 25) + '...')
68
69
  return
69
70
  }
70
71
 
71
72
  if (this.events.wouldExceedMaxSize(logBytes)) {
72
- handle(SUPPORTABILITY_METRIC_CHANNEL, ['Logging/Harvest/Early/Seen', this.events.byteSize() + logBytes])
73
+ handle(SUPPORTABILITY_METRIC_CHANNEL, ['Logging/Harvest/Early/Seen', this.events.byteSize() + logBytes], undefined, FEATURE_NAMES.metrics, this.ee)
73
74
  this.agentRef.runtime.harvester.triggerHarvestFor(this) // force a harvest synchronously to try adding again
74
75
  }
75
76
 
76
77
  if (!this.events.add(log)) { // still failed after a harvest attempt despite not being too large would mean harvest failed with options.retry
77
- handle(SUPPORTABILITY_METRIC_CHANNEL, [failToHarvestMessage, logBytes])
78
+ handle(SUPPORTABILITY_METRIC_CHANNEL, [failToHarvestMessage, logBytes], undefined, FEATURE_NAMES.metrics, this.ee)
78
79
  warn(31, log.message.slice(0, 25) + '...')
79
80
  }
80
81
  }
@@ -11,8 +11,8 @@ import { FEATURE_NAMES } from '../../../loaders/features/features'
11
11
  import { AggregateBase } from '../../utils/aggregate-base'
12
12
  import { cumulativeLayoutShift } from '../../../common/vitals/cumulative-layout-shift'
13
13
  import { firstContentfulPaint } from '../../../common/vitals/first-contentful-paint'
14
+ import { firstInputDelay } from '../../../common/vitals/first-input-delay'
14
15
  import { firstPaint } from '../../../common/vitals/first-paint'
15
- import { firstInteraction } from '../../../common/vitals/first-interaction'
16
16
  import { interactionToNextPaint } from '../../../common/vitals/interaction-to-next-paint'
17
17
  import { largestContentfulPaint } from '../../../common/vitals/largest-contentful-paint'
18
18
  import { timeToFirstByte } from '../../../common/vitals/time-to-first-byte'
@@ -37,8 +37,8 @@ export class Aggregate extends AggregateBase {
37
37
  this.waitForFlags(([])).then(() => {
38
38
  firstPaint.subscribe(this.#handleVitalMetric)
39
39
  firstContentfulPaint.subscribe(this.#handleVitalMetric)
40
+ firstInputDelay.subscribe(this.#handleVitalMetric)
40
41
  largestContentfulPaint.subscribe(this.#handleVitalMetric)
41
- firstInteraction.subscribe(this.#handleVitalMetric)
42
42
  interactionToNextPaint.subscribe(this.#handleVitalMetric)
43
43
  timeToFirstByte.subscribe(({ attrs }) => {
44
44
  this.addTiming('load', Math.round(attrs.navigationEntry.loadEventEnd))
@@ -50,7 +50,7 @@ export class Aggregate extends AggregateBase {
50
50
  const { name, value, attrs } = cumulativeLayoutShift.current
51
51
  if (value === undefined) return
52
52
  this.addTiming(name, value * 1000, attrs)
53
- }, true) // CLS node should only reports on vis change rather than on every change
53
+ }, true, true) // CLS node should only reports on vis change rather than on every change
54
54
 
55
55
  this.drain()
56
56
  })
@@ -136,6 +136,11 @@ export class TraceStorage {
136
136
 
137
137
  processPVT (name, value, attrs) {
138
138
  this.storeTiming({ [name]: value })
139
+ if (hasFID(name, attrs)) this.storeEvent({ type: 'fid', target: 'document' }, 'document', value, value + attrs.fid)
140
+
141
+ function hasFID (name, attrs) {
142
+ return name === 'fi' && !!attrs && typeof attrs.fid === 'number'
143
+ }
139
144
  }
140
145
 
141
146
  storeTiming (timingEntry, isAbsoluteTimestamp = false) {
@@ -26,10 +26,9 @@ import { globalScope } from '../common/constants/runtime'
26
26
  export class Agent extends AgentBase {
27
27
  /**
28
28
  * @param {Object} options Options to initialize agent with
29
- * @param {string} [agentIdentifier] Optional identifier of agent
30
29
  */
31
- constructor (options, agentIdentifier) {
32
- super(agentIdentifier)
30
+ constructor (options) {
31
+ super()
33
32
 
34
33
  if (!globalScope) {
35
34
  // We could not determine the runtime environment. Short-circuite the agent here
@@ -8,8 +8,8 @@ import { generateRandomHexString } from '../common/ids/unique-id'
8
8
  export class MicroAgentBase {
9
9
  agentIdentifier
10
10
 
11
- constructor (agentIdentifier = generateRandomHexString(16)) {
12
- this.agentIdentifier = agentIdentifier
11
+ constructor () {
12
+ this.agentIdentifier = generateRandomHexString(16)
13
13
  }
14
14
 
15
15
  /**
@@ -28,10 +28,9 @@ const nonAutoFeatures = [
28
28
  export class MicroAgent extends MicroAgentBase {
29
29
  /**
30
30
  * @param {Object} options - Specifies features and runtime configuration,
31
- * @param {string=} agentIdentifier - The optional unique ID of the agent.
32
31
  */
33
- constructor (options, agentIdentifier) {
34
- super(agentIdentifier)
32
+ constructor (options) {
33
+ super()
35
34
 
36
35
  this.features = {}
37
36
  setNREUMInitializedAgent(this.agentIdentifier, this)
@@ -1,44 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.firstInteraction = void 0;
7
- var _vitalMetric = require("./vital-metric");
8
- var _constants = require("./constants");
9
- var _runtime = require("../constants/runtime");
10
- /**
11
- * Copyright 2020-2025 New Relic, Inc. All rights reserved.
12
- * SPDX-License-Identifier: Apache-2.0
13
- */
14
-
15
- // Note: First Interaction is a legacy NR timing event, not an actual CWV metric
16
- const firstInteraction = exports.firstInteraction = new _vitalMetric.VitalMetric(_constants.VITAL_NAMES.FIRST_INTERACTION);
17
- if (_runtime.isBrowserScope) {
18
- try {
19
- let observer;
20
- // preserve the original behavior where FID is not reported if the page is hidden before the first interaction
21
- if (PerformanceObserver.supportedEntryTypes.includes(_constants.PERFORMANCE_ENTRY_TYPE.FIRST_INPUT) && !_runtime.initiallyHidden) {
22
- observer = new PerformanceObserver(list => {
23
- const firstInput = list.getEntries()[0];
24
- const attrs = {
25
- type: firstInput.name,
26
- eventTarget: firstInput.target
27
- };
28
- observer.disconnect();
29
- if (!firstInteraction.isValid) {
30
- firstInteraction.update({
31
- value: firstInput.startTime,
32
- attrs
33
- });
34
- }
35
- });
36
- observer.observe({
37
- type: _constants.PERFORMANCE_ENTRY_TYPE.FIRST_INPUT,
38
- buffered: true
39
- });
40
- }
41
- } catch (e) {
42
- // Do nothing.
43
- }
44
- }
@@ -1,38 +0,0 @@
1
- /**
2
- * Copyright 2020-2025 New Relic, Inc. All rights reserved.
3
- * SPDX-License-Identifier: Apache-2.0
4
- */
5
- import { VitalMetric } from './vital-metric';
6
- import { VITAL_NAMES, PERFORMANCE_ENTRY_TYPE } from './constants';
7
- import { initiallyHidden, isBrowserScope } from '../constants/runtime';
8
-
9
- // Note: First Interaction is a legacy NR timing event, not an actual CWV metric
10
- export const firstInteraction = new VitalMetric(VITAL_NAMES.FIRST_INTERACTION);
11
- if (isBrowserScope) {
12
- try {
13
- let observer;
14
- // preserve the original behavior where FID is not reported if the page is hidden before the first interaction
15
- if (PerformanceObserver.supportedEntryTypes.includes(PERFORMANCE_ENTRY_TYPE.FIRST_INPUT) && !initiallyHidden) {
16
- observer = new PerformanceObserver(list => {
17
- const firstInput = list.getEntries()[0];
18
- const attrs = {
19
- type: firstInput.name,
20
- eventTarget: firstInput.target
21
- };
22
- observer.disconnect();
23
- if (!firstInteraction.isValid) {
24
- firstInteraction.update({
25
- value: firstInput.startTime,
26
- attrs
27
- });
28
- }
29
- });
30
- observer.observe({
31
- type: PERFORMANCE_ENTRY_TYPE.FIRST_INPUT,
32
- buffered: true
33
- });
34
- }
35
- } catch (e) {
36
- // Do nothing.
37
- }
38
- }
@@ -1,3 +0,0 @@
1
- export const firstInteraction: VitalMetric;
2
- import { VitalMetric } from './vital-metric';
3
- //# sourceMappingURL=first-interaction.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"first-interaction.d.ts","sourceRoot":"","sources":["../../../../src/common/vitals/first-interaction.js"],"names":[],"mappings":"AASA,2CAA8E;4BALlD,gBAAgB"}
@@ -1,38 +0,0 @@
1
- /**
2
- * Copyright 2020-2025 New Relic, Inc. All rights reserved.
3
- * SPDX-License-Identifier: Apache-2.0
4
- */
5
- import { VitalMetric } from './vital-metric'
6
- import { VITAL_NAMES, PERFORMANCE_ENTRY_TYPE } from './constants'
7
- import { initiallyHidden, isBrowserScope } from '../constants/runtime'
8
-
9
- // Note: First Interaction is a legacy NR timing event, not an actual CWV metric
10
- export const firstInteraction = new VitalMetric(VITAL_NAMES.FIRST_INTERACTION)
11
-
12
- if (isBrowserScope) {
13
- try {
14
- let observer
15
- // preserve the original behavior where FID is not reported if the page is hidden before the first interaction
16
- if (PerformanceObserver.supportedEntryTypes.includes(PERFORMANCE_ENTRY_TYPE.FIRST_INPUT) && !initiallyHidden) {
17
- observer = new PerformanceObserver((list) => {
18
- const firstInput = list.getEntries()[0]
19
-
20
- const attrs = {
21
- type: firstInput.name,
22
- eventTarget: firstInput.target
23
- }
24
-
25
- observer.disconnect()
26
- if (!firstInteraction.isValid) {
27
- firstInteraction.update({
28
- value: firstInput.startTime,
29
- attrs
30
- })
31
- }
32
- })
33
- observer.observe({ type: PERFORMANCE_ENTRY_TYPE.FIRST_INPUT, buffered: true })
34
- }
35
- } catch (e) {
36
- // Do nothing.
37
- }
38
- }