Skip to content

Commit

Permalink
fix: improvements to getCommonUrlForTracing
Browse files Browse the repository at this point in the history
  • Loading branch information
niieani committed Jun 5, 2024
1 parent fd30d85 commit a63653e
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 36 deletions.
4 changes: 2 additions & 2 deletions src/2024/operationTracking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { type Subscription, Observable, share } from 'rxjs'
import type { AnyPerformanceEntry, PerformanceEntryType } from './globalTypes'
import { sanitizeUrlForTracing } from '../v2/sanitizeUrlForTracing'
import { getCommonUrlForTracing } from '../v2/getCommonUrlForTracing'
import type {
Operation,
OperationSpanMetadata,
Expand Down Expand Up @@ -36,7 +36,7 @@ function extractEntryMetadata(

switch (entry.entryType) {
case 'resource': {
;({ commonUrl: commonName, query } = sanitizeUrlForTracing(entry.name))
;({ commonUrl: commonName, query } = getCommonUrlForTracing(entry.name))
const resourceTiming = entry as PerformanceResourceTiming
extraMetadata.initiatorType = resourceTiming.initiatorType
extraMetadata.transferSize = resourceTiming.transferSize
Expand Down
2 changes: 1 addition & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export {
export * from './v2/constants'
export * from './v2/defaultEventProcessor'
export * from './v2/element'
export * from './v2/getCommonUrlForTracing'
export * from './v2/hooks'
export * from './v2/operation'
export * from './v2/sanitizeUrlForTracing'
export type * from './v2/types'
45 changes: 24 additions & 21 deletions src/v2/defaultEventProcessor.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { sanitizeUrlForTracing } from './sanitizeUrlForTracing'
import { getCommonUrlForTracing } from './getCommonUrlForTracing'
import {
type Event,
type EventProcessor,
Expand All @@ -25,30 +25,33 @@ export const defaultEventProcessor: EventProcessor = (
let commonName = entry.name
let status: EventStatus = 'ok'

if (entry.entryType === 'resource') {
const { commonUrl, query } = sanitizeUrlForTracing(entry.name)
if (entry.entryType === 'resource' || entry.entryType === 'navigation') {
const { commonUrl, query, hash } = getCommonUrlForTracing(entry.name)
commonName = commonUrl
metadata.resourceQuery = query
metadata.resourceHash = hash

const resource =
metadata.resource &&
typeof metadata.resource === 'object' &&
metadata.resource
const resourceType =
resource && typeof resource.type === 'string' && resource.type
const statusCode =
resource && typeof resource.status === 'number' && resource.status
if (entry.entryType === 'resource') {
const resource =
metadata.resource &&
typeof metadata.resource === 'object' &&
metadata.resource
const resourceType =
resource && typeof resource.type === 'string' && resource.type
const statusCode =
resource && typeof resource.status === 'number' && resource.status

if (resourceType && resourceType !== 'xhr' && resourceType !== 'fetch') {
kind = 'asset'
}
// eslint-disable-next-line no-magic-numbers
if (statusCode && statusCode >= 400) {
status = 'error'
}
const resourceTiming = entry as PerformanceResourceTiming
if (resourceTiming.initiatorType === 'iframe') {
kind = 'iframe'
if (resourceType && resourceType !== 'xhr' && resourceType !== 'fetch') {
kind = 'asset'
}
// eslint-disable-next-line no-magic-numbers
if (statusCode && statusCode >= 400) {
status = 'error'
}
const resourceTiming = entry as PerformanceResourceTiming
if (resourceTiming.initiatorType === 'iframe') {
kind = 'iframe'
}
}
} else if (entry.entryType !== 'mark' && entry.entryType !== 'measure') {
commonName = `${entry.entryType}${
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,39 @@
export function sanitizeUrlForTracing(url: string): {
const COMMON_EXTENSIONS = [
'.html',
'.js',
'.css',
'.png',
'.jpg',
'.jpeg',
'.gif',
'.svg',
'.webp',
'.woff',
'.woff2',
'.ttf',
'.eot',
'.otf',
'.ico',
]

export function getCommonUrlForTracing(
url: string,
commonExtensions = COMMON_EXTENSIONS,
): {
commonUrl: string
query: Record<string, string | string[]>
hash: string
} {
let commonUrl = url
let hash = ''
const hashIndex = url.indexOf('#')
if (hashIndex >= 0) {
commonUrl = url.slice(0, hashIndex)
hash = url.slice(hashIndex)
}
// Extract query string into a separate variable
const queryStringIndex = url.indexOf('?')
const query: Record<string, string | string[]> = {}
let commonUrl = url
if (queryStringIndex >= 0) {
// Split the URL to get the query string part
commonUrl = url.slice(0, queryStringIndex)
Expand Down Expand Up @@ -35,19 +63,35 @@ export function sanitizeUrlForTracing(url: string): {
})
}

// Remove URL scheme
// const urlWithoutScheme = commonUrl.replace(/(^\w+:|^)\/\//, '');
// Replace numeric parts of the ID with $ID
let sanitizedUrl = commonUrl.replace(/\/\d+/g, '/$id')
// replace UUIDs as well:
sanitizedUrl = sanitizedUrl.replace(
// if the URL ends with a common extension, replace file name with $file:
const urlParts = commonUrl.split('/')
const lastPart = urlParts.at(-1)!
const extensionIndex = lastPart.lastIndexOf('.')
const extension =
extensionIndex >= 0 ? lastPart.slice(extensionIndex) : undefined
if (extension && commonExtensions.includes(extension)) {
urlParts[urlParts.length - 1] = '$file'
commonUrl = urlParts.join('/')
}

// replace UUIDs:
commonUrl = commonUrl.replace(
// eslint-disable-next-line unicorn/better-regex
/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/g,
'$uuid',
)
// replace 32-character or longer hex strings:
commonUrl = commonUrl.replace(
// eslint-disable-next-line unicorn/better-regex
/[0-9a-f]{32,}/g,
'$hex',
)
// Replace numeric parts of the ID with $id
commonUrl = commonUrl.replace(/\d{2,}/g, '$d')

return {
commonUrl: sanitizedUrl,
commonUrl,
query,
hash,
}
}
4 changes: 2 additions & 2 deletions src/v2/operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ export class Operation implements PerformanceEntryLike {
name: this.name,
startTime: this.startTime,
duration: this.duration,
metadata: this.metadata,
metadata: { ...this.metadata },
event: {
commonName: this.name,
kind: OPERATION_ENTRY_TYPE,
Expand All @@ -630,7 +630,7 @@ export class Operation implements PerformanceEntryLike {
name: this.name,
startTime: this.startTime,
duration: this.durationTillInteractive,
metadata: this.metadata,
metadata: { ...this.metadata },
event: {
commonName: this.name,
kind: OPERATION_INTERACTIVE_ENTRY_TYPE,
Expand Down
4 changes: 3 additions & 1 deletion src/v2/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,12 @@ export interface Metadata {
| 'DELETE'
| 'PATCH'
| 'TRACE'
| undefined
| 'OPTIONS'
| 'CONNECT'
status?: number | undefined
}
resourceQuery?: Record<string, string | string[]>
resourceHash?: string

// renders add this metadata:
visibleState?: VisibleStates | string
Expand Down

0 comments on commit a63653e

Please sign in to comment.