@newrelic/browser-agent 1.303.0 → 1.304.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 (78) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cjs/common/config/init.js +0 -1
  3. package/dist/cjs/common/constants/env.cdn.js +1 -1
  4. package/dist/cjs/common/constants/env.npm.js +1 -1
  5. package/dist/cjs/common/session/session-entity.js +1 -0
  6. package/dist/cjs/common/util/monkey-patched.js +5 -3
  7. package/dist/cjs/common/window/page-visibility.js +4 -0
  8. package/dist/cjs/common/wrap/wrap-websocket.js +262 -32
  9. package/dist/cjs/features/generic_events/aggregate/index.js +24 -8
  10. package/dist/cjs/features/generic_events/instrument/index.js +13 -3
  11. package/dist/cjs/features/jserrors/aggregate/index.js +4 -1
  12. package/dist/cjs/features/metrics/aggregate/index.js +0 -6
  13. package/dist/cjs/features/metrics/constants.js +2 -4
  14. package/dist/cjs/features/metrics/instrument/index.js +0 -11
  15. package/dist/cjs/features/page_view_timing/instrument/index.js +1 -2
  16. package/dist/cjs/features/session_replay/shared/recorder.js +2 -1
  17. package/dist/cjs/features/soft_navigations/aggregate/index.js +1 -1
  18. package/dist/cjs/features/soft_navigations/instrument/index.js +1 -0
  19. package/dist/cjs/features/spa/aggregate/index.js +1 -1
  20. package/dist/esm/common/config/init.js +0 -1
  21. package/dist/esm/common/constants/env.cdn.js +1 -1
  22. package/dist/esm/common/constants/env.npm.js +1 -1
  23. package/dist/esm/common/session/session-entity.js +1 -0
  24. package/dist/esm/common/util/monkey-patched.js +5 -3
  25. package/dist/esm/common/window/page-visibility.js +4 -1
  26. package/dist/esm/common/wrap/wrap-websocket.js +262 -31
  27. package/dist/esm/features/generic_events/aggregate/index.js +24 -8
  28. package/dist/esm/features/generic_events/instrument/index.js +13 -3
  29. package/dist/esm/features/jserrors/aggregate/index.js +4 -1
  30. package/dist/esm/features/metrics/aggregate/index.js +0 -6
  31. package/dist/esm/features/metrics/constants.js +1 -4
  32. package/dist/esm/features/metrics/instrument/index.js +1 -14
  33. package/dist/esm/features/page_view_timing/instrument/index.js +2 -3
  34. package/dist/esm/features/session_replay/shared/recorder.js +2 -1
  35. package/dist/esm/features/soft_navigations/aggregate/index.js +1 -1
  36. package/dist/esm/features/soft_navigations/instrument/index.js +1 -0
  37. package/dist/esm/features/spa/aggregate/index.js +1 -1
  38. package/dist/tsconfig.tsbuildinfo +1 -1
  39. package/dist/types/common/config/init.d.ts.map +1 -1
  40. package/dist/types/common/session/session-entity.d.ts.map +1 -1
  41. package/dist/types/common/util/monkey-patched.d.ts.map +1 -1
  42. package/dist/types/common/window/page-visibility.d.ts +1 -0
  43. package/dist/types/common/window/page-visibility.d.ts.map +1 -1
  44. package/dist/types/common/wrap/wrap-websocket.d.ts +0 -2
  45. package/dist/types/common/wrap/wrap-websocket.d.ts.map +1 -1
  46. package/dist/types/features/generic_events/aggregate/index.d.ts +0 -1
  47. package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
  48. package/dist/types/features/generic_events/instrument/index.d.ts.map +1 -1
  49. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  50. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  51. package/dist/types/features/metrics/constants.d.ts +0 -1
  52. package/dist/types/features/metrics/constants.d.ts.map +1 -1
  53. package/dist/types/features/metrics/instrument/index.d.ts.map +1 -1
  54. package/dist/types/features/page_view_timing/instrument/index.d.ts.map +1 -1
  55. package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
  56. package/dist/types/features/soft_navigations/instrument/index.d.ts.map +1 -1
  57. package/package.json +2 -2
  58. package/src/common/config/init.js +0 -1
  59. package/src/common/session/session-entity.js +1 -0
  60. package/src/common/util/monkey-patched.js +5 -3
  61. package/src/common/window/page-visibility.js +5 -1
  62. package/src/common/wrap/wrap-websocket.js +248 -30
  63. package/src/features/generic_events/aggregate/index.js +26 -8
  64. package/src/features/generic_events/instrument/index.js +13 -3
  65. package/src/features/jserrors/aggregate/index.js +4 -1
  66. package/src/features/metrics/aggregate/index.js +0 -6
  67. package/src/features/metrics/constants.js +0 -4
  68. package/src/features/metrics/instrument/index.js +0 -10
  69. package/src/features/page_view_timing/instrument/index.js +2 -3
  70. package/src/features/session_replay/shared/recorder.js +2 -1
  71. package/src/features/soft_navigations/aggregate/index.js +1 -1
  72. package/src/features/soft_navigations/instrument/index.js +1 -0
  73. package/src/features/spa/aggregate/index.js +1 -1
  74. package/dist/cjs/features/metrics/aggregate/websocket-detection.js +0 -39
  75. package/dist/esm/features/metrics/aggregate/websocket-detection.js +0 -33
  76. package/dist/types/features/metrics/aggregate/websocket-detection.d.ts +0 -12
  77. package/dist/types/features/metrics/aggregate/websocket-detection.d.ts.map +0 -1
  78. package/src/features/metrics/aggregate/websocket-detection.js +0 -35
@@ -270,7 +270,7 @@ export class Aggregate extends AggregateBase {
270
270
  }
271
271
  }
272
272
  function getActionText(elem) {
273
- const tagName = elem.tagName.toLowerCase();
273
+ const tagName = elem.tagName?.toLowerCase();
274
274
  const elementsOfInterest = ['a', 'button', 'input'];
275
275
  if (elementsOfInterest.includes(tagName)) {
276
276
  return elem.title || elem.value || elem.innerText;
@@ -57,6 +57,7 @@ export class Instrument extends InstrumentBase {
57
57
  });
58
58
  });
59
59
  const processUserInteraction = debounce(event => {
60
+ if (document.readyState === 'loading') return; // document.body is not expected to be defined yet during loading, so only "interactive" or "complete" is considered "legit" user interaction
60
61
  handle('newUIEvent', [event], undefined, this.featureName, this.ee);
61
62
  domObserver.observe(document.body, {
62
63
  attributes: true,
@@ -620,7 +620,7 @@ export class Aggregate extends AggregateBase {
620
620
  }, this.featureName, baseEE);
621
621
  baseEE.on('interaction', saveInteraction);
622
622
  function getActionText(node) {
623
- var nodeType = node.tagName.toLowerCase();
623
+ var nodeType = node.tagName?.toLowerCase();
624
624
  var goodNodeTypes = ['a', 'button', 'input'];
625
625
  var isGoodNode = goodNodeTypes.indexOf(nodeType) !== -1;
626
626
  if (isGoodNode) {
@@ -1 +1 @@
1
- {"root":["../src/index.js","../src/cdn/experimental.js","../src/cdn/lite.js","../src/cdn/pro.js","../src/cdn/spa.js","../src/common/aggregate/aggregator.js","../src/common/aggregate/event-aggregator.js","../src/common/config/configurable.js","../src/common/config/info.js","../src/common/config/init-types.js","../src/common/config/init.js","../src/common/config/loader-config.js","../src/common/config/runtime.js","../src/common/constants/agent-constants.js","../src/common/constants/env.cdn.js","../src/common/constants/env.js","../src/common/constants/env.npm.js","../src/common/constants/runtime.js","../src/common/constants/shared-channel.js","../src/common/deny-list/deny-list.js","../src/common/dispatch/global-event.js","../src/common/dom/iframe.js","../src/common/dom/query-selector.js","../src/common/dom/selector-path.js","../src/common/drain/drain.js","../src/common/event-emitter/contextual-ee.js","../src/common/event-emitter/event-context.js","../src/common/event-emitter/handle.js","../src/common/event-emitter/register-handler.js","../src/common/event-listener/event-listener-opts.js","../src/common/harvest/harvester.js","../src/common/harvest/types.js","../src/common/ids/bundle-id.js","../src/common/ids/id.js","../src/common/ids/unique-id.js","../src/common/serialize/bel-serializer.js","../src/common/session/constants.js","../src/common/session/session-entity.js","../src/common/storage/local-storage.js","../src/common/timer/interaction-timer.js","../src/common/timer/timer.js","../src/common/timing/nav-timing.js","../src/common/timing/now.js","../src/common/timing/time-keeper.js","../src/common/unload/eol.js","../src/common/url/canonicalize-url.js","../src/common/url/clean-url.js","../src/common/url/encode.js","../src/common/url/extract-url.js","../src/common/url/location.js","../src/common/url/parse-url.js","../src/common/url/protocol.js","../src/common/util/attribute-size.js","../src/common/util/console.js","../src/common/util/data-size.js","../src/common/util/event-origin.js","../src/common/util/feature-flags.js","../src/common/util/get-or-set.js","../src/common/util/invoke.js","../src/common/util/mfe.js","../src/common/util/monkey-patched.js","../src/common/util/obfuscate.js","../src/common/util/stringify.js","../src/common/util/submit-data.js","../src/common/util/text.js","../src/common/util/traverse.js","../src/common/util/type-check.js","../src/common/vitals/constants.js","../src/common/vitals/cumulative-layout-shift.js","../src/common/vitals/first-contentful-paint.js","../src/common/vitals/first-paint.js","../src/common/vitals/interaction-to-next-paint.js","../src/common/vitals/largest-contentful-paint.js","../src/common/vitals/time-to-first-byte.js","../src/common/vitals/vital-metric.js","../src/common/window/load.js","../src/common/window/nreum.js","../src/common/window/page-visibility.js","../src/common/wrap/wrap-events.js","../src/common/wrap/wrap-fetch.js","../src/common/wrap/wrap-function.js","../src/common/wrap/wrap-history.js","../src/common/wrap/wrap-jsonp.js","../src/common/wrap/wrap-logger.js","../src/common/wrap/wrap-mutation.js","../src/common/wrap/wrap-promise.js","../src/common/wrap/wrap-timer.js","../src/common/wrap/wrap-websocket.js","../src/common/wrap/wrap-xhr.js","../src/features/ajax/constants.js","../src/features/ajax/index.js","../src/features/ajax/aggregate/gql.js","../src/features/ajax/aggregate/index.js","../src/features/ajax/instrument/distributed-tracing.js","../src/features/ajax/instrument/index.js","../src/features/ajax/instrument/response-size.js","../src/features/generic_events/constants.js","../src/features/generic_events/index.js","../src/features/generic_events/aggregate/index.js","../src/features/generic_events/aggregate/user-actions/aggregated-user-action.js","../src/features/generic_events/aggregate/user-actions/user-actions-aggregator.js","../src/features/generic_events/instrument/index.js","../src/features/jserrors/constants.js","../src/features/jserrors/index.js","../src/features/jserrors/aggregate/canonical-function-name.js","../src/features/jserrors/aggregate/cause-string.js","../src/features/jserrors/aggregate/compute-stack-trace.js","../src/features/jserrors/aggregate/format-stack-trace.js","../src/features/jserrors/aggregate/index.js","../src/features/jserrors/aggregate/internal-errors.js","../src/features/jserrors/aggregate/string-hash-code.js","../src/features/jserrors/instrument/index.js","../src/features/jserrors/shared/cast-error.js","../src/features/jserrors/shared/uncaught-error.js","../src/features/logging/constants.js","../src/features/logging/index.js","../src/features/logging/aggregate/index.js","../src/features/logging/instrument/index.js","../src/features/logging/shared/log.js","../src/features/logging/shared/utils.js","../src/features/metrics/constants.js","../src/features/metrics/index.js","../src/features/metrics/aggregate/framework-detection.js","../src/features/metrics/aggregate/harvest-metadata.js","../src/features/metrics/aggregate/index.js","../src/features/metrics/aggregate/websocket-detection.js","../src/features/metrics/instrument/index.js","../src/features/page_action/constants.js","../src/features/page_action/index.js","../src/features/page_action/instrument/index.js","../src/features/page_view_event/constants.js","../src/features/page_view_event/index.js","../src/features/page_view_event/aggregate/index.js","../src/features/page_view_event/aggregate/initialized-features.js","../src/features/page_view_event/instrument/index.js","../src/features/page_view_timing/constants.js","../src/features/page_view_timing/index.js","../src/features/page_view_timing/aggregate/index.js","../src/features/page_view_timing/instrument/index.js","../src/features/session_replay/constants.js","../src/features/session_replay/index.js","../src/features/session_replay/aggregate/index.js","../src/features/session_replay/instrument/index.js","../src/features/session_replay/shared/recorder-events.js","../src/features/session_replay/shared/recorder.js","../src/features/session_replay/shared/stylesheet-evaluator.js","../src/features/session_replay/shared/utils.js","../src/features/session_trace/constants.js","../src/features/session_trace/index.js","../src/features/session_trace/aggregate/index.js","../src/features/session_trace/aggregate/trace/node.js","../src/features/session_trace/aggregate/trace/storage.js","../src/features/session_trace/aggregate/trace/utils.js","../src/features/session_trace/instrument/index.js","../src/features/soft_navigations/constants.js","../src/features/soft_navigations/index.js","../src/features/soft_navigations/aggregate/ajax-node.js","../src/features/soft_navigations/aggregate/bel-node.js","../src/features/soft_navigations/aggregate/index.js","../src/features/soft_navigations/aggregate/initial-page-load-interaction.js","../src/features/soft_navigations/aggregate/interaction.js","../src/features/soft_navigations/instrument/index.js","../src/features/spa/constants.js","../src/features/spa/index.js","../src/features/spa/aggregate/index.js","../src/features/spa/aggregate/interaction-node.js","../src/features/spa/aggregate/interaction.js","../src/features/spa/aggregate/serializer.js","../src/features/spa/instrument/index.js","../src/features/utils/agent-session.js","../src/features/utils/aggregate-base.js","../src/features/utils/event-buffer.js","../src/features/utils/feature-base.js","../src/features/utils/feature-gates.js","../src/features/utils/instrument-base.js","../src/features/utils/nr1-debugger.js","../src/interfaces/registered-entity.js","../src/loaders/agent-base.js","../src/loaders/agent.js","../src/loaders/api-base.js","../src/loaders/browser-agent.js","../src/loaders/micro-agent-base.js","../src/loaders/micro-agent.js","../src/loaders/api/addPageAction.js","../src/loaders/api/addRelease.js","../src/loaders/api/addToTrace.js","../src/loaders/api/consent.js","../src/loaders/api/constants.js","../src/loaders/api/finished.js","../src/loaders/api/interaction-types.js","../src/loaders/api/interaction.js","../src/loaders/api/log.js","../src/loaders/api/measure.js","../src/loaders/api/noticeError.js","../src/loaders/api/pauseReplay.js","../src/loaders/api/recordCustomEvent.js","../src/loaders/api/recordReplay.js","../src/loaders/api/register-api-types.js","../src/loaders/api/register.js","../src/loaders/api/setApplicationVersion.js","../src/loaders/api/setCustomAttribute.js","../src/loaders/api/setErrorHandler.js","../src/loaders/api/setPageViewName.js","../src/loaders/api/setUserId.js","../src/loaders/api/sharedHandlers.js","../src/loaders/api/start.js","../src/loaders/api/topLevelCallers.js","../src/loaders/api/wrapLogger.js","../src/loaders/configure/configure.js","../src/loaders/configure/nonce.js","../src/loaders/configure/public-path.js","../src/loaders/features/enabled-features.js","../src/loaders/features/featureDependencies.js","../src/loaders/features/features.js"],"version":"5.9.3"}
1
+ {"root":["../src/index.js","../src/cdn/experimental.js","../src/cdn/lite.js","../src/cdn/pro.js","../src/cdn/spa.js","../src/common/aggregate/aggregator.js","../src/common/aggregate/event-aggregator.js","../src/common/config/configurable.js","../src/common/config/info.js","../src/common/config/init-types.js","../src/common/config/init.js","../src/common/config/loader-config.js","../src/common/config/runtime.js","../src/common/constants/agent-constants.js","../src/common/constants/env.cdn.js","../src/common/constants/env.js","../src/common/constants/env.npm.js","../src/common/constants/runtime.js","../src/common/constants/shared-channel.js","../src/common/deny-list/deny-list.js","../src/common/dispatch/global-event.js","../src/common/dom/iframe.js","../src/common/dom/query-selector.js","../src/common/dom/selector-path.js","../src/common/drain/drain.js","../src/common/event-emitter/contextual-ee.js","../src/common/event-emitter/event-context.js","../src/common/event-emitter/handle.js","../src/common/event-emitter/register-handler.js","../src/common/event-listener/event-listener-opts.js","../src/common/harvest/harvester.js","../src/common/harvest/types.js","../src/common/ids/bundle-id.js","../src/common/ids/id.js","../src/common/ids/unique-id.js","../src/common/serialize/bel-serializer.js","../src/common/session/constants.js","../src/common/session/session-entity.js","../src/common/storage/local-storage.js","../src/common/timer/interaction-timer.js","../src/common/timer/timer.js","../src/common/timing/nav-timing.js","../src/common/timing/now.js","../src/common/timing/time-keeper.js","../src/common/unload/eol.js","../src/common/url/canonicalize-url.js","../src/common/url/clean-url.js","../src/common/url/encode.js","../src/common/url/extract-url.js","../src/common/url/location.js","../src/common/url/parse-url.js","../src/common/url/protocol.js","../src/common/util/attribute-size.js","../src/common/util/console.js","../src/common/util/data-size.js","../src/common/util/event-origin.js","../src/common/util/feature-flags.js","../src/common/util/get-or-set.js","../src/common/util/invoke.js","../src/common/util/mfe.js","../src/common/util/monkey-patched.js","../src/common/util/obfuscate.js","../src/common/util/stringify.js","../src/common/util/submit-data.js","../src/common/util/text.js","../src/common/util/traverse.js","../src/common/util/type-check.js","../src/common/vitals/constants.js","../src/common/vitals/cumulative-layout-shift.js","../src/common/vitals/first-contentful-paint.js","../src/common/vitals/first-paint.js","../src/common/vitals/interaction-to-next-paint.js","../src/common/vitals/largest-contentful-paint.js","../src/common/vitals/time-to-first-byte.js","../src/common/vitals/vital-metric.js","../src/common/window/load.js","../src/common/window/nreum.js","../src/common/window/page-visibility.js","../src/common/wrap/wrap-events.js","../src/common/wrap/wrap-fetch.js","../src/common/wrap/wrap-function.js","../src/common/wrap/wrap-history.js","../src/common/wrap/wrap-jsonp.js","../src/common/wrap/wrap-logger.js","../src/common/wrap/wrap-mutation.js","../src/common/wrap/wrap-promise.js","../src/common/wrap/wrap-timer.js","../src/common/wrap/wrap-websocket.js","../src/common/wrap/wrap-xhr.js","../src/features/ajax/constants.js","../src/features/ajax/index.js","../src/features/ajax/aggregate/gql.js","../src/features/ajax/aggregate/index.js","../src/features/ajax/instrument/distributed-tracing.js","../src/features/ajax/instrument/index.js","../src/features/ajax/instrument/response-size.js","../src/features/generic_events/constants.js","../src/features/generic_events/index.js","../src/features/generic_events/aggregate/index.js","../src/features/generic_events/aggregate/user-actions/aggregated-user-action.js","../src/features/generic_events/aggregate/user-actions/user-actions-aggregator.js","../src/features/generic_events/instrument/index.js","../src/features/jserrors/constants.js","../src/features/jserrors/index.js","../src/features/jserrors/aggregate/canonical-function-name.js","../src/features/jserrors/aggregate/cause-string.js","../src/features/jserrors/aggregate/compute-stack-trace.js","../src/features/jserrors/aggregate/format-stack-trace.js","../src/features/jserrors/aggregate/index.js","../src/features/jserrors/aggregate/internal-errors.js","../src/features/jserrors/aggregate/string-hash-code.js","../src/features/jserrors/instrument/index.js","../src/features/jserrors/shared/cast-error.js","../src/features/jserrors/shared/uncaught-error.js","../src/features/logging/constants.js","../src/features/logging/index.js","../src/features/logging/aggregate/index.js","../src/features/logging/instrument/index.js","../src/features/logging/shared/log.js","../src/features/logging/shared/utils.js","../src/features/metrics/constants.js","../src/features/metrics/index.js","../src/features/metrics/aggregate/framework-detection.js","../src/features/metrics/aggregate/harvest-metadata.js","../src/features/metrics/aggregate/index.js","../src/features/metrics/instrument/index.js","../src/features/page_action/constants.js","../src/features/page_action/index.js","../src/features/page_action/instrument/index.js","../src/features/page_view_event/constants.js","../src/features/page_view_event/index.js","../src/features/page_view_event/aggregate/index.js","../src/features/page_view_event/aggregate/initialized-features.js","../src/features/page_view_event/instrument/index.js","../src/features/page_view_timing/constants.js","../src/features/page_view_timing/index.js","../src/features/page_view_timing/aggregate/index.js","../src/features/page_view_timing/instrument/index.js","../src/features/session_replay/constants.js","../src/features/session_replay/index.js","../src/features/session_replay/aggregate/index.js","../src/features/session_replay/instrument/index.js","../src/features/session_replay/shared/recorder-events.js","../src/features/session_replay/shared/recorder.js","../src/features/session_replay/shared/stylesheet-evaluator.js","../src/features/session_replay/shared/utils.js","../src/features/session_trace/constants.js","../src/features/session_trace/index.js","../src/features/session_trace/aggregate/index.js","../src/features/session_trace/aggregate/trace/node.js","../src/features/session_trace/aggregate/trace/storage.js","../src/features/session_trace/aggregate/trace/utils.js","../src/features/session_trace/instrument/index.js","../src/features/soft_navigations/constants.js","../src/features/soft_navigations/index.js","../src/features/soft_navigations/aggregate/ajax-node.js","../src/features/soft_navigations/aggregate/bel-node.js","../src/features/soft_navigations/aggregate/index.js","../src/features/soft_navigations/aggregate/initial-page-load-interaction.js","../src/features/soft_navigations/aggregate/interaction.js","../src/features/soft_navigations/instrument/index.js","../src/features/spa/constants.js","../src/features/spa/index.js","../src/features/spa/aggregate/index.js","../src/features/spa/aggregate/interaction-node.js","../src/features/spa/aggregate/interaction.js","../src/features/spa/aggregate/serializer.js","../src/features/spa/instrument/index.js","../src/features/utils/agent-session.js","../src/features/utils/aggregate-base.js","../src/features/utils/event-buffer.js","../src/features/utils/feature-base.js","../src/features/utils/feature-gates.js","../src/features/utils/instrument-base.js","../src/features/utils/nr1-debugger.js","../src/interfaces/registered-entity.js","../src/loaders/agent-base.js","../src/loaders/agent.js","../src/loaders/api-base.js","../src/loaders/browser-agent.js","../src/loaders/micro-agent-base.js","../src/loaders/micro-agent.js","../src/loaders/api/addPageAction.js","../src/loaders/api/addRelease.js","../src/loaders/api/addToTrace.js","../src/loaders/api/consent.js","../src/loaders/api/constants.js","../src/loaders/api/finished.js","../src/loaders/api/interaction-types.js","../src/loaders/api/interaction.js","../src/loaders/api/log.js","../src/loaders/api/measure.js","../src/loaders/api/noticeError.js","../src/loaders/api/pauseReplay.js","../src/loaders/api/recordCustomEvent.js","../src/loaders/api/recordReplay.js","../src/loaders/api/register-api-types.js","../src/loaders/api/register.js","../src/loaders/api/setApplicationVersion.js","../src/loaders/api/setCustomAttribute.js","../src/loaders/api/setErrorHandler.js","../src/loaders/api/setPageViewName.js","../src/loaders/api/setUserId.js","../src/loaders/api/sharedHandlers.js","../src/loaders/api/start.js","../src/loaders/api/topLevelCallers.js","../src/loaders/api/wrapLogger.js","../src/loaders/configure/configure.js","../src/loaders/configure/nonce.js","../src/loaders/configure/public-path.js","../src/loaders/features/enabled-features.js","../src/loaders/features/featureDependencies.js","../src/loaders/features/features.js"],"version":"5.9.3"}
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../src/common/config/init.js"],"names":[],"mappings":"AA+IO,0CAEN;mBAtIY,OAAO,cAAc,EAAE,IAAI"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../src/common/config/init.js"],"names":[],"mappings":"AA8IO,0CAEN;mBArIY,OAAO,cAAc,EAAE,IAAI"}
@@ -1 +1 @@
1
- {"version":3,"file":"session-entity.d.ts","sourceRoot":"","sources":["../../../../src/common/session/session-entity.js"],"names":[],"mappings":"AAsCA;IACE;;;;;OAKG;IACH,uBA+BC;IAzBC,qBAAsC;IACtC,aAAsB;IACtB,UAAe;IAGf,SAAc;IAEd,QAAiC;IAoBnC;;;;;aAgFC;IApEC,8BAA0B;IAC1B,+BAA4B;IAe1B,gCAOqC;IAUrC,4CAkBsC;IAexC,iCAAuB;IAKzB,wBAEC;IAED,sBAEC;IAED;;;OAGG;IACH,QAFa,MAAM,CA6BlB;IAED;;;;;;OAMG;IACH,YAHW,MAAM,GACJ,MAAM,CAkBlB;IAED,gBA2BC;IAED;;OAEG;IACH,gBAIC;IAED;;;OAGG;IACH,qBAHW,MAAM,GACJ,OAAO,CAInB;IAED;;;OAGG;IACH,gBAHW,MAAM,GACJ,OAAO,CAKnB;IAED,yDAUC;IAED,6DAIC;IAED;;;OAGG;IACH,6BAHW,MAAM,GACJ,MAAM,CAIlB;IAED,gDAaC;IAHG,YAAuD;CAI5D;sBA1TqB,gBAAgB;iCAGL,4BAA4B"}
1
+ {"version":3,"file":"session-entity.d.ts","sourceRoot":"","sources":["../../../../src/common/session/session-entity.js"],"names":[],"mappings":"AAsCA;IACE;;;;;OAKG;IACH,uBA+BC;IAzBC,qBAAsC;IACtC,aAAsB;IACtB,UAAe;IAGf,SAAc;IAEd,QAAiC;IAoBnC;;;;;aAgFC;IApEC,8BAA0B;IAC1B,+BAA4B;IAe1B,gCAOqC;IAUrC,4CAkBsC;IAexC,iCAAuB;IAKzB,wBAEC;IAED,sBAEC;IAED;;;OAGG;IACH,QAFa,MAAM,CA6BlB;IAED;;;;;;OAMG;IACH,YAHW,MAAM,GACJ,MAAM,CAkBlB;IAED,gBA4BC;IAED;;OAEG;IACH,gBAIC;IAED;;;OAGG;IACH,qBAHW,MAAM,GACJ,OAAO,CAInB;IAED;;;OAGG;IACH,gBAHW,MAAM,GACJ,OAAO,CAKnB;IAED,yDAUC;IAED,6DAIC;IAED;;;OAGG;IACH,6BAHW,MAAM,GACJ,MAAM,CAIlB;IAED,gDAaC;IAHG,YAAuD;CAI5D;sBA3TqB,gBAAgB;iCAGL,4BAA4B"}
@@ -1 +1 @@
1
- {"version":3,"file":"monkey-patched.d.ts","sourceRoot":"","sources":["../../../../src/common/util/monkey-patched.js"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,iCAHW,UAAW,GACT,OAAO,CAYnB"}
1
+ {"version":3,"file":"monkey-patched.d.ts","sourceRoot":"","sources":["../../../../src/common/util/monkey-patched.js"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,iCAHW,UAAW,GACT,OAAO,CAcnB"}
@@ -4,4 +4,5 @@
4
4
  * @returns void
5
5
  */
6
6
  export function subscribeToVisibilityChange(cb: Function, toHiddenOnly?: boolean, capture: any, abortSignal: any): void;
7
+ export function subscribeToPageUnload(cb: any, capture: any, abortSignal: any): void;
7
8
  //# sourceMappingURL=page-visibility.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"page-visibility.d.ts","sourceRoot":"","sources":["../../../../src/common/window/page-visibility.js"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,yEAHW,OAAO,wCAajB"}
1
+ {"version":3,"file":"page-visibility.d.ts","sourceRoot":"","sources":["../../../../src/common/window/page-visibility.js"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,yEAHW,OAAO,wCAajB;AAED,qFAEC"}
@@ -1,4 +1,2 @@
1
1
  export function wrapWebSocket(sharedEE: any): any;
2
- export const WEBSOCKET_TAG: "websocket-";
3
- export const ADD_EVENT_LISTENER_TAG: "addEventListener";
4
2
  //# sourceMappingURL=wrap-websocket.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"wrap-websocket.d.ts","sourceRoot":"","sources":["../../../../src/common/wrap/wrap-websocket.js"],"names":[],"mappings":"AAeA,kDA6CC;AAlDD,4BAA6B,YAAY,CAAA;AACzC,qCAAsC,kBAAkB,CAAA"}
1
+ {"version":3,"file":"wrap-websocket.d.ts","sourceRoot":"","sources":["../../../../src/common/wrap/wrap-websocket.js"],"names":[],"mappings":"AAaA,kDA2IC"}
@@ -21,7 +21,6 @@ export class Aggregate extends AggregateBase {
21
21
  ua: any;
22
22
  at: any;
23
23
  };
24
- toEpoch(timestamp: any): number;
25
24
  #private;
26
25
  }
27
26
  import { AggregateBase } from '../../utils/aggregate-base';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/generic_events/aggregate/index.js"],"names":[],"mappings":"AAkBA;IACE,2BAAiC;IAGjC,2BAgOC;IA9NC,gCAAkG;IAiOpG;;;;;;;;;;;;OAYG;IACH,eAJW,MAAM,YAAC,WACP,MAAM,YAAC,QAmCjB;IAED,qCAEC;IAED;;;MAEC;IAED,gCAEC;;CAkBF;8BA5T6B,4BAA4B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/generic_events/aggregate/index.js"],"names":[],"mappings":"AAkBA;IACE,2BAAiC;IAGjC,2BAkPC;IAhPC,gCAAkG;IAmPpG;;;;;;;;;;;;OAYG;IACH,eAJW,MAAM,YAAC,WACP,MAAM,YAAC,QAmCjB;IAED,qCAEC;IAED;;;MAEC;;CAsBF;8BA9U6B,4BAA4B"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/generic_events/instrument/index.js"],"names":[],"mappings":"AAuBA;IACE,2BAAiC;IACjC,2BAgGC;IAXG,2CAA0C;IAG5C,yBAGC;CAMJ;AAED,8CAAuC;+BA9GR,6BAA6B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/generic_events/instrument/index.js"],"names":[],"mappings":"AAwBA;IACE,2BAAiC;IACjC,2BAyGC;IAXG,2CAA0C;IAG5C,yBAGC;CAMJ;AAED,8CAAuC;+BAxHR,6BAA6B"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/jserrors/aggregate/index.js"],"names":[],"mappings":"AAwBA;;GAEG;AAEH;IACE,2BAAiC;IACjC,2BA4BC;IAvBC,kBAAuB;IACvB,eAAoB;IACpB,qBAA0B;IAC1B,2BAAgC;IAChC,qBAAwB;IAqB1B,oDAEC;IAED;;;MAcC;IAED;;;;;;OAMG;IACH,qCAHW,SAAS,GACP,MAAM,CAgBlB;IAED;;;;;;;;;;OAUG;IACH,gBATW,KAAK,GAAC,aAAa,QACnB,MAAM,aACN,OAAO,YAAC,qBACR,MAAM,YAAC,cACP,OAAO,YAAC,kBACR,MAAM,YAAC,WACP,MAAM,YAAC,QA8GjB;IA+BD;;;;;MAKE;IACF,sCAHU,MAAM,GACJ,OAAO,CAIlB;IAGD,yDA6BC;IAED,8GAWC;;CACF;wBAzRY,OAAO,0BAA0B,EAAE,SAAS;8BAR3B,4BAA4B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/jserrors/aggregate/index.js"],"names":[],"mappings":"AAwBA;;GAEG;AAEH;IACE,2BAAiC;IACjC,2BA4BC;IAvBC,kBAAuB;IACvB,eAAoB;IACpB,qBAA0B;IAC1B,2BAAgC;IAChC,qBAAwB;IAqB1B,oDAEC;IAED;;;MAcC;IAED;;;;;;OAMG;IACH,qCAHW,SAAS,GACP,MAAM,CAgBlB;IAED;;;;;;;;;;OAUG;IACH,gBATW,KAAK,GAAC,aAAa,QACnB,MAAM,aACN,OAAO,YAAC,qBACR,MAAM,YAAC,cACP,OAAO,YAAC,kBACR,MAAM,YAAC,WACP,MAAM,YAAC,QAiHjB;IA+BD;;;;;MAKE;IACF,sCAHU,MAAM,GACJ,OAAO,CAIlB;IAGD,yDA6BC;IAED,8GAWC;;CACF;wBA5RY,OAAO,0BAA0B,EAAE,SAAS;8BAR3B,4BAA4B"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/metrics/aggregate/index.js"],"names":[],"mappings":"AAiBA;IACE,2BAAiC;IACjC,2BAgCC;IA5BC,uKAAuK;IACvK,oBAAyB;IAWzB,uCAAiE;IAkBnE,iCAAsE;IAEtE,wDAKC;IAED,iDAKC;IAED,qBAgFC;IAED,0BAOC;CACF;8BApJ6B,4BAA4B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/metrics/aggregate/index.js"],"names":[],"mappings":"AAiBA;IACE,2BAAiC;IACjC,2BAgCC;IA5BC,uKAAuK;IACvK,oBAAyB;IAWzB,uCAAiE;IAkBnE,iCAAsE;IAEtE,wDAKC;IAED,iDAKC;IAED,qBA0EC;IAED,0BAOC;CACF;8BA9I6B,4BAA4B"}
@@ -3,5 +3,4 @@ export const SUPPORTABILITY_METRIC: "sm";
3
3
  export const CUSTOM_METRIC: "cm";
4
4
  export const SUPPORTABILITY_METRIC_CHANNEL: "storeSupportabilityMetrics";
5
5
  export const CUSTOM_METRIC_CHANNEL: "storeEventMetrics";
6
- export const WATCHABLE_WEB_SOCKET_EVENTS: string[];
7
6
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/features/metrics/constants.js"],"names":[],"mappings":"AAQA,kCAAiD;AACjD,oCAAqC,IAAI,CAAA;AACzC,4BAA6B,IAAI,CAAA;AACjC,4CAA6C,4BAA4B,CAAA;AACzE,oCAAqC,mBAAmB,CAAA;AAExD,mDAA2F"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/features/metrics/constants.js"],"names":[],"mappings":"AAMA,kCAAiD;AACjD,oCAAqC,IAAI,CAAA;AACzC,4BAA6B,IAAI,CAAA;AACjC,4CAA6C,4BAA4B,CAAA;AACzE,oCAAqC,mBAAmB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/metrics/instrument/index.js"],"names":[],"mappings":"AAgBA;IACE,2BAAiC;IACjC,2BAiBC;CACF;AAED,wCAAiC;+BA/BF,6BAA6B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/metrics/instrument/index.js"],"names":[],"mappings":"AAaA;IACE,2BAAiC;IACjC,2BAUC;CACF;AAED,wCAAiC;+BArBF,6BAA6B"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/page_view_timing/instrument/index.js"],"names":[],"mappings":"AAYA;IACE,2BAAiC;IACjC,2BAWC;CACF;AAED,+CAAwC;+BArBT,6BAA6B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/page_view_timing/instrument/index.js"],"names":[],"mappings":"AAWA;IACE,2BAAiC;IACjC,2BAWC;CACF;AAED,+CAAwC;+BArBT,6BAA6B"}
@@ -1 +1 @@
1
- {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/shared/recorder.js"],"names":[],"mappings":"AAqBA;IAUE,+BAkCC;IApCD,sBAAmB;IAGjB,iDAAiD;IACjD,kBAAgC;IAEhC,QAAyB;IACzB,mBAA6C;IAC7C,cAAqC;IAErC,qBAAwB;IACxB,0FAA0F;IAC1F,eAAkE;IAElE,iHAAiH;IACjH,uBAAgD;IAChD,mFAAmF;IACnF,iCAA0D;IAC1D,uIAAuI;IACvI,yBAA4B;IAC5B,qBAAwB;IACxB,kIAAkI;IAClI,kBAAqB;IACrB,uIAAuI;IACvI,0BAAwE;IAc1E,mBAEC;IAED;;;;;;;;;MAWC;IAED,kFAAkF;IAClF,oBAGC;IAED,qDAAqD;IACrD,8CAyCC;IAED;;;;;OAKG;IACH,aAHW,GAAC,cACD,GAAC,QAiCX;IAED,yHAAyH;IACzH,yCAiCC;IAED,0HAA0H;IAC1H,yBAOC;IAED,wBAEC;IAED,gCAAgC;IAChC,uCAGC;IAED;;;SAGK;IACL,oCAGC;;CACF;+BAtO8B,mBAAmB"}
1
+ {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/shared/recorder.js"],"names":[],"mappings":"AAqBA;IAUE,+BAkCC;IApCD,sBAAmB;IAGjB,iDAAiD;IACjD,kBAAgC;IAEhC,QAAyB;IACzB,mBAA6C;IAC7C,cAAqC;IAErC,qBAAwB;IACxB,0FAA0F;IAC1F,eAAkE;IAElE,iHAAiH;IACjH,uBAAgD;IAChD,mFAAmF;IACnF,iCAA0D;IAC1D,uIAAuI;IACvI,yBAA4B;IAC5B,qBAAwB;IACxB,kIAAkI;IAClI,kBAAqB;IACrB,uIAAuI;IACvI,0BAAwE;IAc1E,mBAEC;IAED;;;;;;;;;MAWC;IAED,kFAAkF;IAClF,oBAGC;IAED,qDAAqD;IACrD,8CA0CC;IAED;;;;;OAKG;IACH,aAHW,GAAC,cACD,GAAC,QAiCX;IAED,yHAAyH;IACzH,yCAiCC;IAED,0HAA0H;IAC1H,yBAOC;IAED,wBAEC;IAED,gCAAgC;IAChC,uCAGC;IAED;;;SAGK;IACL,oCAGC;;CACF;+BAvO8B,mBAAmB"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/soft_navigations/instrument/index.js"],"names":[],"mappings":"AAsBA;IACE,2BAAiC;IACjC,2BAkDC;IAxCG,2CAA0C;CAyC/C;AAED,wCAAiC;+BAnEF,6BAA6B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/soft_navigations/instrument/index.js"],"names":[],"mappings":"AAsBA;IACE,2BAAiC;IACjC,2BAmDC;IAzCG,2CAA0C;CA0C/C;AAED,wCAAiC;+BApEF,6BAA6B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newrelic/browser-agent",
3
- "version": "1.303.0",
3
+ "version": "1.304.0",
4
4
  "private": false,
5
5
  "author": "New Relic Browser Agent Team <browser-agent@newrelic.com>",
6
6
  "description": "New Relic Browser Agent",
@@ -220,8 +220,8 @@
220
220
  "url": "https://github.com/newrelic/newrelic-browser-agent.git"
221
221
  },
222
222
  "dependencies": {
223
- "fflate": "0.8.2",
224
223
  "@newrelic/rrweb": "1.0.1",
224
+ "fflate": "0.8.2",
225
225
  "web-vitals": "4.2.4"
226
226
  },
227
227
  "devDependencies": {
@@ -102,7 +102,6 @@ const InitModelFn = () => {
102
102
  collect_fonts: false,
103
103
  inline_images: false,
104
104
  fix_stylesheets: true,
105
- // recording config settings
106
105
  mask_all_inputs: true,
107
106
  // this has a getter/setter to facilitate validation of the selectors
108
107
  get mask_text_selector () { return hiddenState.mask_selector },
@@ -231,6 +231,7 @@ export class SessionEntity {
231
231
  // * stop recording (stn and sr)...
232
232
  // * delete the session and start over
233
233
  try {
234
+ warn(66)
234
235
  if (this.initialized) {
235
236
  this.ee.emit(SESSION_EVENTS.RESET)
236
237
  this.state.numOfResets++
@@ -14,9 +14,11 @@ const checked = new Map()
14
14
  export function isNative (...fns) {
15
15
  return fns.every(fn => {
16
16
  if (checked.has(fn)) return checked.get(fn)
17
- const isNative = typeof fn === 'function' && fn.toString().includes('[native code]')
18
- if (!isNative) {
19
- warn(64, fn?.name || fn?.toString())
17
+ const fnString = typeof fn === 'function' ? fn.toString() : ''
18
+ const isNative = fnString.includes('[native code]')
19
+ const isNr = fnString.includes('nrWrapper')
20
+ if (!isNative && !isNr) {
21
+ warn(64, fn?.name || fnString)
20
22
  }
21
23
  checked.set(fn, isNative)
22
24
  return isNative
@@ -3,7 +3,7 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
 
6
- import { documentAddEventListener } from '../event-listener/event-listener-opts'
6
+ import { documentAddEventListener, windowAddEventListener } from '../event-listener/event-listener-opts'
7
7
 
8
8
  /**
9
9
  * @param {function} cb - called when a visibility change occurs with the vis state at that time
@@ -21,3 +21,7 @@ export function subscribeToVisibilityChange (cb, toHiddenOnly = false, capture,
21
21
  cb(document.visibilityState)
22
22
  }
23
23
  }
24
+
25
+ export function subscribeToPageUnload (cb, capture, abortSignal) {
26
+ windowAddEventListener('pagehide', cb, capture, abortSignal)
27
+ }
@@ -3,59 +3,277 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
  import { globalScope } from '../constants/runtime'
6
- import { now } from '../timing/now'
7
- import { checkState } from '../window/load'
8
6
  import { generateRandomHexString } from '../ids/unique-id'
7
+ import { now } from '../timing/now'
9
8
  import { gosNREUMOriginals } from '../window/nreum'
10
-
11
- export const WEBSOCKET_TAG = 'websocket-'
12
- export const ADD_EVENT_LISTENER_TAG = 'addEventListener'
9
+ import { subscribeToPageUnload } from '../window/page-visibility'
13
10
 
14
11
  const wrapped = {}
12
+ const openWebSockets = new Set() // track all instances to close out metrics on page unload
15
13
 
16
14
  export function wrapWebSocket (sharedEE) {
17
- if (wrapped[sharedEE.debugId]++) return sharedEE
18
15
  const originals = gosNREUMOriginals().o
19
16
  if (!originals.WS) return sharedEE
20
17
 
21
- function reporter (socketId) {
22
- const createdAt = now()
23
- return function (message, ...data) {
24
- const timestamp = data[0]?.timeStamp || now()
25
- const isLoaded = checkState()
26
- sharedEE.emit(WEBSOCKET_TAG + message, [timestamp, timestamp - createdAt, isLoaded, socketId, ...data])
27
- }
28
- }
18
+ const wsEE = sharedEE.get('websockets')
19
+ if (wrapped[wsEE.debugId]++) return wsEE
20
+ wrapped[wsEE.debugId] = 1 // otherwise, first feature to wrap events
21
+
22
+ // This handles page navigation scenarios where the browser closes WebSockets after pagehide fires
23
+ subscribeToPageUnload(() => {
24
+ const unloadTime = now()
25
+ openWebSockets.forEach(ws => {
26
+ ws.nrData.closedAt = unloadTime
27
+ ws.nrData.closeCode = 1001 // Going Away - standard code for page navigation
28
+ ws.nrData.closeReason = 'Page navigating away'
29
+ ws.nrData.closeWasClean = false
30
+ if (ws.nrData.openedAt) {
31
+ ws.nrData.connectedDuration = unloadTime - ws.nrData.openedAt
32
+ }
33
+
34
+ wsEE.emit('ws', [ws.nrData], ws)
35
+ })
36
+ })
29
37
 
30
38
  class WrappedWebSocket extends WebSocket {
31
39
  static name = 'WebSocket'
40
+ static toString () { // fake native WebSocket when static class is stringified
41
+ return 'function WebSocket() { [native code] }'
42
+ }
43
+
44
+ toString () { // fake [object WebSocket] when instance is stringified
45
+ return '[object WebSocket]'
46
+ }
47
+
48
+ get [Symbol.toStringTag] () { // fake [object WebSocket] when Object.prototype.toString.call is used on instance
49
+ return WrappedWebSocket.name
50
+ }
51
+
52
+ // Private method to tag send, close, and event listener errors with WebSocket ID for JSErrors feature
53
+ #tagError (error) {
54
+ ;(error.__newrelic ??= {}).socketId = this.nrData.socketId
55
+ this.nrData.hasErrors ??= true
56
+ }
32
57
 
33
58
  constructor (...args) {
34
59
  super(...args)
35
- const socketId = generateRandomHexString(6)
36
- this.report = reporter(socketId)
37
- this.report('new')
38
-
39
- const events = ['message', 'error', 'open', 'close']
40
- /** add event listeners */
41
- events.forEach(evt => {
42
- this.addEventListener(evt, function (e) {
43
- this.report(ADD_EVENT_LISTENER_TAG, { eventType: evt, event: e })
60
+ /** @type {WebSocketData} */
61
+ this.nrData = new WebSocketData(args[0], args[1])
62
+
63
+ this.addEventListener('open', () => {
64
+ this.nrData.openedAt = now()
65
+ ;['protocol', 'extensions', 'binaryType'].forEach(prop => {
66
+ this.nrData[prop] = this[prop]
44
67
  })
68
+ openWebSockets.add(this)
69
+ })
70
+
71
+ this.addEventListener('message', (event) => {
72
+ const { type, size } = getDataInfo(event.data)
73
+ this.nrData.messageOrigin ??= event.origin // the origin of messages thru WS lifetime cannot be changed, so set once is sufficient
74
+ this.nrData.messageCount = (this.nrData.messageCount ?? 0) + 1
75
+ this.nrData.messageBytes = (this.nrData.messageBytes ?? 0) + size
76
+ this.nrData.messageBytesMin = Math.min(this.nrData.messageBytesMin ?? Infinity, size)
77
+ this.nrData.messageBytesMax = Math.max(this.nrData.messageBytesMax ?? 0, size)
78
+ if (!(this.nrData.messageTypes ?? '').includes(type)) {
79
+ this.nrData.messageTypes = this.nrData.messageTypes ? `${this.nrData.messageTypes},${type}` : type
80
+ }
45
81
  })
82
+
83
+ this.addEventListener('close', (event) => {
84
+ this.nrData.closedAt = now()
85
+ this.nrData.closeCode = event.code
86
+ this.nrData.closeReason = event.reason
87
+ this.nrData.closeWasClean = event.wasClean
88
+ this.nrData.connectedDuration = this.nrData.closedAt - this.nrData.openedAt
89
+
90
+ openWebSockets.delete(this) // remove from tracking set since it's now closed
91
+ wsEE.emit('ws', [this.nrData], this)
92
+ })
93
+ }
94
+
95
+ addEventListener (type, listener, ...rest) {
96
+ const wsInstance = this
97
+ const wrappedListener = typeof listener === 'function'
98
+ ? function (...args) {
99
+ try {
100
+ return listener.apply(this, args)
101
+ } catch (error) {
102
+ wsInstance.#tagError(error)
103
+ throw error
104
+ }
105
+ }
106
+ : listener?.handleEvent
107
+ ? { // case for listener === object with handleEvent
108
+ handleEvent: function (...args) {
109
+ try {
110
+ return listener.handleEvent.apply(listener, args)
111
+ } catch (error) {
112
+ wsInstance.#tagError(error)
113
+ throw error
114
+ }
115
+ }
116
+ }
117
+ : listener // case for listener === null
118
+ return super.addEventListener(type, wrappedListener, ...rest)
46
119
  }
47
120
 
48
- send (...args) {
49
- this.report('send', ...args)
121
+ send (data) {
122
+ // Only track metrics if the connection is OPEN; data sent in CONNECTING state throws, and data sent in CLOSING/CLOSED states is silently discarded
123
+ if (this.readyState === WebSocket.OPEN) {
124
+ const { type, size } = getDataInfo(data)
125
+ this.nrData.sendCount = (this.nrData.sendCount ?? 0) + 1
126
+ this.nrData.sendBytes = (this.nrData.sendBytes ?? 0) + size
127
+ this.nrData.sendBytesMin = Math.min(this.nrData.sendBytesMin ?? Infinity, size)
128
+ this.nrData.sendBytesMax = Math.max(this.nrData.sendBytesMax ?? 0, size)
129
+ if (!(this.nrData.sendTypes ?? '').includes(type)) {
130
+ this.nrData.sendTypes = this.nrData.sendTypes ? `${this.nrData.sendTypes},${type}` : type
131
+ }
132
+ }
50
133
  try {
51
- return super.send(...args)
52
- } catch (err) {
53
- this.report('send-err', ...args)
54
- throw err
134
+ return super.send(data)
135
+ } catch (error) {
136
+ this.#tagError(error)
137
+ throw error
138
+ }
139
+ }
140
+
141
+ close (...args) {
142
+ try {
143
+ super.close(...args)
144
+ } catch (error) {
145
+ this.#tagError(error)
146
+ throw error
55
147
  }
56
148
  }
57
149
  }
58
150
 
59
151
  globalScope.WebSocket = WrappedWebSocket
60
- return sharedEE
152
+ return wsEE
153
+ }
154
+
155
+ /**
156
+ * Returns the data type and size of the WebSocket send data
157
+ * @param {*} data - The data being sent
158
+ * @returns {{ type: string, size: number }} - The type name and size in bytes
159
+ */
160
+ function getDataInfo (data) {
161
+ if (typeof data === 'string') {
162
+ return {
163
+ type: 'string',
164
+ size: new TextEncoder().encode(data).length // efficient way to calculate the # of UTF-8 bytes that WS sends (cannot use string length)
165
+ }
166
+ }
167
+ if (data instanceof ArrayBuffer) {
168
+ return { type: 'ArrayBuffer', size: data.byteLength }
169
+ }
170
+ if (data instanceof Blob) {
171
+ return { type: 'Blob', size: data.size }
172
+ }
173
+ if (data instanceof DataView) {
174
+ return { type: 'DataView', size: data.byteLength }
175
+ }
176
+ if (ArrayBuffer.isView(data)) {
177
+ return { type: 'TypedArray', size: data.byteLength }
178
+ }
179
+ return { type: 'unknown', size: 0 }
180
+ }
181
+
182
+ /**
183
+ * WebSocket instrumentation data model
184
+ */
185
+ class WebSocketData {
186
+ /**
187
+ * @param {string} requestedUrl - The URL passed to WebSocket constructor
188
+ * @param {string|string[]} [requestedProtocols] - The protocols passed to WebSocket constructor
189
+ */
190
+ constructor (requestedUrl, requestedProtocols) {
191
+ /** @type {number} Timestamp when the WebSocket was constructed (relative time); will be time corrected later when timeKeeper is available */
192
+ this.timestamp = now()
193
+
194
+ /** @type {string} Most current URL when WebSocket was created; relevant for SPA */
195
+ this.currentUrl = window.location.href
196
+
197
+ /*
198
+ * pageUrl will be set by addEvent later; unlike timestamp and currentUrl, it's not sensitive to *when* it is set.
199
+ * It should not be explicitly defined here as it will overwrite the default provided by Generic Events later.
200
+ */
201
+
202
+ /** @type {string} Unique identifier for this WebSocket connection */
203
+ this.socketId = generateRandomHexString(8)
204
+
205
+ /** @type {string} The URL requested for the WebSocket connection */
206
+ this.requestedUrl = requestedUrl
207
+
208
+ /** @type {string} Comma-separated list of requested protocols */
209
+ this.requestedProtocols = Array.isArray(requestedProtocols) ? requestedProtocols.join(',') : (requestedProtocols || '')
210
+
211
+ // Properties set when connection opens
212
+ /** @type {number} [openedAt] Timestamp when connection opened */
213
+ this.openedAt = undefined
214
+
215
+ /** @type {string} [protocol] The sub-protocol selected by the server */
216
+ this.protocol = undefined
217
+
218
+ /** @type {string} [extensions] The extensions selected by the server */
219
+ this.extensions = undefined
220
+
221
+ /** @type {string} [binaryType] The binary type ('blob' or 'arraybuffer') */
222
+ this.binaryType = undefined
223
+
224
+ // Message received metrics
225
+ /** @type {string} [messageOrigin] Origin of messages (set once) */
226
+ this.messageOrigin = undefined
227
+
228
+ /** @type {number} [messageCount] Total number of messages received */
229
+ this.messageCount = undefined
230
+
231
+ /** @type {number} [messageBytes] Total bytes received */
232
+ this.messageBytes = undefined
233
+
234
+ /** @type {number} [messageBytesMin] Minimum message size received */
235
+ this.messageBytesMin = undefined
236
+
237
+ /** @type {number} [messageBytesMax] Maximum message size received */
238
+ this.messageBytesMax = undefined
239
+
240
+ /** @type {string} [messageTypes] Comma-separated list of message types received */
241
+ this.messageTypes = undefined
242
+
243
+ // Send metrics
244
+ /** @type {number} [sendCount] Total number of messages sent */
245
+ this.sendCount = undefined
246
+
247
+ /** @type {number} [sendBytes] Total bytes sent */
248
+ this.sendBytes = undefined
249
+
250
+ /** @type {number} [sendBytesMin] Minimum message size sent */
251
+ this.sendBytesMin = undefined
252
+
253
+ /** @type {number} [sendBytesMax] Maximum message size sent */
254
+ this.sendBytesMax = undefined
255
+
256
+ /** @type {string} [sendTypes] Comma-separated list of message types sent */
257
+ this.sendTypes = undefined
258
+
259
+ // Close metrics
260
+ /** @type {number} [closedAt] Timestamp when connection closed */
261
+ this.closedAt = undefined
262
+
263
+ /** @type {number} [closeCode] WebSocket close code */
264
+ this.closeCode = undefined
265
+
266
+ /** @type {string} [closeReason] WebSocket close reason */
267
+ this.closeReason = undefined
268
+
269
+ /** @type {boolean} [closeWasClean] Whether the connection closed cleanly */
270
+ this.closeWasClean = undefined
271
+
272
+ /** @type {number} [connectedDuration] Duration of the connection in milliseconds */
273
+ this.connectedDuration = undefined
274
+
275
+ // Error tracking
276
+ /** @type {boolean} [hasErrors] Whether any errors occurred */
277
+ this.hasErrors = undefined
278
+ }
61
279
  }