@@ -41,6 +41,14 @@ export class Instrument extends InstrumentBase {
4141 setupRegisterAPI ( agentRef )
4242 setupMeasureAPI ( agentRef )
4343
44+ const ufEnabled = agentRef . init . feature_flags . includes ( 'user_frustrations' )
45+ let historyEE
46+ if ( isBrowserScope && ufEnabled ) {
47+ wrapFetch ( this . ee )
48+ wrapXhr ( this . ee )
49+ historyEE = wrapHistory ( this . ee )
50+ }
51+
4452 if ( isBrowserScope ) {
4553 if ( agentRef . init . user_actions . enabled ) {
4654 OBSERVED_EVENTS . forEach ( eventType =>
@@ -52,7 +60,43 @@ export class Instrument extends InstrumentBase {
5260 }
5361 // Capture is not used here so that we don't get element focus/blur events, only the window's as they do not bubble. They are also not cancellable, so no worries about being front of line.
5462 )
63+
64+ if ( ufEnabled ) {
65+ globalScope . addEventListener ( 'error' , ( ) => {
66+ handle ( 'uaErr' , [ ] , undefined , FEATURE_NAMES . genericEvents , this . ee )
67+ } , eventListenerOpts ( false , this . removeOnAbort ?. signal ) )
68+
69+ this . ee . on ( 'open-xhr-start' , ( args , xhr ) => {
70+ if ( ! isInternalTraffic ( args [ 1 ] ) ) {
71+ xhr . addEventListener ( 'readystatechange' , ( ) => {
72+ if ( xhr . readyState === 2 ) { // HEADERS_RECEIVED
73+ handle ( 'uaXhr' , [ ] , undefined , FEATURE_NAMES . genericEvents , this . ee )
74+ }
75+ } )
76+ }
77+ } )
78+ this . ee . on ( 'fetch-start' , ( fetchArguments ) => {
79+ if ( fetchArguments . length >= 1 && ! isInternalTraffic ( extractUrl ( fetchArguments [ 0 ] ) ) ) {
80+ handle ( 'uaXhr' , [ ] , undefined , FEATURE_NAMES . genericEvents , this . ee )
81+ }
82+ } )
83+
84+ function isInternalTraffic ( url ) {
85+ const parsedUrl = parseUrl ( url )
86+ return agentRef . beacons . includes ( parsedUrl . hostname + ':' + parsedUrl . port )
87+ }
88+
89+ historyEE . on ( 'pushState-end' , navigationChange )
90+ historyEE . on ( 'replaceState-end' , navigationChange )
91+ window . addEventListener ( 'hashchange' , navigationChange , eventListenerOpts ( true , this . removeOnAbort ?. signal ) )
92+ window . addEventListener ( 'popstate' , navigationChange , eventListenerOpts ( true , this . removeOnAbort ?. signal ) )
93+
94+ function navigationChange ( ) {
95+ historyEE . emit ( 'navChange' )
96+ }
97+ }
5598 }
99+
56100 if ( agentRef . init . performance . resources . enabled && globalScope . PerformanceObserver ?. supportedEntryTypes . includes ( 'resource' ) ) {
57101 const observer = new PerformanceObserver ( ( list ) => {
58102 list . getEntries ( ) . forEach ( entry => {
@@ -61,15 +105,6 @@ export class Instrument extends InstrumentBase {
61105 } )
62106 observer . observe ( { type : 'resource' , buffered : true } )
63107 }
64-
65- const historyEE = wrapHistory ( this . ee )
66- historyEE . on ( 'pushState-end' , navigationChange )
67- historyEE . on ( 'replaceState-end' , navigationChange )
68- window . addEventListener ( 'hashchange' , navigationChange , eventListenerOpts ( true , this . removeOnAbort ?. signal ) )
69- window . addEventListener ( 'popstate' , navigationChange , eventListenerOpts ( true , this . removeOnAbort ?. signal ) )
70- function navigationChange ( ) {
71- historyEE . emit ( 'navChange' )
72- }
73108 }
74109
75110 try {
@@ -81,32 +116,6 @@ export class Instrument extends InstrumentBase {
81116 this . abortHandler = undefined // weakly allow this abort op to run only once
82117 }
83118
84- globalScope . addEventListener ( 'error' , ( ) => {
85- handle ( 'uaErr' , [ ] , undefined , FEATURE_NAMES . genericEvents , this . ee )
86- } , eventListenerOpts ( false , this . removeOnAbort ?. signal ) )
87-
88- wrapFetch ( this . ee )
89- wrapXhr ( this . ee )
90- this . ee . on ( 'open-xhr-start' , ( args , xhr ) => {
91- if ( ! isInternalTraffic ( args [ 1 ] ) ) {
92- xhr . addEventListener ( 'readystatechange' , ( ) => {
93- if ( xhr . readyState === 2 ) { // HEADERS_RECEIVED
94- handle ( 'uaXhr' , [ ] , undefined , FEATURE_NAMES . genericEvents , this . ee )
95- }
96- } )
97- }
98- } )
99- this . ee . on ( 'fetch-start' , ( fetchArguments ) => {
100- if ( fetchArguments . length >= 1 && ! isInternalTraffic ( extractUrl ( fetchArguments [ 0 ] ) ) ) {
101- handle ( 'uaXhr' , [ ] , undefined , FEATURE_NAMES . genericEvents , this . ee )
102- }
103- } )
104-
105- function isInternalTraffic ( url ) {
106- const parsedUrl = parseUrl ( url )
107- return agentRef . beacons . includes ( parsedUrl . hostname + ':' + parsedUrl . port )
108- }
109-
110119 /** If any of the sources are active, import the aggregator. otherwise deregister */
111120 if ( genericEventSourceConfigs . some ( x => x ) ) this . importAggregator ( agentRef , ( ) => import ( /* webpackChunkName: "generic_events-aggregate" */ '../aggregate' ) )
112121 else this . deregisterDrain ( )
0 commit comments