Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ [RUMF-1262] ignore some URLs when watching the page activity #1536

Merged
merged 10 commits into from
May 20, 2022
4 changes: 4 additions & 0 deletions packages/core/src/tools/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -631,3 +631,7 @@ export function removeDuplicates<T>(array: T[]) {
array.forEach((item) => set.add(item))
return setToArray(set)
}

export function matchList(list: Array<string | RegExp>, value: string) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

return list.some((item) => item === value || (item instanceof RegExp && item.test(value)))
}
23 changes: 23 additions & 0 deletions packages/rum-core/src/domain/configuration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,29 @@ describe('validateAndBuildRumConfiguration', () => {
})
})

describe('excludedActivityUrls', () => {
it('defaults to an empty array', () => {
expect(validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!.excludedActivityUrls).toEqual([])
})

it('is set to provided value', () => {
expect(
validateAndBuildRumConfiguration({
...DEFAULT_INIT_CONFIGURATION,
excludedActivityUrls: ['foo'],
service: 'bar',
})!.excludedActivityUrls
).toEqual(['foo'])
})

it('does not validate the configuration if an incorrect value is provided', () => {
expect(
validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, excludedActivityUrls: 'foo' as any })
).toBeUndefined()
expect(displaySpy).toHaveBeenCalledOnceWith('Excluded Activity Urls should be an array')
})
})

describe('trackInteractions', () => {
it('defaults to false', () => {
expect(validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!.trackInteractions).toBeFalse()
Expand Down
8 changes: 8 additions & 0 deletions packages/rum-core/src/domain/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface RumInitConfiguration extends InitConfiguration {
applicationId: string
beforeSend?: ((event: RumEvent, context: RumEventDomainContext) => void | boolean) | undefined
premiumSampleRate?: number | undefined
excludedActivityUrls?: ReadonlyArray<string | RegExp> | undefined

// tracing options
allowedTracingOrigins?: ReadonlyArray<string | RegExp> | undefined
Expand Down Expand Up @@ -44,6 +45,7 @@ export interface RumConfiguration extends Configuration {
actionNameAttribute: string | undefined
allowedTracingOrigins: Array<string | RegExp>
tracingSampleRate: number
excludedActivityUrls: Array<string | RegExp>
applicationId: string
defaultPrivacyLevel: DefaultPrivacyLevel
premiumSampleRate: number
Expand Down Expand Up @@ -84,6 +86,11 @@ export function validateAndBuildRumConfiguration(
}
}

if (initConfiguration.excludedActivityUrls !== undefined && !Array.isArray(initConfiguration.excludedActivityUrls)) {
display.error('Excluded Activity Urls should be an array')
return
}

const baseConfiguration = validateAndBuildConfiguration(initConfiguration)
if (!baseConfiguration) {
return
Expand All @@ -99,6 +106,7 @@ export function validateAndBuildRumConfiguration(
premiumSampleRate: premiumSampleRate ?? 100,
allowedTracingOrigins: initConfiguration.allowedTracingOrigins ?? [],
tracingSampleRate: initConfiguration.tracingSampleRate ?? 100,
excludedActivityUrls: initConfiguration.excludedActivityUrls ?? [],
trackInteractions: !!initConfiguration.trackInteractions || trackFrustrations,
trackFrustrations,
trackViewsManually: !!initConfiguration.trackViewsManually,
Expand Down
7 changes: 5 additions & 2 deletions packages/rum-core/src/domain/requestCollection.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ describe('collect fetch', () => {
fetchStub(FAKE_URL).resolveWith({ status: 500, responseText: 'fetch error' })

fetchStubManager.whenAllComplete(() => {
expect(startSpy).toHaveBeenCalledWith({ requestIndex: jasmine.any(Number) as unknown as number })
expect(startSpy).toHaveBeenCalledWith({ requestIndex: jasmine.any(Number) as unknown as number, url: FAKE_URL })
done()
})
})
Expand Down Expand Up @@ -182,7 +182,10 @@ describe('collect xhr', () => {
xhr.complete(200)
},
onComplete() {
expect(startSpy).toHaveBeenCalledWith({ requestIndex: jasmine.any(Number) as unknown as number })
expect(startSpy).toHaveBeenCalledWith({
requestIndex: jasmine.any(Number) as unknown as number,
url: jasmine.stringMatching(/\/ok$/) as unknown as string,
})
done()
},
})
Expand Down
3 changes: 3 additions & 0 deletions packages/rum-core/src/domain/requestCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export interface RumXhrCompleteContext extends XhrCompleteContext, CustomContext

export interface RequestStartEvent {
requestIndex: number
url: string
}

export interface RequestCompleteEvent {
Expand Down Expand Up @@ -75,6 +76,7 @@ export function trackXhr(lifeCycle: LifeCycle, configuration: RumConfiguration,

lifeCycle.notify(LifeCycleEventType.REQUEST_STARTED, {
requestIndex: context.requestIndex,
url: context.url,
})
break
case 'complete':
Expand Down Expand Up @@ -113,6 +115,7 @@ export function trackFetch(lifeCycle: LifeCycle, configuration: RumConfiguration

lifeCycle.notify(LifeCycleEventType.REQUEST_STARTED, {
requestIndex: context.requestIndex,
url: context.url,
})
break
case 'complete':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,11 @@ export const ACTION_CONTEXT_TIME_OUT_DELAY = 5 * ONE_MINUTE // arbitrary
export function trackClickActions(
lifeCycle: LifeCycle,
domMutationObservable: Observable<void>,
{ actionNameAttribute, trackFrustrations }: RumConfiguration
configuration: RumConfiguration
) {
const history: ClickActionIdHistory = new ContextHistory(ACTION_CONTEXT_TIME_OUT_DELAY)
const stopObservable = new Observable<void>()
const { trackFrustrations } = configuration
let currentRageClickChain: RageClickChain | undefined

lifeCycle.subscribe(LifeCycleEventType.SESSION_RENEWED, () => {
Expand Down Expand Up @@ -95,7 +96,7 @@ export function trackClickActions(
return
}

const name = getActionNameFromElement(event.target, actionNameAttribute)
const name = getActionNameFromElement(event.target, configuration.actionNameAttribute)
if (!trackFrustrations && !name) {
// TODO: remove this in a future major version. To keep retrocompatibility, ignore any action
// with a blank name
Expand All @@ -117,6 +118,7 @@ export function trackClickActions(
const { stop: stopWaitPageActivityEnd } = waitPageActivityEnd(
lifeCycle,
domMutationObservable,
configuration,
(pageActivityEndEvent) => {
if (!pageActivityEndEvent.hadActivity) {
// If it has no activity, consider it as a dead click.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { noop, round, ONE_SECOND, elapsed } from '@datadog/browser-core'
import type { RumLayoutShiftTiming } from '../../../browser/performanceCollection'
import { supportPerformanceTimingEvent } from '../../../browser/performanceCollection'
import { ViewLoadingType } from '../../../rawRumEvent.types'
import type { RumConfiguration } from '../../configuration'
import type { LifeCycle } from '../../lifeCycle'
import { LifeCycleEventType } from '../../lifeCycle'
import type { EventCounts } from '../../trackEventCounts'
Expand All @@ -18,6 +19,7 @@ export interface ViewMetrics {
export function trackViewMetrics(
lifeCycle: LifeCycle,
domMutationObservable: Observable<void>,
configuration: RumConfiguration,
scheduleViewUpdate: () => void,
loadingType: ViewLoadingType,
viewStart: ClocksState
Expand All @@ -39,6 +41,7 @@ export function trackViewMetrics(
const { stop: stopLoadingTimeTracking, setLoadEvent } = trackLoadingTime(
lifeCycle,
domMutationObservable,
configuration,
loadingType,
viewStart,
(newLoadingTime) => {
Expand Down Expand Up @@ -71,6 +74,7 @@ export function trackViewMetrics(
function trackLoadingTime(
lifeCycle: LifeCycle,
domMutationObservable: Observable<void>,
configuration: RumConfiguration,
loadType: ViewLoadingType,
viewStart: ClocksState,
callback: (loadingTime: Duration) => void
Expand All @@ -85,7 +89,7 @@ function trackLoadingTime(
}
}

const { stop } = waitPageActivityEnd(lifeCycle, domMutationObservable, (event) => {
const { stop } = waitPageActivityEnd(lifeCycle, domMutationObservable, configuration, (event) => {
if (isWaitingForActivityLoadingTime) {
isWaitingForActivityLoadingTime = false
if (event.hadActivity) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import type { LifeCycle } from '../../lifeCycle'
import { LifeCycleEventType } from '../../lifeCycle'
import type { EventCounts } from '../../trackEventCounts'
import type { LocationChange } from '../../../browser/locationChangeObservable'
import type { RumConfiguration } from '../../configuration'
import type { Timings } from './trackInitialViewTimings'
import { trackInitialViewTimings } from './trackInitialViewTimings'
import { trackViewMetrics } from './trackViewMetrics'
Expand Down Expand Up @@ -68,6 +69,7 @@ export function trackViews(
location: Location,
lifeCycle: LifeCycle,
domMutationObservable: Observable<void>,
configuration: RumConfiguration,
locationChangeObservable: Observable<LocationChange>,
areViewsTrackedAutomatically: boolean,
initialViewOptions?: ViewOptions
Expand All @@ -86,6 +88,7 @@ export function trackViews(
const initialView = newView(
lifeCycle,
domMutationObservable,
configuration,
location,
ViewLoadingType.INITIAL_LOAD,
clocksOrigin(),
Expand All @@ -99,7 +102,15 @@ export function trackViews(
}

function trackViewChange(startClocks?: ClocksState, viewOptions?: ViewOptions) {
return newView(lifeCycle, domMutationObservable, location, ViewLoadingType.ROUTE_CHANGE, startClocks, viewOptions)
return newView(
lifeCycle,
domMutationObservable,
configuration,
location,
ViewLoadingType.ROUTE_CHANGE,
startClocks,
viewOptions
)
}

function startViewLifeCycle() {
Expand Down Expand Up @@ -168,6 +179,7 @@ export function trackViews(
function newView(
lifeCycle: LifeCycle,
domMutationObservable: Observable<void>,
configuration: RumConfiguration,
initialLocation: Location,
loadingType: ViewLoadingType,
startClocks: ClocksState = clocksNow(),
Expand Down Expand Up @@ -205,7 +217,7 @@ function newView(
setLoadEvent,
stop: stopViewMetricsTracking,
viewMetrics,
} = trackViewMetrics(lifeCycle, domMutationObservable, scheduleViewUpdate, loadingType, startClocks)
} = trackViewMetrics(lifeCycle, domMutationObservable, configuration, scheduleViewUpdate, loadingType, startClocks)

// Initial view update
triggerViewUpdate()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export function startViewCollection(
location,
lifeCycle,
domMutationObservable,
configuration,
locationChangeObservable,
!configuration.trackViewsManually,
initialViewOptions
Expand Down
10 changes: 2 additions & 8 deletions packages/rum-core/src/domain/tracing/tracer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getOrigin, objectEntries, shallowClone, performDraw } from '@datadog/browser-core'
import { getOrigin, matchList, objectEntries, shallowClone, performDraw } from '@datadog/browser-core'
import type { RumConfiguration } from '../configuration'
import type {
RumFetchCompleteContext,
Expand Down Expand Up @@ -98,13 +98,7 @@ function injectHeadersIfTracingAllowed(
}

function isAllowedUrl(configuration: RumConfiguration, requestUrl: string) {
const requestOrigin = getOrigin(requestUrl)
for (const allowedOrigin of configuration.allowedTracingOrigins) {
if (requestOrigin === allowedOrigin || (allowedOrigin instanceof RegExp && allowedOrigin.test(requestOrigin))) {
return true
}
}
return false
return matchList(configuration.allowedTracingOrigins, getOrigin(requestUrl))
}

export function isTracingSupported() {
Expand Down
Loading