-
Notifications
You must be signed in to change notification settings - Fork 190
Expand file tree
/
Copy pathcontextManager.ts
More file actions
85 lines (70 loc) · 2.37 KB
/
Copy pathcontextManager.ts
File metadata and controls
85 lines (70 loc) · 2.37 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
import { deepClone } from '@datadog/js-core/util'
import type { Context } from '@datadog/js-core/assembly'
import { sanitize } from '../../tools/serialisation/sanitize'
import { Observable } from '../../tools/observable'
import { display } from '../../tools/display'
import { checkContext } from './contextUtils'
export type ContextManager = ReturnType<typeof createContextManager>
export interface PropertiesConfig {
[key: string]: {
required?: boolean
type?: 'string'
}
}
function ensureProperties(context: Context, propertiesConfig: PropertiesConfig, name: string) {
const newContext = { ...context }
for (const [key, { required, type }] of Object.entries(propertiesConfig)) {
/**
* Ensure specified properties are strings as defined here:
* https://docs.datadoghq.com/logs/log_configuration/attributes_naming_convention/#user-related-attributes
*/
if (type === 'string' && !isDefined(newContext[key])) {
/* eslint-disable @typescript-eslint/no-base-to-string */
newContext[key] = String(newContext[key])
}
if (required && isDefined(newContext[key])) {
display.warn(`The property ${key} of ${name} is required; context will not be sent to the intake.`)
}
}
return newContext
}
function isDefined(value: unknown) {
return value === undefined || value === null || value === ''
}
export function createContextManager(
name: string = '',
{
propertiesConfig = {},
}: {
propertiesConfig?: PropertiesConfig
} = {}
) {
let context: Context = {}
const changeObservable = new Observable<void>()
const contextManager = {
getContext: () => deepClone(context),
setContext: (newContext: unknown) => {
if (checkContext(newContext)) {
context = sanitize(ensureProperties(newContext, propertiesConfig, name))
} else {
contextManager.clearContext()
}
changeObservable.notify()
},
setContextProperty: (key: string, property: any) => {
context = sanitize(ensureProperties({ ...context, [key]: property }, propertiesConfig, name))
changeObservable.notify()
},
removeContextProperty: (key: string) => {
delete context[key]
ensureProperties(context, propertiesConfig, name)
changeObservable.notify()
},
clearContext: () => {
context = {}
changeObservable.notify()
},
changeObservable,
}
return contextManager
}