Skip to content

Commit cfd2dc8

Browse files
🔊 Add Url Extension Telemetry (#3768)
Co-authored-by: Thomas Lebeau <[email protected]>
1 parent 12c011e commit cfd2dc8

File tree

3 files changed

+43
-16
lines changed

3 files changed

+43
-16
lines changed

‎packages/core/src/domain/allowedTrackingOrigins.ts‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { display } from '../tools/display'
22
import { matchList } from '../tools/matchOption'
33
import type { InitConfiguration } from './configuration'
4-
import { isUnsupportedExtensionEnvironment } from './extension/extensionUtils'
4+
import { extractExtensionUrlFromStack, isUnsupportedExtensionEnvironment } from './extension/extensionUtils'
55
import { addTelemetryDebug } from './telemetry'
66

77
export const WARN_DOES_NOT_HAVE_ALLOWED_TRACKING_ORIGIN =
@@ -11,13 +11,17 @@ export const ERROR_NOT_ALLOWED_TRACKING_ORIGIN = 'SDK initialized on a non-allow
1111
export function isAllowedTrackingOrigins(
1212
configuration: InitConfiguration,
1313
windowOrigin = typeof location !== 'undefined' ? location.origin : '',
14-
errorStack?: string
14+
errorStack = new Error().stack
1515
): boolean {
1616
const allowedTrackingOrigins = configuration.allowedTrackingOrigins
1717
if (!allowedTrackingOrigins) {
1818
if (isUnsupportedExtensionEnvironment(windowOrigin, errorStack)) {
1919
display.warn(WARN_DOES_NOT_HAVE_ALLOWED_TRACKING_ORIGIN)
20-
addTelemetryDebug(WARN_DOES_NOT_HAVE_ALLOWED_TRACKING_ORIGIN)
20+
21+
const extensionUrl = extractExtensionUrlFromStack(errorStack)
22+
addTelemetryDebug(WARN_DOES_NOT_HAVE_ALLOWED_TRACKING_ORIGIN, {
23+
extensionUrl: extensionUrl || 'unknown',
24+
})
2125
// TODO(next major): make `allowedTrackingOrigins` required in unsupported extension environments
2226
}
2327
return true

‎packages/core/src/domain/extension/extensionUtils.spec.ts‎

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { containsExtensionUrl, EXTENSION_PREFIXES, isUnsupportedExtensionEnvironment } from './extensionUtils'
1+
import {
2+
containsExtensionUrl,
3+
EXTENSION_PREFIXES,
4+
extractExtensionUrlFromStack,
5+
isUnsupportedExtensionEnvironment,
6+
} from './extensionUtils'
27

38
describe('containsExtensionUrl', () => {
49
it('should return true if string contains an extension URL', () => {
@@ -13,7 +18,7 @@ describe('containsExtensionUrl', () => {
1318
})
1419
})
1520

16-
describe('testIsUnsupportedExtensionEnvironment', () => {
21+
describe('isUnsupportedExtensionEnvironment', () => {
1722
it('should return true when window location is a regular URL and error stack contains extension URL', () => {
1823
expect(
1924
isUnsupportedExtensionEnvironment('https://example.com', 'Error: at chrome-extension://abcdefg/content.js:10:15')
@@ -46,19 +51,28 @@ describe('testIsUnsupportedExtensionEnvironment', () => {
4651
})
4752
})
4853

49-
it('should handle case when Error.stack is undefined', () => {
50-
const mockError = new Error()
51-
mockError.stack = undefined
52-
spyOn(window, 'Error').and.returnValue(mockError)
53-
54+
it('should handle case when stack trace is undefined', () => {
5455
expect(isUnsupportedExtensionEnvironment('https://example.com')).toBe(false)
5556
})
5657

5758
it('should handle extension stack trace', () => {
58-
const mockError = new Error()
59-
mockError.stack = 'Error: at chrome-extension://abcdefg/content.js:10:15'
60-
spyOn(window, 'Error').and.returnValue(mockError)
59+
expect(
60+
isUnsupportedExtensionEnvironment('https://example.com', 'Error: at chrome-extension://abcdefg/content.js:10:15')
61+
).toBe(true)
62+
})
63+
})
64+
65+
describe('extractExtensionUrlFromStack', () => {
66+
it('should extract extension URL from stack trace', () => {
67+
const stack = `Error
68+
at foo (<anonymous>:549:44)
69+
at bar (<anonymous>:701:91)
70+
at e.init (chrome-extension://boceobohkgenpcpogecpjlnmnfbdigda/content-script-main.js:1:1009)`
71+
expect(extractExtensionUrlFromStack(stack)).toBe('chrome-extension://boceobohkgenpcpogecpjlnmnfbdigda')
72+
})
6173

62-
expect(isUnsupportedExtensionEnvironment('https://example.com')).toBe(true)
74+
it('should return undefined when no extension URL found', () => {
75+
const stack = 'Error at https://example.com/script.js:10:15'
76+
expect(extractExtensionUrlFromStack(stack)).toBeUndefined()
6377
})
6478
})

‎packages/core/src/domain/extension/extensionUtils.ts‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,17 @@ export function containsExtensionUrl(str: string): boolean {
1111
* @param stack - The error stack to check for extension URLs
1212
* @returns true if running in an unsupported browser extension environment
1313
*/
14-
export function isUnsupportedExtensionEnvironment(windowLocation: string, stack = new Error().stack) {
14+
export function isUnsupportedExtensionEnvironment(windowLocation: string, stack: string = '') {
1515
// If we're on a regular web page but the error stack shows extension URLs,
1616
// then an extension is injecting RUM.
17-
return !containsExtensionUrl(windowLocation) && containsExtensionUrl(stack || '')
17+
return !containsExtensionUrl(windowLocation) && containsExtensionUrl(stack)
18+
}
19+
20+
export function extractExtensionUrlFromStack(stack: string = ''): string | undefined {
21+
for (const prefix of EXTENSION_PREFIXES) {
22+
const match = stack.match(new RegExp(`${prefix}[^/]+`))
23+
if (match) {
24+
return match[0]
25+
}
26+
}
1827
}

0 commit comments

Comments
 (0)