Skip to content

Commit a63653e

Browse files
committed
fix: improvements to getCommonUrlForTracing
1 parent fd30d85 commit a63653e

File tree

6 files changed

+85
-36
lines changed

6 files changed

+85
-36
lines changed

src/2024/operationTracking.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { type Subscription, Observable, share } from 'rxjs'
44
import type { AnyPerformanceEntry, PerformanceEntryType } from './globalTypes'
5-
import { sanitizeUrlForTracing } from '../v2/sanitizeUrlForTracing'
5+
import { getCommonUrlForTracing } from '../v2/getCommonUrlForTracing'
66
import type {
77
Operation,
88
OperationSpanMetadata,
@@ -36,7 +36,7 @@ function extractEntryMetadata(
3636

3737
switch (entry.entryType) {
3838
case 'resource': {
39-
;({ commonUrl: commonName, query } = sanitizeUrlForTracing(entry.name))
39+
;({ commonUrl: commonName, query } = getCommonUrlForTracing(entry.name))
4040
const resourceTiming = entry as PerformanceResourceTiming
4141
extraMetadata.initiatorType = resourceTiming.initiatorType
4242
extraMetadata.transferSize = resourceTiming.transferSize

src/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export {
4040
export * from './v2/constants'
4141
export * from './v2/defaultEventProcessor'
4242
export * from './v2/element'
43+
export * from './v2/getCommonUrlForTracing'
4344
export * from './v2/hooks'
4445
export * from './v2/operation'
45-
export * from './v2/sanitizeUrlForTracing'
4646
export type * from './v2/types'

src/v2/defaultEventProcessor.ts

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { sanitizeUrlForTracing } from './sanitizeUrlForTracing'
1+
import { getCommonUrlForTracing } from './getCommonUrlForTracing'
22
import {
33
type Event,
44
type EventProcessor,
@@ -25,30 +25,33 @@ export const defaultEventProcessor: EventProcessor = (
2525
let commonName = entry.name
2626
let status: EventStatus = 'ok'
2727

28-
if (entry.entryType === 'resource') {
29-
const { commonUrl, query } = sanitizeUrlForTracing(entry.name)
28+
if (entry.entryType === 'resource' || entry.entryType === 'navigation') {
29+
const { commonUrl, query, hash } = getCommonUrlForTracing(entry.name)
3030
commonName = commonUrl
3131
metadata.resourceQuery = query
32+
metadata.resourceHash = hash
3233

33-
const resource =
34-
metadata.resource &&
35-
typeof metadata.resource === 'object' &&
36-
metadata.resource
37-
const resourceType =
38-
resource && typeof resource.type === 'string' && resource.type
39-
const statusCode =
40-
resource && typeof resource.status === 'number' && resource.status
34+
if (entry.entryType === 'resource') {
35+
const resource =
36+
metadata.resource &&
37+
typeof metadata.resource === 'object' &&
38+
metadata.resource
39+
const resourceType =
40+
resource && typeof resource.type === 'string' && resource.type
41+
const statusCode =
42+
resource && typeof resource.status === 'number' && resource.status
4143

42-
if (resourceType && resourceType !== 'xhr' && resourceType !== 'fetch') {
43-
kind = 'asset'
44-
}
45-
// eslint-disable-next-line no-magic-numbers
46-
if (statusCode && statusCode >= 400) {
47-
status = 'error'
48-
}
49-
const resourceTiming = entry as PerformanceResourceTiming
50-
if (resourceTiming.initiatorType === 'iframe') {
51-
kind = 'iframe'
44+
if (resourceType && resourceType !== 'xhr' && resourceType !== 'fetch') {
45+
kind = 'asset'
46+
}
47+
// eslint-disable-next-line no-magic-numbers
48+
if (statusCode && statusCode >= 400) {
49+
status = 'error'
50+
}
51+
const resourceTiming = entry as PerformanceResourceTiming
52+
if (resourceTiming.initiatorType === 'iframe') {
53+
kind = 'iframe'
54+
}
5255
}
5356
} else if (entry.entryType !== 'mark' && entry.entryType !== 'measure') {
5457
commonName = `${entry.entryType}${

src/v2/sanitizeUrlForTracing.ts renamed to src/v2/getCommonUrlForTracing.ts

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,39 @@
1-
export function sanitizeUrlForTracing(url: string): {
1+
const COMMON_EXTENSIONS = [
2+
'.html',
3+
'.js',
4+
'.css',
5+
'.png',
6+
'.jpg',
7+
'.jpeg',
8+
'.gif',
9+
'.svg',
10+
'.webp',
11+
'.woff',
12+
'.woff2',
13+
'.ttf',
14+
'.eot',
15+
'.otf',
16+
'.ico',
17+
]
18+
19+
export function getCommonUrlForTracing(
20+
url: string,
21+
commonExtensions = COMMON_EXTENSIONS,
22+
): {
223
commonUrl: string
324
query: Record<string, string | string[]>
25+
hash: string
426
} {
27+
let commonUrl = url
28+
let hash = ''
29+
const hashIndex = url.indexOf('#')
30+
if (hashIndex >= 0) {
31+
commonUrl = url.slice(0, hashIndex)
32+
hash = url.slice(hashIndex)
33+
}
534
// Extract query string into a separate variable
635
const queryStringIndex = url.indexOf('?')
736
const query: Record<string, string | string[]> = {}
8-
let commonUrl = url
937
if (queryStringIndex >= 0) {
1038
// Split the URL to get the query string part
1139
commonUrl = url.slice(0, queryStringIndex)
@@ -35,19 +63,35 @@ export function sanitizeUrlForTracing(url: string): {
3563
})
3664
}
3765

38-
// Remove URL scheme
39-
// const urlWithoutScheme = commonUrl.replace(/(^\w+:|^)\/\//, '');
40-
// Replace numeric parts of the ID with $ID
41-
let sanitizedUrl = commonUrl.replace(/\/\d+/g, '/$id')
42-
// replace UUIDs as well:
43-
sanitizedUrl = sanitizedUrl.replace(
66+
// if the URL ends with a common extension, replace file name with $file:
67+
const urlParts = commonUrl.split('/')
68+
const lastPart = urlParts.at(-1)!
69+
const extensionIndex = lastPart.lastIndexOf('.')
70+
const extension =
71+
extensionIndex >= 0 ? lastPart.slice(extensionIndex) : undefined
72+
if (extension && commonExtensions.includes(extension)) {
73+
urlParts[urlParts.length - 1] = '$file'
74+
commonUrl = urlParts.join('/')
75+
}
76+
77+
// replace UUIDs:
78+
commonUrl = commonUrl.replace(
4479
// eslint-disable-next-line unicorn/better-regex
4580
/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/g,
4681
'$uuid',
4782
)
83+
// replace 32-character or longer hex strings:
84+
commonUrl = commonUrl.replace(
85+
// eslint-disable-next-line unicorn/better-regex
86+
/[0-9a-f]{32,}/g,
87+
'$hex',
88+
)
89+
// Replace numeric parts of the ID with $id
90+
commonUrl = commonUrl.replace(/\d{2,}/g, '$d')
4891

4992
return {
50-
commonUrl: sanitizedUrl,
93+
commonUrl,
5194
query,
95+
hash,
5296
}
5397
}

src/v2/operation.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ export class Operation implements PerformanceEntryLike {
611611
name: this.name,
612612
startTime: this.startTime,
613613
duration: this.duration,
614-
metadata: this.metadata,
614+
metadata: { ...this.metadata },
615615
event: {
616616
commonName: this.name,
617617
kind: OPERATION_ENTRY_TYPE,
@@ -630,7 +630,7 @@ export class Operation implements PerformanceEntryLike {
630630
name: this.name,
631631
startTime: this.startTime,
632632
duration: this.durationTillInteractive,
633-
metadata: this.metadata,
633+
metadata: { ...this.metadata },
634634
event: {
635635
commonName: this.name,
636636
kind: OPERATION_INTERACTIVE_ENTRY_TYPE,

src/v2/types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,12 @@ export interface Metadata {
211211
| 'DELETE'
212212
| 'PATCH'
213213
| 'TRACE'
214-
| undefined
214+
| 'OPTIONS'
215+
| 'CONNECT'
215216
status?: number | undefined
216217
}
217218
resourceQuery?: Record<string, string | string[]>
219+
resourceHash?: string
218220

219221
// renders add this metadata:
220222
visibleState?: VisibleStates | string

0 commit comments

Comments
 (0)