@platformatic/runtime 3.61.1 → 3.62.1
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 +25 -0
- package/index.d.ts +32 -1
- package/lib/errors.js +25 -0
- package/lib/runtime.js +584 -85
- package/lib/worker/health-signals.js +34 -0
- package/lib/worker/main.js +18 -2
- package/package.json +18 -18
- package/schema.json +212 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getITC, updateGlobals } from '@platformatic/globals'
|
|
2
|
+
import { monitorEventLoopDelay } from 'node:perf_hooks'
|
|
2
3
|
import {
|
|
3
4
|
HealthSignalMustBeObjectError,
|
|
4
5
|
HealthSignalTypeMustBeStringError
|
|
@@ -79,4 +80,37 @@ export function initHealthSignalsApi (options = {}) {
|
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
updateGlobals({ sendHealthSignal })
|
|
83
|
+
|
|
84
|
+
return sendHealthSignal
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Samples the event loop delay and reports it as an eventLoopDelay health
|
|
88
|
+
// signal once per second, in milliseconds. The measurement must run inside
|
|
89
|
+
// the worker (monitorEventLoopDelay is per-isolate, there is no cross-thread
|
|
90
|
+
// equivalent): during a hard block nothing is reported and a sample with a
|
|
91
|
+
// large max arrives once the loop unblocks — full blocks are already caught
|
|
92
|
+
// by the main-thread measured ELU, this signal catches long individual
|
|
93
|
+
// stalls at low average utilization, which are invisible to any ELU
|
|
94
|
+
// threshold.
|
|
95
|
+
export function startEventLoopDelayMonitor (sendHealthSignal, options = {}) {
|
|
96
|
+
const histogram = monitorEventLoopDelay({ resolution: options.resolution ?? 20 })
|
|
97
|
+
histogram.enable()
|
|
98
|
+
|
|
99
|
+
const interval = setInterval(() => {
|
|
100
|
+
// With one-second windows the p99 is close to the max (few dozen samples
|
|
101
|
+
// per window), but it smooths single outliers on consumers that prefer it
|
|
102
|
+
const max = histogram.max / 1e6
|
|
103
|
+
const mean = histogram.mean / 1e6
|
|
104
|
+
const p99 = histogram.percentile(99) / 1e6
|
|
105
|
+
histogram.reset()
|
|
106
|
+
|
|
107
|
+
// Signals are delivered on a best-effort basis
|
|
108
|
+
sendHealthSignal({ type: 'eventLoopDelay', max, mean, p99 }).catch(() => {})
|
|
109
|
+
}, options.interval ?? 1000)
|
|
110
|
+
interval.unref()
|
|
111
|
+
|
|
112
|
+
return function stopEventLoopDelayMonitor () {
|
|
113
|
+
clearInterval(interval)
|
|
114
|
+
histogram.disable()
|
|
115
|
+
}
|
|
82
116
|
}
|
package/lib/worker/main.js
CHANGED
|
@@ -22,7 +22,7 @@ import pino from 'pino'
|
|
|
22
22
|
import { install as installUndiciGlobals } from 'undici'
|
|
23
23
|
import { exitCodes } from '../errors.js'
|
|
24
24
|
import { Controller } from './controller.js'
|
|
25
|
-
import { initHealthSignalsApi } from './health-signals.js'
|
|
25
|
+
import { initHealthSignalsApi, startEventLoopDelayMonitor } from './health-signals.js'
|
|
26
26
|
import { setDispatcher } from './interceptors.js'
|
|
27
27
|
import { setupITC } from './itc.js'
|
|
28
28
|
import { SharedContext } from './shared-context.js'
|
|
@@ -338,11 +338,27 @@ async function main () {
|
|
|
338
338
|
}
|
|
339
339
|
}
|
|
340
340
|
|
|
341
|
-
initHealthSignalsApi({
|
|
341
|
+
const sendHealthSignal = initHealthSignalsApi({
|
|
342
342
|
workerId: workerData.worker.id,
|
|
343
343
|
applicationId: applicationConfig.id
|
|
344
344
|
})
|
|
345
345
|
|
|
346
|
+
// When health.maxEventLoopDelay or health.maxEventLoopDelayP99 are
|
|
347
|
+
// configured, sample the event loop delay and report it as a health
|
|
348
|
+
// signal: the main thread evaluates it as part of the health checks and it
|
|
349
|
+
// is exposed on the health metrics event.
|
|
350
|
+
const maxEventLoopDelay = Number(applicationConfig.health?.maxEventLoopDelay ?? runtimeConfig.health?.maxEventLoopDelay)
|
|
351
|
+
const maxEventLoopDelayP99 = Number(
|
|
352
|
+
applicationConfig.health?.maxEventLoopDelayP99 ?? runtimeConfig.health?.maxEventLoopDelayP99
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
if (
|
|
356
|
+
(Number.isFinite(maxEventLoopDelay) && maxEventLoopDelay > 0) ||
|
|
357
|
+
(Number.isFinite(maxEventLoopDelayP99) && maxEventLoopDelayP99 > 0)
|
|
358
|
+
) {
|
|
359
|
+
startEventLoopDelayMonitor(sendHealthSignal)
|
|
360
|
+
}
|
|
361
|
+
|
|
346
362
|
itc.notify('init')
|
|
347
363
|
}
|
|
348
364
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/runtime",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"description": "",
|
|
3
|
+
"version": "3.62.1",
|
|
4
|
+
"description": "Platformatic runtime",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"author": "Platformatic Inc. <oss@platformatic.dev> (https://platformatic.dev)",
|
|
@@ -36,17 +36,17 @@
|
|
|
36
36
|
"pino-sentry-transport": "^1.6.0",
|
|
37
37
|
"split2": "^4.2.0",
|
|
38
38
|
"tstyche": "^6.2.0",
|
|
39
|
-
"typescript": "^5.
|
|
39
|
+
"typescript": "^5.9.3",
|
|
40
40
|
"undici-oidc-interceptor": "^0.9.0",
|
|
41
41
|
"why-is-node-running": "^2.2.2",
|
|
42
|
-
"@platformatic/
|
|
43
|
-
"@platformatic/
|
|
44
|
-
"@platformatic/
|
|
45
|
-
"@platformatic/node": "3.
|
|
46
|
-
"@platformatic/
|
|
47
|
-
"@platformatic/sql-
|
|
48
|
-
"@platformatic/
|
|
49
|
-
"@platformatic/
|
|
42
|
+
"@platformatic/composer": "3.62.1",
|
|
43
|
+
"@platformatic/db": "3.62.1",
|
|
44
|
+
"@platformatic/gateway": "3.62.1",
|
|
45
|
+
"@platformatic/node": "3.62.1",
|
|
46
|
+
"@platformatic/service": "3.62.1",
|
|
47
|
+
"@platformatic/sql-mapper": "3.62.1",
|
|
48
|
+
"@platformatic/sql-graphql": "3.62.1",
|
|
49
|
+
"@platformatic/wattpm-pprof-capture": "3.62.1"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@fastify/accepts": "^5.0.0",
|
|
@@ -77,13 +77,13 @@
|
|
|
77
77
|
"undici": "^7.27.2",
|
|
78
78
|
"undici-thread-interceptor": "^1.3.1",
|
|
79
79
|
"ws": "^8.16.0",
|
|
80
|
-
"@platformatic/basic": "3.
|
|
81
|
-
"@platformatic/foundation": "3.
|
|
82
|
-
"@platformatic/
|
|
83
|
-
"@platformatic/
|
|
84
|
-
"@platformatic/
|
|
85
|
-
"@platformatic/telemetry": "3.
|
|
86
|
-
"@platformatic/
|
|
80
|
+
"@platformatic/basic": "3.62.1",
|
|
81
|
+
"@platformatic/foundation": "3.62.1",
|
|
82
|
+
"@platformatic/generators": "3.62.1",
|
|
83
|
+
"@platformatic/globals": "3.62.1",
|
|
84
|
+
"@platformatic/itc": "3.62.1",
|
|
85
|
+
"@platformatic/telemetry": "3.62.1",
|
|
86
|
+
"@platformatic/metrics": "3.62.1"
|
|
87
87
|
},
|
|
88
88
|
"engines": {
|
|
89
89
|
"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.62.1.json",
|
|
3
3
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
4
|
"title": "Platformatic Runtime Config",
|
|
5
5
|
"type": "object",
|
|
@@ -22,6 +22,59 @@
|
|
|
22
22
|
}
|
|
23
23
|
]
|
|
24
24
|
},
|
|
25
|
+
"extensions": {
|
|
26
|
+
"anyOf": [
|
|
27
|
+
{
|
|
28
|
+
"type": "string",
|
|
29
|
+
"resolvePath": true
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"type": "object",
|
|
33
|
+
"additionalProperties": false,
|
|
34
|
+
"required": [
|
|
35
|
+
"path"
|
|
36
|
+
],
|
|
37
|
+
"properties": {
|
|
38
|
+
"path": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"resolvePath": true
|
|
41
|
+
},
|
|
42
|
+
"options": {
|
|
43
|
+
"type": "object",
|
|
44
|
+
"additionalProperties": true
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"type": "array",
|
|
50
|
+
"items": {
|
|
51
|
+
"anyOf": [
|
|
52
|
+
{
|
|
53
|
+
"type": "string",
|
|
54
|
+
"resolvePath": true
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"type": "object",
|
|
58
|
+
"additionalProperties": false,
|
|
59
|
+
"required": [
|
|
60
|
+
"path"
|
|
61
|
+
],
|
|
62
|
+
"properties": {
|
|
63
|
+
"path": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"resolvePath": true
|
|
66
|
+
},
|
|
67
|
+
"options": {
|
|
68
|
+
"type": "object",
|
|
69
|
+
"additionalProperties": true
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
},
|
|
25
78
|
"entrypoint": {
|
|
26
79
|
"type": "string"
|
|
27
80
|
},
|
|
@@ -181,6 +234,28 @@
|
|
|
181
234
|
}
|
|
182
235
|
]
|
|
183
236
|
},
|
|
237
|
+
"maxEventLoopDelay": {
|
|
238
|
+
"anyOf": [
|
|
239
|
+
{
|
|
240
|
+
"type": "number",
|
|
241
|
+
"minimum": 0
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"type": "string"
|
|
245
|
+
}
|
|
246
|
+
]
|
|
247
|
+
},
|
|
248
|
+
"maxEventLoopDelayP99": {
|
|
249
|
+
"anyOf": [
|
|
250
|
+
{
|
|
251
|
+
"type": "number",
|
|
252
|
+
"minimum": 0
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"type": "string"
|
|
256
|
+
}
|
|
257
|
+
]
|
|
258
|
+
},
|
|
184
259
|
"maxHeapUsed": {
|
|
185
260
|
"anyOf": [
|
|
186
261
|
{
|
|
@@ -251,6 +326,18 @@
|
|
|
251
326
|
},
|
|
252
327
|
"additionalProperties": false
|
|
253
328
|
},
|
|
329
|
+
"restartOnError": {
|
|
330
|
+
"description": "Overrides the runtime-level restartOnError for this application. Set to false or 0 to never restart the application when it crashes, a positive number to wait that amount of milliseconds between restarts, or true to use the default delay.",
|
|
331
|
+
"anyOf": [
|
|
332
|
+
{
|
|
333
|
+
"type": "boolean"
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
"type": "number",
|
|
337
|
+
"minimum": 0
|
|
338
|
+
}
|
|
339
|
+
]
|
|
340
|
+
},
|
|
254
341
|
"dependencies": {
|
|
255
342
|
"type": "array",
|
|
256
343
|
"items": {
|
|
@@ -579,6 +666,28 @@
|
|
|
579
666
|
}
|
|
580
667
|
]
|
|
581
668
|
},
|
|
669
|
+
"maxEventLoopDelay": {
|
|
670
|
+
"anyOf": [
|
|
671
|
+
{
|
|
672
|
+
"type": "number",
|
|
673
|
+
"minimum": 0
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
"type": "string"
|
|
677
|
+
}
|
|
678
|
+
]
|
|
679
|
+
},
|
|
680
|
+
"maxEventLoopDelayP99": {
|
|
681
|
+
"anyOf": [
|
|
682
|
+
{
|
|
683
|
+
"type": "number",
|
|
684
|
+
"minimum": 0
|
|
685
|
+
},
|
|
686
|
+
{
|
|
687
|
+
"type": "string"
|
|
688
|
+
}
|
|
689
|
+
]
|
|
690
|
+
},
|
|
582
691
|
"maxHeapUsed": {
|
|
583
692
|
"anyOf": [
|
|
584
693
|
{
|
|
@@ -649,6 +758,18 @@
|
|
|
649
758
|
},
|
|
650
759
|
"additionalProperties": false
|
|
651
760
|
},
|
|
761
|
+
"restartOnError": {
|
|
762
|
+
"description": "Overrides the runtime-level restartOnError for this application. Set to false or 0 to never restart the application when it crashes, a positive number to wait that amount of milliseconds between restarts, or true to use the default delay.",
|
|
763
|
+
"anyOf": [
|
|
764
|
+
{
|
|
765
|
+
"type": "boolean"
|
|
766
|
+
},
|
|
767
|
+
{
|
|
768
|
+
"type": "number",
|
|
769
|
+
"minimum": 0
|
|
770
|
+
}
|
|
771
|
+
]
|
|
772
|
+
},
|
|
652
773
|
"dependencies": {
|
|
653
774
|
"type": "array",
|
|
654
775
|
"items": {
|
|
@@ -975,6 +1096,28 @@
|
|
|
975
1096
|
}
|
|
976
1097
|
]
|
|
977
1098
|
},
|
|
1099
|
+
"maxEventLoopDelay": {
|
|
1100
|
+
"anyOf": [
|
|
1101
|
+
{
|
|
1102
|
+
"type": "number",
|
|
1103
|
+
"minimum": 0
|
|
1104
|
+
},
|
|
1105
|
+
{
|
|
1106
|
+
"type": "string"
|
|
1107
|
+
}
|
|
1108
|
+
]
|
|
1109
|
+
},
|
|
1110
|
+
"maxEventLoopDelayP99": {
|
|
1111
|
+
"anyOf": [
|
|
1112
|
+
{
|
|
1113
|
+
"type": "number",
|
|
1114
|
+
"minimum": 0
|
|
1115
|
+
},
|
|
1116
|
+
{
|
|
1117
|
+
"type": "string"
|
|
1118
|
+
}
|
|
1119
|
+
]
|
|
1120
|
+
},
|
|
978
1121
|
"maxHeapUsed": {
|
|
979
1122
|
"anyOf": [
|
|
980
1123
|
{
|
|
@@ -1045,6 +1188,18 @@
|
|
|
1045
1188
|
},
|
|
1046
1189
|
"additionalProperties": false
|
|
1047
1190
|
},
|
|
1191
|
+
"restartOnError": {
|
|
1192
|
+
"description": "Overrides the runtime-level restartOnError for this application. Set to false or 0 to never restart the application when it crashes, a positive number to wait that amount of milliseconds between restarts, or true to use the default delay.",
|
|
1193
|
+
"anyOf": [
|
|
1194
|
+
{
|
|
1195
|
+
"type": "boolean"
|
|
1196
|
+
},
|
|
1197
|
+
{
|
|
1198
|
+
"type": "number",
|
|
1199
|
+
"minimum": 0
|
|
1200
|
+
}
|
|
1201
|
+
]
|
|
1202
|
+
},
|
|
1048
1203
|
"dependencies": {
|
|
1049
1204
|
"type": "array",
|
|
1050
1205
|
"items": {
|
|
@@ -1371,6 +1526,28 @@
|
|
|
1371
1526
|
}
|
|
1372
1527
|
]
|
|
1373
1528
|
},
|
|
1529
|
+
"maxEventLoopDelay": {
|
|
1530
|
+
"anyOf": [
|
|
1531
|
+
{
|
|
1532
|
+
"type": "number",
|
|
1533
|
+
"minimum": 0
|
|
1534
|
+
},
|
|
1535
|
+
{
|
|
1536
|
+
"type": "string"
|
|
1537
|
+
}
|
|
1538
|
+
]
|
|
1539
|
+
},
|
|
1540
|
+
"maxEventLoopDelayP99": {
|
|
1541
|
+
"anyOf": [
|
|
1542
|
+
{
|
|
1543
|
+
"type": "number",
|
|
1544
|
+
"minimum": 0
|
|
1545
|
+
},
|
|
1546
|
+
{
|
|
1547
|
+
"type": "string"
|
|
1548
|
+
}
|
|
1549
|
+
]
|
|
1550
|
+
},
|
|
1374
1551
|
"maxHeapUsed": {
|
|
1375
1552
|
"anyOf": [
|
|
1376
1553
|
{
|
|
@@ -1441,6 +1618,18 @@
|
|
|
1441
1618
|
},
|
|
1442
1619
|
"additionalProperties": false
|
|
1443
1620
|
},
|
|
1621
|
+
"restartOnError": {
|
|
1622
|
+
"description": "Overrides the runtime-level restartOnError for this application. Set to false or 0 to never restart the application when it crashes, a positive number to wait that amount of milliseconds between restarts, or true to use the default delay.",
|
|
1623
|
+
"anyOf": [
|
|
1624
|
+
{
|
|
1625
|
+
"type": "boolean"
|
|
1626
|
+
},
|
|
1627
|
+
{
|
|
1628
|
+
"type": "number",
|
|
1629
|
+
"minimum": 0
|
|
1630
|
+
}
|
|
1631
|
+
]
|
|
1632
|
+
},
|
|
1444
1633
|
"dependencies": {
|
|
1445
1634
|
"type": "array",
|
|
1446
1635
|
"items": {
|
|
@@ -2136,6 +2325,28 @@
|
|
|
2136
2325
|
],
|
|
2137
2326
|
"default": 0.99
|
|
2138
2327
|
},
|
|
2328
|
+
"maxEventLoopDelay": {
|
|
2329
|
+
"anyOf": [
|
|
2330
|
+
{
|
|
2331
|
+
"type": "number",
|
|
2332
|
+
"minimum": 0
|
|
2333
|
+
},
|
|
2334
|
+
{
|
|
2335
|
+
"type": "string"
|
|
2336
|
+
}
|
|
2337
|
+
]
|
|
2338
|
+
},
|
|
2339
|
+
"maxEventLoopDelayP99": {
|
|
2340
|
+
"anyOf": [
|
|
2341
|
+
{
|
|
2342
|
+
"type": "number",
|
|
2343
|
+
"minimum": 0
|
|
2344
|
+
},
|
|
2345
|
+
{
|
|
2346
|
+
"type": "string"
|
|
2347
|
+
}
|
|
2348
|
+
]
|
|
2349
|
+
},
|
|
2139
2350
|
"maxHeapUsed": {
|
|
2140
2351
|
"anyOf": [
|
|
2141
2352
|
{
|