@platformatic/runtime 2.5.4 → 2.5.5-alpha.2
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/worker/app.js +4 -10
- package/lib/worker/default-stackable.js +2 -4
- package/package.json +14 -14
- package/schema.json +1 -1
- package/lib/worker/metrics.js +0 -176
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 HttpsSchemasPlatformaticDevPlatformaticRuntime255Alpha2Json = {
|
|
9
9
|
[k: string]: unknown;
|
|
10
10
|
} & {
|
|
11
11
|
$schema?: string;
|
package/lib/worker/app.js
CHANGED
|
@@ -10,7 +10,6 @@ const debounce = require('debounce')
|
|
|
10
10
|
|
|
11
11
|
const errors = require('../errors')
|
|
12
12
|
const defaultStackable = require('./default-stackable')
|
|
13
|
-
const { collectMetrics } = require('./metrics')
|
|
14
13
|
const { getServiceUrl, loadConfig, loadEmptyConfig } = require('../utils')
|
|
15
14
|
|
|
16
15
|
class PlatformaticApp extends EventEmitter {
|
|
@@ -19,7 +18,6 @@ class PlatformaticApp extends EventEmitter {
|
|
|
19
18
|
#listening
|
|
20
19
|
#watch
|
|
21
20
|
#fileWatcher
|
|
22
|
-
#metricsRegistry
|
|
23
21
|
#debouncedRestart
|
|
24
22
|
#context
|
|
25
23
|
|
|
@@ -32,7 +30,6 @@ class PlatformaticApp extends EventEmitter {
|
|
|
32
30
|
this.#listening = false
|
|
33
31
|
this.stackable = null
|
|
34
32
|
this.#fileWatcher = null
|
|
35
|
-
this.#metricsRegistry = null
|
|
36
33
|
|
|
37
34
|
this.#context = {
|
|
38
35
|
serviceId: this.appConfig.id,
|
|
@@ -114,10 +111,9 @@ class PlatformaticApp extends EventEmitter {
|
|
|
114
111
|
})
|
|
115
112
|
this.stackable = this.#wrapStackable(stackable)
|
|
116
113
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
114
|
+
this.once('start', () => {
|
|
115
|
+
this.stackable.collectMetrics()
|
|
116
|
+
})
|
|
121
117
|
|
|
122
118
|
this.#updateDispatcher()
|
|
123
119
|
} catch (err) {
|
|
@@ -196,9 +192,7 @@ class PlatformaticApp extends EventEmitter {
|
|
|
196
192
|
}
|
|
197
193
|
|
|
198
194
|
async getMetrics ({ format }) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
return format === 'json' ? this.#metricsRegistry.getMetricsAsJSON() : this.#metricsRegistry.metrics()
|
|
195
|
+
return this.stackable.getMetrics({ format })
|
|
202
196
|
}
|
|
203
197
|
|
|
204
198
|
#fetchServiceUrl (key, { parent, context: service }) {
|
|
@@ -16,10 +16,8 @@ const defaultStackable = {
|
|
|
16
16
|
getOpenapiSchema: () => null,
|
|
17
17
|
getGraphqlSchema: () => null,
|
|
18
18
|
getMeta: () => ({}),
|
|
19
|
-
collectMetrics: () =>
|
|
20
|
-
|
|
21
|
-
httpMetrics: true
|
|
22
|
-
}),
|
|
19
|
+
collectMetrics: () => {},
|
|
20
|
+
getMetrics: () => null,
|
|
23
21
|
inject: () => {
|
|
24
22
|
throw new Error('Stackable inject not implemented')
|
|
25
23
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/runtime",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.5-alpha.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -34,17 +34,17 @@
|
|
|
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/
|
|
39
|
-
"@platformatic/
|
|
40
|
-
"@platformatic/sql-
|
|
41
|
-
"@platformatic/sql-
|
|
37
|
+
"@platformatic/composer": "2.5.5-alpha.2",
|
|
38
|
+
"@platformatic/db": "2.5.5-alpha.2",
|
|
39
|
+
"@platformatic/service": "2.5.5-alpha.2",
|
|
40
|
+
"@platformatic/sql-mapper": "2.5.5-alpha.2",
|
|
41
|
+
"@platformatic/sql-graphql": "2.5.5-alpha.2"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@fastify/error": "^4.0.0",
|
|
45
45
|
"@fastify/websocket": "^11.0.0",
|
|
46
46
|
"@hapi/topo": "^6.0.2",
|
|
47
|
-
"@platformatic/http-metrics": "^0.2.
|
|
47
|
+
"@platformatic/http-metrics": "^0.2.1",
|
|
48
48
|
"@watchable/unpromise": "^1.0.2",
|
|
49
49
|
"boring-name-generator": "^1.0.3",
|
|
50
50
|
"change-case-all": "^2.1.0",
|
|
@@ -69,13 +69,13 @@
|
|
|
69
69
|
"undici": "^6.9.0",
|
|
70
70
|
"undici-thread-interceptor": "^0.7.0",
|
|
71
71
|
"ws": "^8.16.0",
|
|
72
|
-
"@platformatic/basic": "2.5.
|
|
73
|
-
"@platformatic/
|
|
74
|
-
"@platformatic/
|
|
75
|
-
"@platformatic/
|
|
76
|
-
"@platformatic/
|
|
77
|
-
"@platformatic/ts-compiler": "2.5.
|
|
78
|
-
"@platformatic/utils": "2.5.
|
|
72
|
+
"@platformatic/basic": "2.5.5-alpha.2",
|
|
73
|
+
"@platformatic/config": "2.5.5-alpha.2",
|
|
74
|
+
"@platformatic/generators": "2.5.5-alpha.2",
|
|
75
|
+
"@platformatic/itc": "2.5.5-alpha.2",
|
|
76
|
+
"@platformatic/telemetry": "2.5.5-alpha.2",
|
|
77
|
+
"@platformatic/ts-compiler": "2.5.5-alpha.2",
|
|
78
|
+
"@platformatic/utils": "2.5.5-alpha.2"
|
|
79
79
|
},
|
|
80
80
|
"scripts": {
|
|
81
81
|
"test": "npm run lint && borp --concurrency=1 --timeout=180000 && tsd",
|
package/schema.json
CHANGED
package/lib/worker/metrics.js
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const os = require('node:os')
|
|
4
|
-
const { eventLoopUtilization } = require('node:perf_hooks').performance
|
|
5
|
-
const { Registry, Gauge, Counter, collectDefaultMetrics } = require('prom-client')
|
|
6
|
-
const collectHttpMetrics = require('@platformatic/http-metrics')
|
|
7
|
-
|
|
8
|
-
async function collectMetrics (stackable, serviceId, opts = {}) {
|
|
9
|
-
const registry = new Registry()
|
|
10
|
-
|
|
11
|
-
const httpRequestCallbacks = []
|
|
12
|
-
const httpResponseCallbacks = []
|
|
13
|
-
|
|
14
|
-
const metricsConfig = await stackable.collectMetrics({
|
|
15
|
-
registry,
|
|
16
|
-
startHttpTimer: options => httpRequestCallbacks.forEach(cb => cb(options)),
|
|
17
|
-
endHttpTimer: options => httpResponseCallbacks.forEach(cb => cb(options))
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
const labels = opts.labels ?? {}
|
|
21
|
-
registry.setDefaultLabels({ ...labels, serviceId })
|
|
22
|
-
|
|
23
|
-
if (metricsConfig.defaultMetrics) {
|
|
24
|
-
collectDefaultMetrics({ register: registry })
|
|
25
|
-
collectEluMetric(registry)
|
|
26
|
-
await collectThreadCpuMetrics(registry)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (metricsConfig.httpMetrics) {
|
|
30
|
-
{
|
|
31
|
-
const { startTimer, endTimer } = collectHttpMetrics(registry, {
|
|
32
|
-
customLabels: ['telemetry_id'],
|
|
33
|
-
getCustomLabels: req => {
|
|
34
|
-
const telemetryId = req.headers?.['x-plt-telemetry-id'] ?? 'unknown'
|
|
35
|
-
return { telemetry_id: telemetryId }
|
|
36
|
-
}
|
|
37
|
-
})
|
|
38
|
-
httpRequestCallbacks.push(startTimer)
|
|
39
|
-
httpResponseCallbacks.push(endTimer)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
{
|
|
43
|
-
// TODO: check if it's a nodejs environment
|
|
44
|
-
// Needed for the Meraki metrics
|
|
45
|
-
const { startTimer, endTimer } = collectHttpMetrics(registry, {
|
|
46
|
-
customLabels: ['telemetry_id'],
|
|
47
|
-
getCustomLabels: req => {
|
|
48
|
-
const telemetryId = req.headers?.['x-plt-telemetry-id'] ?? 'unknown'
|
|
49
|
-
return { telemetry_id: telemetryId }
|
|
50
|
-
},
|
|
51
|
-
histogram: {
|
|
52
|
-
name: 'http_request_all_duration_seconds',
|
|
53
|
-
help: 'request duration in seconds summary for all requests',
|
|
54
|
-
collect: function () {
|
|
55
|
-
process.nextTick(() => this.reset())
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
summary: {
|
|
59
|
-
name: 'http_request_all_summary_seconds',
|
|
60
|
-
help: 'request duration in seconds histogram for all requests',
|
|
61
|
-
collect: function () {
|
|
62
|
-
process.nextTick(() => this.reset())
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
})
|
|
66
|
-
httpRequestCallbacks.push(startTimer)
|
|
67
|
-
httpResponseCallbacks.push(endTimer)
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return registry
|
|
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
|
-
|
|
127
|
-
function collectEluMetric (register) {
|
|
128
|
-
let startELU = eventLoopUtilization()
|
|
129
|
-
const eluMetric = new Gauge({
|
|
130
|
-
name: 'nodejs_eventloop_utilization',
|
|
131
|
-
help: 'The event loop utilization as a fraction of the loop time. 1 is fully utilized, 0 is fully idle.',
|
|
132
|
-
collect: () => {
|
|
133
|
-
const endELU = eventLoopUtilization()
|
|
134
|
-
const result = eventLoopUtilization(endELU, startELU).utilization
|
|
135
|
-
eluMetric.set(result)
|
|
136
|
-
startELU = endELU
|
|
137
|
-
},
|
|
138
|
-
registers: [register]
|
|
139
|
-
})
|
|
140
|
-
register.registerMetric(eluMetric)
|
|
141
|
-
|
|
142
|
-
let previousIdleTime = 0
|
|
143
|
-
let previousTotalTime = 0
|
|
144
|
-
const cpuMetric = new Gauge({
|
|
145
|
-
name: 'process_cpu_percent_usage',
|
|
146
|
-
help: 'The process CPU percent usage.',
|
|
147
|
-
collect: () => {
|
|
148
|
-
const cpus = os.cpus()
|
|
149
|
-
let idleTime = 0
|
|
150
|
-
let totalTime = 0
|
|
151
|
-
|
|
152
|
-
cpus.forEach(cpu => {
|
|
153
|
-
for (const type in cpu.times) {
|
|
154
|
-
totalTime += cpu.times[type]
|
|
155
|
-
if (type === 'idle') {
|
|
156
|
-
idleTime += cpu.times[type]
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
})
|
|
160
|
-
|
|
161
|
-
const idleDiff = idleTime - previousIdleTime
|
|
162
|
-
const totalDiff = totalTime - previousTotalTime
|
|
163
|
-
|
|
164
|
-
const usagePercent = 100 - (100 * idleDiff) / totalDiff
|
|
165
|
-
const roundedUsage = Math.round(usagePercent * 100) / 100
|
|
166
|
-
cpuMetric.set(roundedUsage)
|
|
167
|
-
|
|
168
|
-
previousIdleTime = idleTime
|
|
169
|
-
previousTotalTime = totalTime
|
|
170
|
-
},
|
|
171
|
-
registers: [register]
|
|
172
|
-
})
|
|
173
|
-
register.registerMetric(cpuMetric)
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
module.exports = { collectMetrics }
|