@platformatic/runtime 2.5.2 → 2.5.4
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 +1 -1
- package/lib/config.js +8 -3
- package/lib/runtime.js +3 -0
- package/lib/worker/main.js +3 -1
- package/lib/worker/metrics.js +63 -9
- package/package.json +14 -13
- package/schema.json +1 -1
package/config.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* and run json-schema-to-typescript to regenerate this file.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
export type
|
|
8
|
+
export type HttpsSchemasPlatformaticDevPlatformaticRuntime254Json = {
|
|
9
9
|
[k: string]: unknown;
|
|
10
10
|
} & {
|
|
11
11
|
$schema?: string;
|
package/lib/config.js
CHANGED
|
@@ -140,9 +140,14 @@ async function _transformConfig (configManager, args) {
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
if (!hasValidEntrypoint) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
143
|
+
if (config.entrypoint) {
|
|
144
|
+
throw new errors.InvalidEntrypointError(config.entrypoint)
|
|
145
|
+
} else if (services.length >= 1) {
|
|
146
|
+
throw new errors.MissingEntrypointError()
|
|
147
|
+
}
|
|
148
|
+
// If there are no services, and no entrypoint it's an empty app.
|
|
149
|
+
// It won't start, but we should be able to parse and operate on it,
|
|
150
|
+
// like adding other services.
|
|
146
151
|
}
|
|
147
152
|
|
|
148
153
|
configManager.current.services = services
|
package/lib/runtime.js
CHANGED
|
@@ -127,6 +127,9 @@ class Runtime extends EventEmitter {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
async start () {
|
|
130
|
+
if (typeof this.#configManager.current.entrypoint === 'undefined') {
|
|
131
|
+
throw new errors.MissingEntrypointError()
|
|
132
|
+
}
|
|
130
133
|
this.#updateStatus('starting')
|
|
131
134
|
|
|
132
135
|
// Important: do not use Promise.all here since it won't properly manage dependencies
|
package/lib/worker/main.js
CHANGED
|
@@ -85,7 +85,9 @@ async function main () {
|
|
|
85
85
|
setGlobalDispatcher(globalDispatcher)
|
|
86
86
|
|
|
87
87
|
// Setup mesh networker
|
|
88
|
-
|
|
88
|
+
// The timeout is set to 5 minutes to avoid long term memory leaks
|
|
89
|
+
// TODO: make this configurable
|
|
90
|
+
const threadDispatcher = wire({ port: parentPort, useNetwork: service.useHttp, timeout: 5 * 60 * 1000 })
|
|
89
91
|
|
|
90
92
|
// If the service is an entrypoint and runtime server config is defined, use it.
|
|
91
93
|
let serverConfig = null
|
package/lib/worker/metrics.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const os = require('node:os')
|
|
4
4
|
const { eventLoopUtilization } = require('node:perf_hooks').performance
|
|
5
|
-
const { Registry, Gauge, collectDefaultMetrics } = require('prom-client')
|
|
5
|
+
const { Registry, Gauge, Counter, collectDefaultMetrics } = require('prom-client')
|
|
6
6
|
const collectHttpMetrics = require('@platformatic/http-metrics')
|
|
7
7
|
|
|
8
8
|
async function collectMetrics (stackable, serviceId, opts = {}) {
|
|
@@ -23,13 +23,14 @@ async function collectMetrics (stackable, serviceId, opts = {}) {
|
|
|
23
23
|
if (metricsConfig.defaultMetrics) {
|
|
24
24
|
collectDefaultMetrics({ register: registry })
|
|
25
25
|
collectEluMetric(registry)
|
|
26
|
+
await collectThreadCpuMetrics(registry)
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
if (metricsConfig.httpMetrics) {
|
|
29
30
|
{
|
|
30
31
|
const { startTimer, endTimer } = collectHttpMetrics(registry, {
|
|
31
32
|
customLabels: ['telemetry_id'],
|
|
32
|
-
getCustomLabels:
|
|
33
|
+
getCustomLabels: req => {
|
|
33
34
|
const telemetryId = req.headers?.['x-plt-telemetry-id'] ?? 'unknown'
|
|
34
35
|
return { telemetry_id: telemetryId }
|
|
35
36
|
}
|
|
@@ -43,7 +44,7 @@ async function collectMetrics (stackable, serviceId, opts = {}) {
|
|
|
43
44
|
// Needed for the Meraki metrics
|
|
44
45
|
const { startTimer, endTimer } = collectHttpMetrics(registry, {
|
|
45
46
|
customLabels: ['telemetry_id'],
|
|
46
|
-
getCustomLabels:
|
|
47
|
+
getCustomLabels: req => {
|
|
47
48
|
const telemetryId = req.headers?.['x-plt-telemetry-id'] ?? 'unknown'
|
|
48
49
|
return { telemetry_id: telemetryId }
|
|
49
50
|
},
|
|
@@ -52,15 +53,15 @@ async function collectMetrics (stackable, serviceId, opts = {}) {
|
|
|
52
53
|
help: 'request duration in seconds summary for all requests',
|
|
53
54
|
collect: function () {
|
|
54
55
|
process.nextTick(() => this.reset())
|
|
55
|
-
}
|
|
56
|
+
}
|
|
56
57
|
},
|
|
57
58
|
summary: {
|
|
58
59
|
name: 'http_request_all_summary_seconds',
|
|
59
60
|
help: 'request duration in seconds histogram for all requests',
|
|
60
61
|
collect: function () {
|
|
61
62
|
process.nextTick(() => this.reset())
|
|
62
|
-
}
|
|
63
|
-
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
64
65
|
})
|
|
65
66
|
httpRequestCallbacks.push(startTimer)
|
|
66
67
|
httpResponseCallbacks.push(endTimer)
|
|
@@ -70,6 +71,59 @@ async function collectMetrics (stackable, serviceId, opts = {}) {
|
|
|
70
71
|
return registry
|
|
71
72
|
}
|
|
72
73
|
|
|
74
|
+
async function collectThreadCpuMetrics (registry) {
|
|
75
|
+
// We need until we switch to 22 as thread-cpu-usage is ESM
|
|
76
|
+
const { threadCpuUsage } = await import('thread-cpu-usage')
|
|
77
|
+
|
|
78
|
+
let lastSample = process.hrtime.bigint()
|
|
79
|
+
let lastUsage = threadCpuUsage()
|
|
80
|
+
|
|
81
|
+
const threadCpuUserUsageCounterMetric = new Counter({
|
|
82
|
+
name: 'thread_cpu_user_system_seconds_total',
|
|
83
|
+
help: 'Total user CPU time spent in seconds for the current thread.',
|
|
84
|
+
registers: [registry]
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
const threadCpuSystemUsageCounterMetric = new Counter({
|
|
88
|
+
name: 'thread_cpu_system_seconds_total',
|
|
89
|
+
help: 'Total system CPU time spent in seconds for the current thread.',
|
|
90
|
+
registers: [registry]
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
const threadCpuPercentUsageGaugeMetric = new Gauge({
|
|
94
|
+
name: 'thread_cpu_percent_usage',
|
|
95
|
+
help: 'The thread CPU percent usage.',
|
|
96
|
+
registers: [registry]
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
const threadCpuUsageCounterMetric = new Counter({
|
|
100
|
+
name: 'thread_cpu_seconds_total',
|
|
101
|
+
help: 'Total user and system CPU time spent in seconds for the current threads.',
|
|
102
|
+
// Use this one metric's `collect` to set all metrics' values.
|
|
103
|
+
collect () {
|
|
104
|
+
const newSample = process.hrtime.bigint()
|
|
105
|
+
const newUsage = threadCpuUsage()
|
|
106
|
+
const user = newUsage.user - lastUsage.user
|
|
107
|
+
const system = newUsage.system - lastUsage.system
|
|
108
|
+
const elapsed = Number(newSample - lastSample)
|
|
109
|
+
|
|
110
|
+
lastUsage = newUsage
|
|
111
|
+
lastSample = newSample
|
|
112
|
+
|
|
113
|
+
threadCpuSystemUsageCounterMetric.inc(system / 1e6)
|
|
114
|
+
threadCpuUserUsageCounterMetric.inc(user / 1e6)
|
|
115
|
+
threadCpuUsageCounterMetric.inc((user + system) / 1e6)
|
|
116
|
+
threadCpuPercentUsageGaugeMetric.set((100 * ((user + system) * 1000)) / elapsed)
|
|
117
|
+
},
|
|
118
|
+
registers: [registry]
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
registry.registerMetric(threadCpuUserUsageCounterMetric)
|
|
122
|
+
registry.registerMetric(threadCpuSystemUsageCounterMetric)
|
|
123
|
+
registry.registerMetric(threadCpuUsageCounterMetric)
|
|
124
|
+
registry.registerMetric(threadCpuPercentUsageGaugeMetric)
|
|
125
|
+
}
|
|
126
|
+
|
|
73
127
|
function collectEluMetric (register) {
|
|
74
128
|
let startELU = eventLoopUtilization()
|
|
75
129
|
const eluMetric = new Gauge({
|
|
@@ -81,7 +135,7 @@ function collectEluMetric (register) {
|
|
|
81
135
|
eluMetric.set(result)
|
|
82
136
|
startELU = endELU
|
|
83
137
|
},
|
|
84
|
-
registers: [register]
|
|
138
|
+
registers: [register]
|
|
85
139
|
})
|
|
86
140
|
register.registerMetric(eluMetric)
|
|
87
141
|
|
|
@@ -107,14 +161,14 @@ function collectEluMetric (register) {
|
|
|
107
161
|
const idleDiff = idleTime - previousIdleTime
|
|
108
162
|
const totalDiff = totalTime - previousTotalTime
|
|
109
163
|
|
|
110
|
-
const usagePercent = 100 - (
|
|
164
|
+
const usagePercent = 100 - (100 * idleDiff) / totalDiff
|
|
111
165
|
const roundedUsage = Math.round(usagePercent * 100) / 100
|
|
112
166
|
cpuMetric.set(roundedUsage)
|
|
113
167
|
|
|
114
168
|
previousIdleTime = idleTime
|
|
115
169
|
previousTotalTime = totalTime
|
|
116
170
|
},
|
|
117
|
-
registers: [register]
|
|
171
|
+
registers: [register]
|
|
118
172
|
})
|
|
119
173
|
register.registerMetric(cpuMetric)
|
|
120
174
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/runtime",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
"typescript": "^5.5.4",
|
|
35
35
|
"undici-oidc-interceptor": "^0.5.0",
|
|
36
36
|
"why-is-node-running": "^2.2.2",
|
|
37
|
-
"@platformatic/composer": "2.5.
|
|
38
|
-
"@platformatic/service": "2.5.
|
|
39
|
-
"@platformatic/
|
|
40
|
-
"@platformatic/sql-
|
|
41
|
-
"@platformatic/
|
|
37
|
+
"@platformatic/composer": "2.5.4",
|
|
38
|
+
"@platformatic/service": "2.5.4",
|
|
39
|
+
"@platformatic/db": "2.5.4",
|
|
40
|
+
"@platformatic/sql-graphql": "2.5.4",
|
|
41
|
+
"@platformatic/sql-mapper": "2.5.4"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@fastify/error": "^4.0.0",
|
|
@@ -65,16 +65,17 @@
|
|
|
65
65
|
"prom-client": "^15.1.2",
|
|
66
66
|
"semgrator": "^0.3.0",
|
|
67
67
|
"tail-file-stream": "^0.2.0",
|
|
68
|
+
"thread-cpu-usage": "^0.2.0",
|
|
68
69
|
"undici": "^6.9.0",
|
|
69
70
|
"undici-thread-interceptor": "^0.7.0",
|
|
70
71
|
"ws": "^8.16.0",
|
|
71
|
-
"@platformatic/basic": "2.5.
|
|
72
|
-
"@platformatic/
|
|
73
|
-
"@platformatic/
|
|
74
|
-
"@platformatic/telemetry": "2.5.
|
|
75
|
-
"@platformatic/generators": "2.5.
|
|
76
|
-
"@platformatic/ts-compiler": "2.5.
|
|
77
|
-
"@platformatic/utils": "2.5.
|
|
72
|
+
"@platformatic/basic": "2.5.4",
|
|
73
|
+
"@platformatic/itc": "2.5.4",
|
|
74
|
+
"@platformatic/config": "2.5.4",
|
|
75
|
+
"@platformatic/telemetry": "2.5.4",
|
|
76
|
+
"@platformatic/generators": "2.5.4",
|
|
77
|
+
"@platformatic/ts-compiler": "2.5.4",
|
|
78
|
+
"@platformatic/utils": "2.5.4"
|
|
78
79
|
},
|
|
79
80
|
"scripts": {
|
|
80
81
|
"test": "npm run lint && borp --concurrency=1 --timeout=180000 && tsd",
|
package/schema.json
CHANGED