-
Notifications
You must be signed in to change notification settings - Fork 190
Expand file tree
/
Copy pathsourceCodeContext.ts
More file actions
91 lines (74 loc) · 2.32 KB
/
Copy pathsourceCodeContext.ts
File metadata and controls
91 lines (74 loc) · 2.32 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
import {
SKIPPED,
computeStackTrace,
objectEntries,
addTelemetryError,
HookNames,
addTelemetryUsage,
} from '@datadog/browser-core'
import type { Hooks, DefaultRumEventAttributes, AssembleHookParams } from '../hooks'
interface SourceCodeContext {
service: string
version?: string
}
export interface BrowserWindow {
DD_SOURCE_CODE_CONTEXT?: { [stack: string]: SourceCodeContext }
}
type StackFrameUrl = string
export function startSourceCodeContext(hooks: Hooks) {
const browserWindow = window as BrowserWindow
const contextByFile = new Map<StackFrameUrl, SourceCodeContext>()
function buildContextByFile() {
if (!browserWindow.DD_SOURCE_CODE_CONTEXT) {
return
}
addTelemetryUsage({ feature: 'source-code-context' })
objectEntries(browserWindow.DD_SOURCE_CODE_CONTEXT).forEach(([stack, context]) => {
const stackTrace = computeStackTrace({ stack })
const firstFrame = stackTrace.stack[0]
if (!firstFrame.url) {
addTelemetryError('Source code context: missing frame url', { stack })
return
}
// don't overwrite existing context
if (!contextByFile.has(firstFrame.url)) {
contextByFile.set(firstFrame.url, context)
}
})
browserWindow.DD_SOURCE_CODE_CONTEXT = {}
}
buildContextByFile()
hooks.register(HookNames.Assemble, ({ domainContext, rawRumEvent }): DefaultRumEventAttributes | SKIPPED => {
buildContextByFile()
if (contextByFile.size === 0) {
return SKIPPED
}
const url = getSourceUrl(domainContext, rawRumEvent)
const context = url && contextByFile.get(url)
if (!context) {
return SKIPPED
}
return {
type: rawRumEvent.type,
service: context.service,
version: context.version,
}
})
}
function getSourceUrl(
domainContext: AssembleHookParams['domainContext'],
rawRumEvent: AssembleHookParams['rawRumEvent']
) {
if (rawRumEvent.type === 'long_task' && rawRumEvent.long_task.entry_type === 'long-animation-frame') {
return rawRumEvent.long_task.scripts[0]?.source_url
}
let stack
if ('handlingStack' in domainContext) {
stack = domainContext.handlingStack
}
if (rawRumEvent.type === 'error' && rawRumEvent.error.stack) {
stack = rawRumEvent.error.stack
}
const stackTrace = computeStackTrace({ stack })
return stackTrace.stack[0]?.url
}