-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsampling.js
More file actions
137 lines (121 loc) · 5.4 KB
/
sampling.js
File metadata and controls
137 lines (121 loc) · 5.4 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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
const sampling = {
defaults: {
acceptance: {
size: 1,
averagePause: 0.2,
pauseVariance: 0.1,
errorBudget: 0,
},
monitoring: {
size: 5,
averagePause: 0.2,
pauseVariance: 0.1,
errorBudget: 4,
},
sampling: {
size: 5,
averagePause: 0.2,
pauseVariance: 0.1,
errorBudget: 4,
warningThreshold: 0.9,
},
},
defaultSampling: (modeDefaults, script) => Object.assign({
size: sampling.defaults.sampling.size,
averagePause: sampling.defaults.sampling.averagePause,
pauseVariance: sampling.defaults.sampling.pauseVariance,
errorBudget: sampling.defaults.sampling.errorBudget,
warningThreshold: sampling.defaults.sampling.warningThreshold,
}, modeDefaults, script.sampling || {}),
applySamplingToScript: (script, settings, appliedSampling) => {
const updatedScript = Object.assign({}, script, {
sampling: appliedSampling,
})
sampling.validateSampling(updatedScript, settings)
return updatedScript
},
applyAcceptanceSamplingToScript: (script, settings) => {
const acceptanceSampling = sampling.defaultSampling(sampling.defaults.acceptance, script)
return sampling.applySamplingToScript(script, settings, acceptanceSampling)
},
applyMonitoringSamplingToScript: (script, settings) => {
const monitoringSampling = sampling.defaultSampling(sampling.defaults.monitoring, script)
return sampling.applySamplingToScript(script, settings, monitoringSampling)
},
validateSampling: (script, settings) => {
// Specific type and value checking
if (typeof script.sampling.size !== 'number' || script.sampling.size <= 0) {
throw new Error('If specified, the sampling size must have type number and be greater than zero')
}
if (typeof script.sampling.averagePause !== 'number' || script.sampling.averagePause <= 0) {
throw new Error('If specified, the sampling averagePause must have type number and be greater than zero')
}
if (typeof script.sampling.pauseVariance !== 'number' || script.sampling.pauseVariance < 0) {
throw new Error('If specified, the sampling pauseVariance must have type number and be greater than or equal to zero')
}
if (typeof script.sampling.errorBudget !== 'number' || script.sampling.errorBudget < 0) {
throw new Error('If specified, the sampling errorBudget must have type number and be greater than or equal to zero')
}
if (typeof script.sampling.warningThreshold !== 'number' || script.sampling.warningThreshold <= 0 || script.sampling.warningThreshold > 1) {
throw new Error('If specified, the sampling warningThreshold must have type number and be either one or between zero and one')
}
const scenarioCount = script.scenarios ? script.scenarios.length : 1
const totalSamples = script.sampling.size * scenarioCount
// Value relationship checking
if (
totalSamples <= script.sampling.errorBudget
) {
throw new Error(`The given size * scenarios (${
totalSamples
}) and errorBudget (${
script.sampling.errorBudget
}) values (perhaps from defaults) succeeds even if all samples fail`)
}
if (
script.sampling.pauseVariance > script.sampling.averagePause
) {
throw new Error(`The given pauseVariance (${
script.sampling.pauseVariance
}) cannot exceed the given averagePause (${
script.sampling.averagePause
})`)
}
// Value to function constrain checking
const mostPossiblePause = (script.sampling.averagePause + script.sampling.pauseVariance) * totalSamples
if (mostPossiblePause > settings.maxScriptDurationInSeconds) {
throw new Error(`The given averagePause (${
script.sampling.averagePause
}), pauseVariance (${
script.sampling.pauseVariance
}), and size * scenarios (${
totalSamples
}) values in combination could, even ignoring request duration, exceed the maximum allowable duration (${
settings.maxScriptDurationInSeconds
})`)
}
if (mostPossiblePause > (settings.maxScriptDurationInSeconds * script.sampling.warningThreshold)) {
console.warn([
'## !! WARNING !! ##',
'',
'As configured (perhaps via defaults), it is possible that the total execution',
'time of your sampling will exceed the duration allowed for executing it.',
'Additionally, specifying regular continuous sampling in this configuration can',
'result in greater than expected costs',
'Values:',
`\tsize: ${script.sampling.size}`,
`\tscenarios: ${script.scenarios.length}`,
`\ttotalSamples (size * scenarios): ${totalSamples}`,
`\taveragePause: ${script.sampling.averagePause}`,
`\tpauseVariance: ${script.sampling.pauseVariance}`,
`\tmaxScriptDurationInSeconds: ${settings.maxScriptDurationInSeconds}`,
`\twarningThreshold: ${script.sampling.warningThreshold}`,
'Calculation',
`\t(${script.sampling.averagePause} + ${script.sampling.pauseVariance}) * ${script.sampling.size} = ${mostPossiblePause}`,
`\t${settings.maxScriptDurationInSeconds} * ${script.sampling.warningThreshold} = ${settings.maxScriptDurationInSeconds * script.sampling.warningThreshold}`,
'Condition',
`\t${mostPossiblePause} > ${settings.maxScriptDurationInSeconds * script.sampling.warningThreshold}`,
].join('\n'))
}
},
}
module.exports = sampling