-
Notifications
You must be signed in to change notification settings - Fork 190
Expand file tree
/
Copy pathurlContexts.ts
More file actions
107 lines (92 loc) · 2.84 KB
/
Copy pathurlContexts.ts
File metadata and controls
107 lines (92 loc) · 2.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import type { RelativeTime, Observable } from '@datadog/browser-core'
import {
SESSION_TIME_OUT_DELAY,
relativeNow,
createValueHistory,
HookNames,
DISCARDED,
buildUrl,
mockable,
globalObject,
} from '@datadog/browser-core'
import type { LocationChange } from '../../browser/locationChangeObservable'
import type { LifeCycle } from '../lifeCycle'
import { LifeCycleEventType } from '../lifeCycle'
import type { DefaultRumEventAttributes, Hooks } from '../hooks'
/**
* We want to attach to an event:
* - the url corresponding to its start
* - the referrer corresponding to the previous view url (or document referrer for initial view)
*/
export const URL_CONTEXT_TIME_OUT_DELAY = SESSION_TIME_OUT_DELAY
export interface UrlContext {
url: string
referrer: string
}
export interface UrlContexts {
findUrl: (startTime?: RelativeTime) => UrlContext | undefined
stop: () => void
}
export function startUrlContexts(
lifeCycle: LifeCycle,
hooks: Hooks,
locationChangeObservable: Observable<LocationChange>
) {
const urlContextHistory = createValueHistory<UrlContext>({ expireDelay: URL_CONTEXT_TIME_OUT_DELAY })
let previousViewUrl: string | undefined
lifeCycle.subscribe(LifeCycleEventType.BEFORE_VIEW_CREATED, ({ startClocks, url }) => {
const locationHref = mockable(globalObject.location).href
const viewUrl = url !== undefined ? buildUrl(url, locationHref).href : locationHref
urlContextHistory.add(
buildUrlContext({
url: viewUrl,
referrer: !previousViewUrl ? document.referrer : previousViewUrl,
}),
startClocks.relative
)
previousViewUrl = viewUrl
})
lifeCycle.subscribe(LifeCycleEventType.AFTER_VIEW_ENDED, ({ endClocks }) => {
urlContextHistory.closeActive(endClocks.relative)
})
const locationChangeSubscription = locationChangeObservable.subscribe(({ newLocation }) => {
const current = urlContextHistory.find()
if (current) {
const changeTime = relativeNow()
urlContextHistory.closeActive(changeTime)
urlContextHistory.add(
buildUrlContext({
url: newLocation.href,
referrer: current.referrer,
}),
changeTime
)
}
})
function buildUrlContext({ url, referrer }: { url: string; referrer: string }) {
return {
url,
referrer,
}
}
hooks.register(HookNames.Assemble, ({ startTime, eventType }): DefaultRumEventAttributes | DISCARDED => {
const urlContext = urlContextHistory.find(startTime)
if (!urlContext) {
return DISCARDED
}
return {
type: eventType,
view: {
url: urlContext.url,
referrer: urlContext.referrer,
},
}
})
return {
findUrl: (startTime?: RelativeTime) => urlContextHistory.find(startTime),
stop: () => {
locationChangeSubscription.unsubscribe()
urlContextHistory.stop()
},
}
}