Skip to content

Commit 3b86cc4

Browse files
committed
refactor(browser): Extract bfcache reason capture and hoist transaction name
Compute the transaction name once per pageshow and thread it through the metric helpers instead of re-reading the scope for each metric. Extract the not-restored reason emission into its own helper and correct the pageshow event type.
1 parent 428cf3f commit 3b86cc4

1 file changed

Lines changed: 52 additions & 48 deletions

File tree

packages/browser/src/integrations/bfcache.ts

Lines changed: 52 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { WINDOW } from '../helpers';
66

77
const INTEGRATION_NAME = 'BFCacheMetrics';
88

9+
type BFCacheOutcome = 'hit' | 'miss';
10+
911
type BFCacheFrame = 'top' | 'child';
1012

1113
interface BFCacheIntegrationOptions {
@@ -51,68 +53,70 @@ export const bfcacheMetricsIntegration = defineIntegration((options: Partial<BFC
5153
return;
5254
}
5355

54-
WINDOW.addEventListener(
55-
'pageshow',
56-
event => {
57-
if (event.persisted) {
58-
_captureBFCacheNavigation('hit');
59-
return;
60-
}
61-
62-
const navigationEntry = WINDOW.performance.getEntriesByType('navigation')[0] as
63-
| NavigationTimingWithNotRestoredReasons
64-
| undefined;
65-
66-
if (navigationEntry?.type !== 'back_forward') {
67-
return;
68-
}
69-
70-
const reasons = _collectNotRestoredReasons(navigationEntry.notRestoredReasons, maxReasons);
71-
72-
_captureBFCacheNavigation('miss', reasons.length);
73-
74-
// Measures how expensive the fallback reload was when a back/forward navigation missed bfcache.
75-
if (typeof navigationEntry.duration === 'number' && navigationEntry.duration > 0) {
76-
const transactionName = _getTransactionName();
77-
78-
metrics.distribution('browser.bfcache.reload.duration', navigationEntry.duration, {
79-
unit: 'millisecond',
80-
attributes: {
81-
[SENTRY_SEGMENT_NAME]: transactionName,
82-
},
83-
});
84-
}
85-
86-
reasons.forEach(({ reason, frame }) => {
87-
const transactionName = _getTransactionName();
88-
89-
metrics.count('browser.bfcache.not_restored', 1, {
90-
attributes: {
91-
'browser.bfcache.reason': reason,
92-
'browser.bfcache.frame': frame,
93-
[SENTRY_SEGMENT_NAME]: transactionName,
94-
},
95-
});
56+
function onPageShow(event: PageTransitionEvent) {
57+
const transactionName = _getTransactionName();
58+
if (event.persisted) {
59+
_captureBFCacheNavigation('hit', undefined, transactionName);
60+
return;
61+
}
62+
63+
const navigationEntry = WINDOW.performance.getEntriesByType('navigation')[0] as
64+
| NavigationTimingWithNotRestoredReasons
65+
| undefined;
66+
67+
if (navigationEntry?.type !== 'back_forward') {
68+
return;
69+
}
70+
71+
const reasons = _collectNotRestoredReasons(navigationEntry.notRestoredReasons, maxReasons);
72+
_captureBFCacheNavigation('miss', reasons.length, transactionName);
73+
74+
// Measures how expensive the fallback reload was when a back/forward navigation missed bfcache.
75+
if (typeof navigationEntry.duration === 'number' && navigationEntry.duration > 0) {
76+
metrics.distribution('browser.bfcache.reload.duration', navigationEntry.duration, {
77+
unit: 'millisecond',
78+
attributes: {
79+
[SENTRY_SEGMENT_NAME]: transactionName,
80+
},
9681
});
97-
},
98-
true,
99-
);
82+
}
83+
84+
reasons.forEach(r => _captureBFCacheReason(r, transactionName));
85+
}
86+
87+
WINDOW.addEventListener('pageshow', onPageShow, true);
10088
},
10189
};
10290
}) satisfies IntegrationFn;
10391

104-
function _captureBFCacheNavigation(outcome: 'hit' | 'miss', reasonCount?: number): void {
105-
const transactionName = _getTransactionName();
106-
92+
/**
93+
* Captures a bf navigation as a metric and records the outcome and reason count.
94+
*/
95+
function _captureBFCacheNavigation(outcome: BFCacheOutcome, reasonCount?: number, transactionName?: string): void {
10796
metrics.count('browser.bfcache.navigation', 1, {
10897
attributes: {
98+
// TODO: use convention constants
10999
'browser.bfcache.outcome': outcome,
110100
'browser.bfcache.not_restored_reason_count': reasonCount,
111101
[SENTRY_SEGMENT_NAME]: transactionName,
112102
},
113103
});
114104
}
115105

106+
/**
107+
* Maps a collected reason to a metric and captures/sends it.
108+
*/
109+
function _captureBFCacheReason({ reason, frame }: CollectedReason, transactionName?: string) {
110+
metrics.count('browser.bfcache.not_restored', 1, {
111+
attributes: {
112+
// TODO: use convention constants
113+
'browser.bfcache.reason': reason,
114+
'browser.bfcache.frame': frame,
115+
[SENTRY_SEGMENT_NAME]: transactionName,
116+
},
117+
});
118+
}
119+
116120
function _getTransactionName(): string | undefined {
117121
return getCurrentScope().getScopeData().transactionName || WINDOW.location?.pathname;
118122
}

0 commit comments

Comments
 (0)