@@ -39,6 +39,7 @@ const (
39
39
memLimitMiBEnvVarName = "SPLUNK_MEMORY_LIMIT_MIB"
40
40
memSpikeEnvVarName = "SPLUNK_MEMORY_SPIKE_PERCENTAGE"
41
41
memSpikeMiBEnvVarName = "SPLUNK_MEMORY_SPIKE_MIB"
42
+ memTotalEnvVarName = "SPLUNK_MEMORY_TOTAL_MIB"
42
43
realmEnvVarName = "SPLUNK_REALM"
43
44
tokenEnvVarName = "SPLUNK_ACCESS_TOKEN"
44
45
@@ -50,22 +51,50 @@ const (
50
51
defaultLocalSAPMNonLinuxConfig = "cmd/otelcol/config/collector/splunk_config_non_linux.yaml"
51
52
defaultLocalOTLPLinuxConfig = "cmd/otelcol/config/collector/otlp_config_linux.yaml"
52
53
defaultLocalOTLPNonLinuxConfig = "cmd/otelcol/config/collector/otlp_config_non_linux.yaml"
54
+ defaultMemoryBallastPercentage = 50
53
55
defaultMemoryLimitPercentage = 90
56
+ defaultMemoryLimitMaxMiB = 2048
54
57
defaultMemorySpikePercentage = 25
58
+ defaultMemorySpikeMaxMiB = 2048
55
59
)
56
60
57
61
func main () {
62
+ // TODO: Use same format as the collector
58
63
log .SetFlags (log .Ldate | log .Ltime | log .Lshortfile )
59
64
65
+ // Check if the total memory is specified via the env var.
66
+ memTotalEnvVarVal := os .Getenv (memTotalEnvVarName )
67
+ memTotalSizeMiB := 0
68
+ if memTotalEnvVarVal != "" {
69
+ // Check if it is a numeric value.
70
+ val , err := strconv .Atoi (memTotalEnvVarVal )
71
+ if err != nil {
72
+ log .Fatalf ("Expected a number in %s env variable but got %s" , memTotalEnvVarName , memTotalEnvVarVal )
73
+ }
74
+ if 10 > val {
75
+ log .Fatalf ("Expected a number greater than 10 for %s env variable but got %s" , memTotalEnvVarName , memTotalEnvVarVal )
76
+ }
77
+ memTotalSizeMiB = val
78
+ }
79
+
60
80
// Check runtime parameters
61
81
// Runtime parameters take priority over environment variables
62
82
// Runtime parameters are not validated
63
83
args := os .Args [1 :]
64
84
if ! contains (args , "--mem-ballast-size-mib" ) {
65
- useBallastSizeFromEnvVar ()
85
+ useMemorySizeFromEnvVar (memTotalSizeMiB )
86
+ } else {
87
+ log .Printf ("Ballast CLI argument found, ignoring %s if set" , ballastEnvVarName )
66
88
}
67
89
if ! contains (args , "--config" ) {
68
90
useConfigFromEnvVar ()
91
+ } else {
92
+ log .Printf ("Config CLI argument found, please ensure memory_limiter settings are correct" )
93
+ }
94
+ if runtime .GOOS == "linux" {
95
+ useMemorySettingsPercentageFromEnvVar ()
96
+ } else {
97
+ useMemorySettingsMiBFromEnvVar (memTotalSizeMiB )
69
98
}
70
99
71
100
factories , err := components .Get ()
@@ -98,18 +127,27 @@ func contains(arr []string, str string) bool {
98
127
return false
99
128
}
100
129
101
- func useBallastSizeFromEnvVar ( ) {
130
+ func useMemorySizeFromEnvVar ( memTotalSizeMiB int ) {
102
131
// Check if the ballast is specified via the env var.
103
132
ballastSize := os .Getenv (ballastEnvVarName )
104
133
if ballastSize != "" {
105
134
// Check if it is a numeric value.
106
- _ , err := strconv .Atoi (ballastSize )
135
+ val , err := strconv .Atoi (ballastSize )
107
136
if err != nil {
108
137
log .Fatalf ("Expected a number in %s env variable but got %s" , ballastEnvVarName , ballastSize )
109
138
}
139
+ if 0 > val {
140
+ log .Fatalf ("Expected a number greater than 0 for %s env variable but got %s" , ballastEnvVarName , ballastSize )
141
+ }
110
142
111
143
// Inject the command line flag that controls the ballast size.
112
144
os .Args = append (os .Args , "--mem-ballast-size-mib=" + ballastSize )
145
+ } else if memTotalSizeMiB > 0 {
146
+ halfMem := strconv .Itoa (memTotalSizeMiB * defaultMemoryBallastPercentage / 100 )
147
+ log .Printf ("Set ballast to %s MiB" , halfMem )
148
+ // Inject the command line flag that controls the ballast size.
149
+ os .Args = append (os .Args , "--mem-ballast-size-mib=" + halfMem )
150
+ os .Setenv (ballastEnvVarName , halfMem )
113
151
}
114
152
}
115
153
@@ -130,7 +168,6 @@ func useConfigFromEnvVar() {
130
168
if config == "" {
131
169
log .Fatalf ("Unable to find the default configuration file, ensure %s environment variable is set properly" , configEnvVarName )
132
170
}
133
- useMemorySettingsPercentageFromEnvVar ()
134
171
} else {
135
172
_ , err := os .Stat (defaultDockerSAPMNonLinuxConfig )
136
173
if err == nil {
@@ -143,7 +180,6 @@ func useConfigFromEnvVar() {
143
180
if config == "" {
144
181
log .Fatalf ("Unable to find the default configuration file, ensure %s environment variable is set properly" , configEnvVarName )
145
182
}
146
- useMemorySettingsMiBFromEnvVar ()
147
183
}
148
184
} else {
149
185
// Check if file exists.
@@ -165,25 +201,31 @@ func useConfigFromEnvVar() {
165
201
defaultLocalOTLPNonLinuxConfig :
166
202
// The following environment variables are required.
167
203
// If any are missing stop here.
168
- requiredEnvVars := []string {ballastEnvVarName , realmEnvVarName , tokenEnvVarName }
204
+ requiredEnvVars := []string {realmEnvVarName , tokenEnvVarName }
169
205
for _ , v := range requiredEnvVars {
170
206
if len (os .Getenv (v )) == 0 {
171
- log .Printf ("Usage: %s=12345 %s=us0 %s=684 %s" , tokenEnvVarName , realmEnvVarName , ballastEnvVarName , os .Args [0 ])
207
+ log .Printf ("Usage: %s=12345 %s=us0 %s=1024 %s" , tokenEnvVarName , realmEnvVarName , memTotalEnvVarName , os .Args [0 ])
172
208
log .Fatalf ("ERROR: Missing environment variable %s" , v )
173
209
}
174
210
}
211
+ // Needed for backwards compatibility
212
+ if len (os .Getenv (memTotalEnvVarName )) == 0 && len (os .Getenv (ballastEnvVarName )) == 0 {
213
+ log .Printf ("Usage: %s=12345 %s=us0 %s=1024 %s" , tokenEnvVarName , realmEnvVarName , memTotalEnvVarName , os .Args [0 ])
214
+ log .Fatalf ("ERROR: Missing environment variable %s" , memTotalEnvVarName )
215
+ }
175
216
}
176
217
177
218
// Inject the command line flag that controls the configuration.
178
219
os .Args = append (os .Args , "--config=" + config )
179
220
}
180
221
181
- func checkMemorySettingsMiBFromEnvVar (envVar string ) int {
222
+ func checkMemorySettingsMiBFromEnvVar (envVar string , memTotalSizeMiB int ) int {
182
223
// Check if the memory limit is specified via the env var
183
224
// Ensure memory limit is valid
184
- var envVarResult int
225
+ var envVarResult int = 0
185
226
envVarVal := os .Getenv (envVar )
186
- if envVarVal != "" {
227
+ switch {
228
+ case envVarVal != "" :
187
229
// Check if it is a numeric value.
188
230
val , err := strconv .Atoi (envVarVal )
189
231
if err != nil {
@@ -193,16 +235,54 @@ func checkMemorySettingsMiBFromEnvVar(envVar string) int {
193
235
log .Fatalf ("Expected a number greater than 0 for %s env variable but got %s" , envVar , envVarVal )
194
236
}
195
237
envVarResult = val
196
- } else {
238
+ case memTotalSizeMiB > 0 :
239
+ break
240
+ default :
197
241
log .Printf ("Usage: %s=12345 %s=us0 %s=684 %s=1024 %s=256 %s" , tokenEnvVarName , realmEnvVarName , ballastEnvVarName , memLimitMiBEnvVarName , memSpikeMiBEnvVarName , os .Args [0 ])
198
242
log .Fatalf ("ERROR: Missing environment variable %s" , envVar )
199
243
}
200
244
return envVarResult
201
245
}
202
246
203
- func useMemorySettingsMiBFromEnvVar () {
204
- memLimit := checkMemorySettingsMiBFromEnvVar (memLimitMiBEnvVarName )
205
- memSpike := checkMemorySettingsMiBFromEnvVar (memSpikeMiBEnvVarName )
247
+ func useMemorySettingsMiBFromEnvVar (memTotalSizeMiB int ) {
248
+ // Check if memory limit is specified via environment variable
249
+ memLimit := checkMemorySettingsMiBFromEnvVar (memLimitMiBEnvVarName , memTotalSizeMiB )
250
+ // Use if set, otherwise memory total size must be specified
251
+ if memLimit == 0 {
252
+ if memTotalSizeMiB == 0 {
253
+ panic ("PANIC: Both memory limit MiB and memory total size are set to zero. This should never happen." )
254
+ }
255
+ // If not set, compute based on memory total size specified
256
+ // and default memory limit percentage const
257
+ memLimitMiB := memTotalSizeMiB * defaultMemoryLimitPercentage / 100
258
+ // The memory limit should be set to defaultMemoryLimitPercentage of total memory
259
+ // while reserving a maximum of defaultMemoryLimitMaxMiB of memory.
260
+ if (memTotalSizeMiB - memLimitMiB ) < defaultMemoryLimitMaxMiB {
261
+ memLimit = memLimitMiB
262
+ } else {
263
+ memLimit = (memTotalSizeMiB - defaultMemoryLimitMaxMiB )
264
+ }
265
+ log .Printf ("Set memory limit to %d MiB" , memLimit )
266
+ }
267
+ // Check if memory spike is specified via environment variable
268
+ memSpike := checkMemorySettingsMiBFromEnvVar (memSpikeMiBEnvVarName , memTotalSizeMiB )
269
+ // Use if set, otherwise memory total size must be specified
270
+ if memSpike == 0 {
271
+ if memTotalSizeMiB == 0 {
272
+ panic ("PANIC: Both memory limit MiB and memory total size are set to zero. This should never happen." )
273
+ }
274
+ // If not set, compute based on memory total size specified
275
+ // and default memory spike percentage const
276
+ memSpikeMiB := memTotalSizeMiB * defaultMemorySpikePercentage / 100
277
+ // The memory spike should be set to defaultMemorySpikePercentage of total memory
278
+ // while specifying a maximum of defaultMemorySpikeMaxMiB of memory.
279
+ if memSpikeMiB < defaultMemorySpikeMaxMiB {
280
+ memSpike = memSpikeMiB
281
+ } else {
282
+ memSpike = defaultMemorySpikeMaxMiB
283
+ }
284
+ log .Printf ("Set memory spike limit to %d MiB" , memSpike )
285
+ }
206
286
setMemorySettingsToEnvVar (memLimit , memLimitMiBEnvVarName , memSpike , memSpikeMiBEnvVarName )
207
287
}
208
288
0 commit comments