@platformatic/runtime 3.13.1 → 3.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config.d.ts +73 -4
- package/index.d.ts +4 -0
- package/index.js +8 -3
- package/lib/config.js +118 -72
- package/lib/dynamic-workers-scaler.js +218 -0
- package/lib/errors.js +17 -0
- package/lib/logger.js +144 -11
- package/lib/runtime.js +401 -423
- package/lib/scaling-algorithm.js +26 -31
- package/lib/worker/controller.js +14 -4
- package/lib/worker/health-signals.js +80 -0
- package/lib/worker/main.js +6 -0
- package/lib/worker/symbols.js +2 -0
- package/package.json +15 -15
- package/schema.json +200 -22
package/lib/scaling-algorithm.js
CHANGED
|
@@ -1,23 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export const scaleUpELUThreshold = 0.8
|
|
2
|
+
export const scaleDownELUThreshold = 0.2
|
|
3
|
+
export const scaleUpTimeWindow = 10_000
|
|
4
|
+
export const scaleDownTimeWindow = 60_000
|
|
5
|
+
|
|
6
|
+
export class ScalingAlgorithm {
|
|
4
7
|
#maxTotalWorkers
|
|
5
|
-
#scaleUpTimeWindowSec
|
|
6
|
-
#scaleDownTimeWindowSec
|
|
7
8
|
#appsMetrics
|
|
8
9
|
#appsConfigs
|
|
9
10
|
|
|
10
11
|
constructor (options = {}) {
|
|
11
|
-
this.#scaleUpELU = options.scaleUpELU ?? 0.8
|
|
12
|
-
this.#scaleDownELU = options.scaleDownELU ?? 0.2
|
|
13
12
|
this.#maxTotalWorkers = options.maxTotalWorkers ?? Infinity
|
|
14
|
-
this.#scaleUpTimeWindowSec = options.scaleUpTimeWindowSec ?? 10
|
|
15
|
-
this.#scaleDownTimeWindowSec = options.scaleDownTimeWindowSec ?? 60
|
|
16
13
|
this.#appsConfigs = options.applications ?? {}
|
|
17
|
-
|
|
18
14
|
this.#appsMetrics = {}
|
|
19
15
|
}
|
|
20
16
|
|
|
17
|
+
addApplication (id, config) {
|
|
18
|
+
this.#appsConfigs[id] = config
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
removeApplication (id) {
|
|
22
|
+
delete this.#appsConfigs[id]
|
|
23
|
+
delete this.#appsMetrics[id]
|
|
24
|
+
}
|
|
25
|
+
|
|
21
26
|
addWorkerHealthInfo (healthInfo) {
|
|
22
27
|
const { workerId, applicationId, elu, heapUsed } = healthInfo
|
|
23
28
|
const timestamp = Date.now()
|
|
@@ -50,7 +55,7 @@ class ScalingAlgorithm {
|
|
|
50
55
|
appsInfo.push({
|
|
51
56
|
applicationId,
|
|
52
57
|
workersCount,
|
|
53
|
-
avgHeapUsed: heapUsed
|
|
58
|
+
avgHeapUsed: heapUsed
|
|
54
59
|
})
|
|
55
60
|
|
|
56
61
|
totalWorkersCount += workersCount
|
|
@@ -112,9 +117,7 @@ class ScalingAlgorithm {
|
|
|
112
117
|
if (workersCount >= appMaxWorkers) continue
|
|
113
118
|
if (avgHeapUsed >= totalAvailableMemory) continue
|
|
114
119
|
|
|
115
|
-
const isScaled = recommendations.some(
|
|
116
|
-
r => r.applicationId === applicationId
|
|
117
|
-
)
|
|
120
|
+
const isScaled = recommendations.some(r => r.applicationId === applicationId)
|
|
118
121
|
if (isScaled) continue
|
|
119
122
|
|
|
120
123
|
const recommendation = this.#getApplicationScaleRecommendation(applicationId)
|
|
@@ -122,10 +125,8 @@ class ScalingAlgorithm {
|
|
|
122
125
|
|
|
123
126
|
if (
|
|
124
127
|
!scaleUpCandidate ||
|
|
125
|
-
|
|
126
|
-
(recommendation.scaleUpELU === scaleUpCandidate.scaleUpELU &&
|
|
127
|
-
workersCount < scaleUpCandidate.workersCount
|
|
128
|
-
)
|
|
128
|
+
recommendation.scaleUpELU > scaleUpCandidate.scaleUpELU ||
|
|
129
|
+
(recommendation.scaleUpELU === scaleUpCandidate.scaleUpELU && workersCount < scaleUpCandidate.workersCount)
|
|
129
130
|
) {
|
|
130
131
|
scaleUpCandidate = {
|
|
131
132
|
applicationId,
|
|
@@ -186,8 +187,8 @@ class ScalingAlgorithm {
|
|
|
186
187
|
count++
|
|
187
188
|
}
|
|
188
189
|
|
|
189
|
-
const elu = Math.round(eluSum / count * 100) / 100
|
|
190
|
-
const heapUsed = Math.round(heapUsedSum / count * 100) / 100
|
|
190
|
+
const elu = Math.round((eluSum / count) * 100) / 100
|
|
191
|
+
const heapUsed = Math.round((heapUsedSum / count) * 100) / 100
|
|
191
192
|
return { elu, heapUsed }
|
|
192
193
|
}
|
|
193
194
|
|
|
@@ -226,28 +227,22 @@ class ScalingAlgorithm {
|
|
|
226
227
|
}
|
|
227
228
|
|
|
228
229
|
#getMetricsTimeWindow () {
|
|
229
|
-
return Math.max(
|
|
230
|
+
return Math.max(scaleUpTimeWindow, scaleDownTimeWindow) * 1000
|
|
230
231
|
}
|
|
231
232
|
|
|
232
233
|
#getApplicationScaleRecommendation (applicationId) {
|
|
233
|
-
const { elu: scaleUpELU } = this.#calculateAppAvgMetrics(applicationId, {
|
|
234
|
-
|
|
235
|
-
})
|
|
236
|
-
const { elu: scaleDownELU } = this.#calculateAppAvgMetrics(applicationId, {
|
|
237
|
-
timeWindow: this.#scaleDownTimeWindowSec * 1000
|
|
238
|
-
})
|
|
234
|
+
const { elu: scaleUpELU } = this.#calculateAppAvgMetrics(applicationId, { timeWindow: scaleUpTimeWindow })
|
|
235
|
+
const { elu: scaleDownELU } = this.#calculateAppAvgMetrics(applicationId, { timeWindow: scaleDownTimeWindow })
|
|
239
236
|
const { heapUsed: avgHeapUsage } = this.#calculateAppAvgMetrics(applicationId)
|
|
240
237
|
|
|
241
238
|
let recommendation = null
|
|
242
|
-
if (scaleUpELU >
|
|
239
|
+
if (scaleUpELU > scaleUpELUThreshold) {
|
|
243
240
|
recommendation = 'scaleUp'
|
|
244
241
|
}
|
|
245
|
-
if (scaleDownELU <
|
|
242
|
+
if (scaleDownELU < scaleDownELUThreshold) {
|
|
246
243
|
recommendation = 'scaleDown'
|
|
247
244
|
}
|
|
248
245
|
|
|
249
246
|
return { recommendation, scaleUpELU, scaleDownELU, avgHeapUsage }
|
|
250
247
|
}
|
|
251
248
|
}
|
|
252
|
-
|
|
253
|
-
export default ScalingAlgorithm
|
package/lib/worker/controller.js
CHANGED
|
@@ -161,7 +161,7 @@ export class Controller extends EventEmitter {
|
|
|
161
161
|
return
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
this
|
|
164
|
+
this.#updateCapabilityStatus('starting')
|
|
165
165
|
this.emit('starting')
|
|
166
166
|
|
|
167
167
|
if (this.#watch) {
|
|
@@ -185,7 +185,7 @@ export class Controller extends EventEmitter {
|
|
|
185
185
|
this.#listening = listen
|
|
186
186
|
/* c8 ignore next 5 */
|
|
187
187
|
} catch (err) {
|
|
188
|
-
this
|
|
188
|
+
this.#updateCapabilityStatus('start:error')
|
|
189
189
|
this.emit('start:error', err)
|
|
190
190
|
|
|
191
191
|
this.capability.log({ message: err.message, level: 'debug' })
|
|
@@ -196,7 +196,7 @@ export class Controller extends EventEmitter {
|
|
|
196
196
|
this.#started = true
|
|
197
197
|
this.#starting = false
|
|
198
198
|
|
|
199
|
-
this
|
|
199
|
+
this.#updateCapabilityStatus('started')
|
|
200
200
|
this.emit('started')
|
|
201
201
|
}
|
|
202
202
|
|
|
@@ -218,7 +218,7 @@ export class Controller extends EventEmitter {
|
|
|
218
218
|
this.#starting = false
|
|
219
219
|
this.#listening = false
|
|
220
220
|
|
|
221
|
-
this
|
|
221
|
+
this.#updateCapabilityStatus('stopped')
|
|
222
222
|
this.emit('stopped')
|
|
223
223
|
}
|
|
224
224
|
|
|
@@ -333,4 +333,14 @@ export class Controller extends EventEmitter {
|
|
|
333
333
|
}
|
|
334
334
|
})
|
|
335
335
|
}
|
|
336
|
+
|
|
337
|
+
#updateCapabilityStatus (status) {
|
|
338
|
+
if (typeof this.capability.updateStatus === 'function') {
|
|
339
|
+
this.capability.updateStatus(status)
|
|
340
|
+
} else {
|
|
341
|
+
// This is horrible but needed for backward compatibility
|
|
342
|
+
this.capability.status = status
|
|
343
|
+
this.capability.emit(status)
|
|
344
|
+
}
|
|
345
|
+
}
|
|
336
346
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HealthSignalMustBeObjectError,
|
|
3
|
+
HealthSignalTypeMustBeStringError
|
|
4
|
+
} from '../errors.js'
|
|
5
|
+
|
|
6
|
+
export class HealthSignalsQueue {
|
|
7
|
+
#size
|
|
8
|
+
#values
|
|
9
|
+
|
|
10
|
+
constructor (options = {}) {
|
|
11
|
+
this.#size = options.size ?? 100
|
|
12
|
+
this.#values = []
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
add (value) {
|
|
16
|
+
if (Array.isArray(value)) {
|
|
17
|
+
for (const v of value) {
|
|
18
|
+
this.#values.push(v)
|
|
19
|
+
}
|
|
20
|
+
} else {
|
|
21
|
+
this.#values.push(value)
|
|
22
|
+
}
|
|
23
|
+
if (this.#values.length > this.#size) {
|
|
24
|
+
this.#values.splice(0, this.#values.length - this.#size)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
getAll () {
|
|
29
|
+
const values = this.#values
|
|
30
|
+
this.#values = []
|
|
31
|
+
return values
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function initHealthSignalsApi (options = {}) {
|
|
36
|
+
const queue = new HealthSignalsQueue()
|
|
37
|
+
const timeout = options.timeout ?? 1000
|
|
38
|
+
const workerId = options.workerId
|
|
39
|
+
|
|
40
|
+
let isSending = false
|
|
41
|
+
let promise = null
|
|
42
|
+
|
|
43
|
+
async function sendHealthSignal (signal) {
|
|
44
|
+
if (typeof signal !== 'object') {
|
|
45
|
+
throw new HealthSignalMustBeObjectError()
|
|
46
|
+
}
|
|
47
|
+
if (typeof signal.type !== 'string') {
|
|
48
|
+
throw new HealthSignalTypeMustBeStringError(signal.type)
|
|
49
|
+
}
|
|
50
|
+
if (!signal.timestamp || typeof signal.timestamp !== 'number') {
|
|
51
|
+
signal.timestamp = Date.now()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
queue.add(signal)
|
|
55
|
+
|
|
56
|
+
if (!isSending) {
|
|
57
|
+
isSending = true
|
|
58
|
+
promise = new Promise((resolve, reject) => {
|
|
59
|
+
setTimeout(async () => {
|
|
60
|
+
isSending = false
|
|
61
|
+
try {
|
|
62
|
+
const signals = queue.getAll()
|
|
63
|
+
await globalThis.platformatic.itc.send('sendHealthSignals', {
|
|
64
|
+
workerId,
|
|
65
|
+
signals
|
|
66
|
+
})
|
|
67
|
+
} catch (err) {
|
|
68
|
+
reject(err)
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
resolve()
|
|
72
|
+
}, timeout)
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return promise
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
globalThis.platformatic.sendHealthSignal = sendHealthSignal
|
|
80
|
+
}
|
package/lib/worker/main.js
CHANGED
|
@@ -20,6 +20,7 @@ import { setDispatcher } from './interceptors.js'
|
|
|
20
20
|
import { setupITC } from './itc.js'
|
|
21
21
|
import { SharedContext } from './shared-context.js'
|
|
22
22
|
import { kId, kITC, kStderrMarker } from './symbols.js'
|
|
23
|
+
import { initHealthSignalsApi } from './health-signals.js'
|
|
23
24
|
|
|
24
25
|
class ForwardingEventEmitter extends EventEmitter {
|
|
25
26
|
emitAndNotify (event, ...args) {
|
|
@@ -190,6 +191,11 @@ async function main () {
|
|
|
190
191
|
globalThis[kITC] = itc
|
|
191
192
|
globalThis.platformatic.itc = itc
|
|
192
193
|
|
|
194
|
+
initHealthSignalsApi({
|
|
195
|
+
workerId: workerData.worker.id,
|
|
196
|
+
applicationId: applicationConfig.id
|
|
197
|
+
})
|
|
198
|
+
|
|
193
199
|
itc.notify('init')
|
|
194
200
|
}
|
|
195
201
|
|
package/lib/worker/symbols.js
CHANGED
|
@@ -5,7 +5,9 @@ export const kApplicationId = Symbol.for('plt.runtime.application.id')
|
|
|
5
5
|
export const kWorkerId = Symbol.for('plt.runtime.worker.id')
|
|
6
6
|
export const kITC = Symbol.for('plt.runtime.itc')
|
|
7
7
|
export const kHealthCheckTimer = Symbol.for('plt.runtime.worker.healthCheckTimer')
|
|
8
|
+
export const kHealthMetricsTimer = Symbol.for('plt.runtime.worker.healthMetricsTimer')
|
|
8
9
|
export const kWorkerStatus = Symbol('plt.runtime.worker.status')
|
|
10
|
+
export const kWorkerHealthSignals = Symbol.for('plt.runtime.worker.healthSignals')
|
|
9
11
|
export const kWorkerStartTime = Symbol.for('plt.runtime.worker.startTime')
|
|
10
12
|
export const kInterceptors = Symbol.for('plt.runtime.worker.interceptors')
|
|
11
13
|
export const kLastHealthCheckELU = Symbol.for('plt.runtime.worker.lastHealthCheckELU')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/runtime",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.15.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -35,14 +35,14 @@
|
|
|
35
35
|
"typescript": "^5.5.4",
|
|
36
36
|
"undici-oidc-interceptor": "^0.5.0",
|
|
37
37
|
"why-is-node-running": "^2.2.2",
|
|
38
|
-
"@platformatic/composer": "3.
|
|
39
|
-
"@platformatic/db": "3.
|
|
40
|
-
"@platformatic/gateway": "3.
|
|
41
|
-
"@platformatic/node": "3.
|
|
42
|
-
"@platformatic/
|
|
43
|
-
"@platformatic/
|
|
44
|
-
"@platformatic/sql-mapper": "3.
|
|
45
|
-
"@platformatic/wattpm-pprof-capture": "3.
|
|
38
|
+
"@platformatic/composer": "3.15.0",
|
|
39
|
+
"@platformatic/db": "3.15.0",
|
|
40
|
+
"@platformatic/gateway": "3.15.0",
|
|
41
|
+
"@platformatic/node": "3.15.0",
|
|
42
|
+
"@platformatic/sql-graphql": "3.15.0",
|
|
43
|
+
"@platformatic/service": "3.15.0",
|
|
44
|
+
"@platformatic/sql-mapper": "3.15.0",
|
|
45
|
+
"@platformatic/wattpm-pprof-capture": "3.15.0"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@fastify/accepts": "^5.0.0",
|
|
@@ -73,12 +73,12 @@
|
|
|
73
73
|
"undici": "^7.0.0",
|
|
74
74
|
"undici-thread-interceptor": "^0.15.0",
|
|
75
75
|
"ws": "^8.16.0",
|
|
76
|
-
"@platformatic/basic": "3.
|
|
77
|
-
"@platformatic/
|
|
78
|
-
"@platformatic/
|
|
79
|
-
"@platformatic/
|
|
80
|
-
"@platformatic/itc": "3.
|
|
81
|
-
"@platformatic/
|
|
76
|
+
"@platformatic/basic": "3.15.0",
|
|
77
|
+
"@platformatic/foundation": "3.15.0",
|
|
78
|
+
"@platformatic/metrics": "3.15.0",
|
|
79
|
+
"@platformatic/generators": "3.15.0",
|
|
80
|
+
"@platformatic/itc": "3.15.0",
|
|
81
|
+
"@platformatic/telemetry": "3.15.0"
|
|
82
82
|
},
|
|
83
83
|
"engines": {
|
|
84
84
|
"node": ">=22.19.0"
|
package/schema.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://schemas.platformatic.dev/@platformatic/runtime/3.
|
|
2
|
+
"$id": "https://schemas.platformatic.dev/@platformatic/runtime/3.15.0.json",
|
|
3
3
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
4
|
"title": "Platformatic Runtime Config",
|
|
5
5
|
"type": "object",
|
|
@@ -64,14 +64,34 @@
|
|
|
64
64
|
"useHttp": {
|
|
65
65
|
"type": "boolean"
|
|
66
66
|
},
|
|
67
|
+
"reuseTcpPorts": {
|
|
68
|
+
"type": "boolean",
|
|
69
|
+
"default": true
|
|
70
|
+
},
|
|
67
71
|
"workers": {
|
|
68
72
|
"anyOf": [
|
|
69
73
|
{
|
|
70
|
-
"type": "number"
|
|
71
|
-
"minimum": 1
|
|
74
|
+
"type": "number"
|
|
72
75
|
},
|
|
73
76
|
{
|
|
74
77
|
"type": "string"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"type": "object",
|
|
81
|
+
"properties": {
|
|
82
|
+
"static": {
|
|
83
|
+
"type": "number",
|
|
84
|
+
"minimum": 1
|
|
85
|
+
},
|
|
86
|
+
"minimum": {
|
|
87
|
+
"type": "number",
|
|
88
|
+
"minimum": 1
|
|
89
|
+
},
|
|
90
|
+
"maximum": {
|
|
91
|
+
"type": "number",
|
|
92
|
+
"minimum": 0
|
|
93
|
+
}
|
|
94
|
+
}
|
|
75
95
|
}
|
|
76
96
|
]
|
|
77
97
|
},
|
|
@@ -326,14 +346,34 @@
|
|
|
326
346
|
"useHttp": {
|
|
327
347
|
"type": "boolean"
|
|
328
348
|
},
|
|
349
|
+
"reuseTcpPorts": {
|
|
350
|
+
"type": "boolean",
|
|
351
|
+
"default": true
|
|
352
|
+
},
|
|
329
353
|
"workers": {
|
|
330
354
|
"anyOf": [
|
|
331
355
|
{
|
|
332
|
-
"type": "number"
|
|
333
|
-
"minimum": 1
|
|
356
|
+
"type": "number"
|
|
334
357
|
},
|
|
335
358
|
{
|
|
336
359
|
"type": "string"
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
"type": "object",
|
|
363
|
+
"properties": {
|
|
364
|
+
"static": {
|
|
365
|
+
"type": "number",
|
|
366
|
+
"minimum": 1
|
|
367
|
+
},
|
|
368
|
+
"minimum": {
|
|
369
|
+
"type": "number",
|
|
370
|
+
"minimum": 1
|
|
371
|
+
},
|
|
372
|
+
"maximum": {
|
|
373
|
+
"type": "number",
|
|
374
|
+
"minimum": 0
|
|
375
|
+
}
|
|
376
|
+
}
|
|
337
377
|
}
|
|
338
378
|
]
|
|
339
379
|
},
|
|
@@ -586,14 +626,34 @@
|
|
|
586
626
|
"useHttp": {
|
|
587
627
|
"type": "boolean"
|
|
588
628
|
},
|
|
629
|
+
"reuseTcpPorts": {
|
|
630
|
+
"type": "boolean",
|
|
631
|
+
"default": true
|
|
632
|
+
},
|
|
589
633
|
"workers": {
|
|
590
634
|
"anyOf": [
|
|
591
635
|
{
|
|
592
|
-
"type": "number"
|
|
593
|
-
"minimum": 1
|
|
636
|
+
"type": "number"
|
|
594
637
|
},
|
|
595
638
|
{
|
|
596
639
|
"type": "string"
|
|
640
|
+
},
|
|
641
|
+
{
|
|
642
|
+
"type": "object",
|
|
643
|
+
"properties": {
|
|
644
|
+
"static": {
|
|
645
|
+
"type": "number",
|
|
646
|
+
"minimum": 1
|
|
647
|
+
},
|
|
648
|
+
"minimum": {
|
|
649
|
+
"type": "number",
|
|
650
|
+
"minimum": 1
|
|
651
|
+
},
|
|
652
|
+
"maximum": {
|
|
653
|
+
"type": "number",
|
|
654
|
+
"minimum": 0
|
|
655
|
+
}
|
|
656
|
+
}
|
|
597
657
|
}
|
|
598
658
|
]
|
|
599
659
|
},
|
|
@@ -846,14 +906,34 @@
|
|
|
846
906
|
"useHttp": {
|
|
847
907
|
"type": "boolean"
|
|
848
908
|
},
|
|
909
|
+
"reuseTcpPorts": {
|
|
910
|
+
"type": "boolean",
|
|
911
|
+
"default": true
|
|
912
|
+
},
|
|
849
913
|
"workers": {
|
|
850
914
|
"anyOf": [
|
|
851
915
|
{
|
|
852
|
-
"type": "number"
|
|
853
|
-
"minimum": 1
|
|
916
|
+
"type": "number"
|
|
854
917
|
},
|
|
855
918
|
{
|
|
856
919
|
"type": "string"
|
|
920
|
+
},
|
|
921
|
+
{
|
|
922
|
+
"type": "object",
|
|
923
|
+
"properties": {
|
|
924
|
+
"static": {
|
|
925
|
+
"type": "number",
|
|
926
|
+
"minimum": 1
|
|
927
|
+
},
|
|
928
|
+
"minimum": {
|
|
929
|
+
"type": "number",
|
|
930
|
+
"minimum": 1
|
|
931
|
+
},
|
|
932
|
+
"maximum": {
|
|
933
|
+
"type": "number",
|
|
934
|
+
"minimum": 0
|
|
935
|
+
}
|
|
936
|
+
}
|
|
857
937
|
}
|
|
858
938
|
]
|
|
859
939
|
},
|
|
@@ -1074,6 +1154,43 @@
|
|
|
1074
1154
|
},
|
|
1075
1155
|
{
|
|
1076
1156
|
"type": "string"
|
|
1157
|
+
},
|
|
1158
|
+
{
|
|
1159
|
+
"type": "object",
|
|
1160
|
+
"properties": {
|
|
1161
|
+
"static": {
|
|
1162
|
+
"type": "number",
|
|
1163
|
+
"minimum": 1
|
|
1164
|
+
},
|
|
1165
|
+
"dynamic": {
|
|
1166
|
+
"type": "boolean",
|
|
1167
|
+
"default": false
|
|
1168
|
+
},
|
|
1169
|
+
"minimum": {
|
|
1170
|
+
"type": "number",
|
|
1171
|
+
"minimum": 1
|
|
1172
|
+
},
|
|
1173
|
+
"maximum": {
|
|
1174
|
+
"type": "number",
|
|
1175
|
+
"minimum": 0
|
|
1176
|
+
},
|
|
1177
|
+
"total": {
|
|
1178
|
+
"type": "number",
|
|
1179
|
+
"minimum": 1
|
|
1180
|
+
},
|
|
1181
|
+
"maxMemory": {
|
|
1182
|
+
"type": "number",
|
|
1183
|
+
"minimum": 0
|
|
1184
|
+
},
|
|
1185
|
+
"cooldown": {
|
|
1186
|
+
"type": "number",
|
|
1187
|
+
"minimum": 0
|
|
1188
|
+
},
|
|
1189
|
+
"gracePeriod": {
|
|
1190
|
+
"type": "number",
|
|
1191
|
+
"minimum": 0
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1077
1194
|
}
|
|
1078
1195
|
]
|
|
1079
1196
|
},
|
|
@@ -1363,6 +1480,10 @@
|
|
|
1363
1480
|
},
|
|
1364
1481
|
"additionalProperties": false
|
|
1365
1482
|
},
|
|
1483
|
+
"reuseTcpPorts": {
|
|
1484
|
+
"type": "boolean",
|
|
1485
|
+
"default": true
|
|
1486
|
+
},
|
|
1366
1487
|
"startTimeout": {
|
|
1367
1488
|
"default": 30000,
|
|
1368
1489
|
"type": "number",
|
|
@@ -1854,6 +1975,58 @@
|
|
|
1854
1975
|
}
|
|
1855
1976
|
],
|
|
1856
1977
|
"default": 10000
|
|
1978
|
+
},
|
|
1979
|
+
"otlpExporter": {
|
|
1980
|
+
"type": "object",
|
|
1981
|
+
"description": "Configuration for exporting metrics to an OTLP endpoint",
|
|
1982
|
+
"properties": {
|
|
1983
|
+
"enabled": {
|
|
1984
|
+
"anyOf": [
|
|
1985
|
+
{
|
|
1986
|
+
"type": "boolean"
|
|
1987
|
+
},
|
|
1988
|
+
{
|
|
1989
|
+
"type": "string"
|
|
1990
|
+
}
|
|
1991
|
+
],
|
|
1992
|
+
"description": "Enable or disable OTLP metrics export"
|
|
1993
|
+
},
|
|
1994
|
+
"endpoint": {
|
|
1995
|
+
"type": "string",
|
|
1996
|
+
"description": "OTLP endpoint URL (e.g., http://collector:4318/v1/metrics)"
|
|
1997
|
+
},
|
|
1998
|
+
"interval": {
|
|
1999
|
+
"anyOf": [
|
|
2000
|
+
{
|
|
2001
|
+
"type": "integer"
|
|
2002
|
+
},
|
|
2003
|
+
{
|
|
2004
|
+
"type": "string"
|
|
2005
|
+
}
|
|
2006
|
+
],
|
|
2007
|
+
"default": 60000,
|
|
2008
|
+
"description": "Interval in milliseconds between metric pushes"
|
|
2009
|
+
},
|
|
2010
|
+
"headers": {
|
|
2011
|
+
"type": "object",
|
|
2012
|
+
"additionalProperties": {
|
|
2013
|
+
"type": "string"
|
|
2014
|
+
},
|
|
2015
|
+
"description": "Additional HTTP headers for authentication"
|
|
2016
|
+
},
|
|
2017
|
+
"serviceName": {
|
|
2018
|
+
"type": "string",
|
|
2019
|
+
"description": "Service name for OTLP resource attributes"
|
|
2020
|
+
},
|
|
2021
|
+
"serviceVersion": {
|
|
2022
|
+
"type": "string",
|
|
2023
|
+
"description": "Service version for OTLP resource attributes"
|
|
2024
|
+
}
|
|
2025
|
+
},
|
|
2026
|
+
"required": [
|
|
2027
|
+
"endpoint"
|
|
2028
|
+
],
|
|
2029
|
+
"additionalProperties": false
|
|
1857
2030
|
}
|
|
1858
2031
|
},
|
|
1859
2032
|
"additionalProperties": false
|
|
@@ -2013,35 +2186,40 @@
|
|
|
2013
2186
|
"type": "number",
|
|
2014
2187
|
"minimum": 1
|
|
2015
2188
|
},
|
|
2189
|
+
"cooldownSec": {
|
|
2190
|
+
"type": "number",
|
|
2191
|
+
"minimum": 0
|
|
2192
|
+
},
|
|
2193
|
+
"gracePeriod": {
|
|
2194
|
+
"type": "number",
|
|
2195
|
+
"minimum": 0
|
|
2196
|
+
},
|
|
2016
2197
|
"scaleUpELU": {
|
|
2017
2198
|
"type": "number",
|
|
2018
2199
|
"minimum": 0,
|
|
2019
|
-
"maximum": 1
|
|
2200
|
+
"maximum": 1,
|
|
2201
|
+
"deprecated": true
|
|
2020
2202
|
},
|
|
2021
2203
|
"scaleDownELU": {
|
|
2022
2204
|
"type": "number",
|
|
2023
2205
|
"minimum": 0,
|
|
2024
|
-
"maximum": 1
|
|
2206
|
+
"maximum": 1,
|
|
2207
|
+
"deprecated": true
|
|
2025
2208
|
},
|
|
2026
2209
|
"timeWindowSec": {
|
|
2027
2210
|
"type": "number",
|
|
2028
|
-
"minimum": 0
|
|
2211
|
+
"minimum": 0,
|
|
2212
|
+
"deprecated": true
|
|
2029
2213
|
},
|
|
2030
2214
|
"scaleDownTimeWindowSec": {
|
|
2031
2215
|
"type": "number",
|
|
2032
|
-
"minimum": 0
|
|
2033
|
-
|
|
2034
|
-
"cooldownSec": {
|
|
2035
|
-
"type": "number",
|
|
2036
|
-
"minimum": 0
|
|
2216
|
+
"minimum": 0,
|
|
2217
|
+
"deprecated": true
|
|
2037
2218
|
},
|
|
2038
2219
|
"scaleIntervalSec": {
|
|
2039
2220
|
"type": "number",
|
|
2040
|
-
"minimum": 0
|
|
2041
|
-
|
|
2042
|
-
"gracePeriod": {
|
|
2043
|
-
"type": "number",
|
|
2044
|
-
"minimum": 0
|
|
2221
|
+
"minimum": 0,
|
|
2222
|
+
"deprecated": true
|
|
2045
2223
|
},
|
|
2046
2224
|
"applications": {
|
|
2047
2225
|
"type": "object",
|