@platformatic/runtime 2.62.1 → 2.63.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 +9 -1
- package/lib/errors.js +1 -0
- package/lib/logger.js +9 -1
- package/lib/prom-server.js +77 -17
- package/lib/runtime.js +15 -0
- package/lib/worker/default-stackable.js +1 -0
- package/lib/worker/itc.js +8 -0
- package/lib/worker/main.js +15 -2
- package/package.json +15 -15
- package/schema.json +41 -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 HttpsSchemasPlatformaticDevPlatformaticRuntime2631Json = {
|
|
9
9
|
[k: string]: unknown;
|
|
10
10
|
} & {
|
|
11
11
|
$schema?: string;
|
|
@@ -77,6 +77,14 @@ export type HttpsSchemasPlatformaticDevPlatformaticRuntime2621Json = {
|
|
|
77
77
|
[k: string]: unknown;
|
|
78
78
|
};
|
|
79
79
|
};
|
|
80
|
+
formatters?: {
|
|
81
|
+
path: string;
|
|
82
|
+
};
|
|
83
|
+
timestamp?: "epochTime" | "unixTime" | "nullTime" | "isoTime";
|
|
84
|
+
redact?: {
|
|
85
|
+
paths: string[];
|
|
86
|
+
censor?: string;
|
|
87
|
+
};
|
|
80
88
|
[k: string]: unknown;
|
|
81
89
|
};
|
|
82
90
|
server?: {
|
package/lib/errors.js
CHANGED
|
@@ -21,6 +21,7 @@ module.exports = {
|
|
|
21
21
|
FailedToRetrieveMetricsError: createError(`${ERROR_PREFIX}_FAILED_TO_RETRIEVE_METRICS`, 'Failed to retrieve metrics for service with id "%s": %s'),
|
|
22
22
|
FailedToRetrieveHealthError: createError(`${ERROR_PREFIX}_FAILED_TO_RETRIEVE_HEALTH`, 'Failed to retrieve health for service with id "%s": %s'),
|
|
23
23
|
FailedToPerformCustomHealthCheckError: createError(`${ERROR_PREFIX}_FAILED_TO_PERFORM_CUSTOM_HEALTH_CHECK`, 'Failed to perform custom healthcheck for service with id "%s": %s'),
|
|
24
|
+
FailedToPerformCustomReadinessCheckError: createError(`${ERROR_PREFIX}_FAILED_TO_PERFORM_CUSTOM_READINESS_CHECK`, 'Failed to perform custom readiness check for service with id "%s": %s'),
|
|
24
25
|
ApplicationAlreadyStartedError: createError(`${ERROR_PREFIX}_APPLICATION_ALREADY_STARTED`, 'Application is already started'),
|
|
25
26
|
ApplicationNotStartedError: createError(`${ERROR_PREFIX}_APPLICATION_NOT_STARTED`, 'Application has not been started'),
|
|
26
27
|
ConfigPathMustBeStringError: createError(`${ERROR_PREFIX}_CONFIG_PATH_MUST_BE_STRING`, 'Config path must be a string'),
|
package/lib/logger.js
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
const { once } = require('node:events')
|
|
4
4
|
const { join } = require('node:path')
|
|
5
5
|
const { isatty } = require('node:tty')
|
|
6
|
-
|
|
7
6
|
const pino = require('pino')
|
|
8
7
|
const pretty = require('pino-pretty')
|
|
8
|
+
const { buildPinoFormatters, buildPinoTimestamp } = require('@platformatic/utils')
|
|
9
9
|
|
|
10
10
|
const customPrettifiers = {
|
|
11
11
|
name (name, _, obj) {
|
|
@@ -18,6 +18,7 @@ const customPrettifiers = {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
// Create the runtime logger
|
|
21
22
|
async function createLogger (config, runtimeLogsDir) {
|
|
22
23
|
const loggerConfig = { ...config.logger }
|
|
23
24
|
|
|
@@ -28,6 +29,13 @@ async function createLogger (config, runtimeLogsDir) {
|
|
|
28
29
|
? pretty({ customPrettifiers })
|
|
29
30
|
: pino.destination(1)
|
|
30
31
|
|
|
32
|
+
if (loggerConfig.formatters) {
|
|
33
|
+
loggerConfig.formatters = buildPinoFormatters(loggerConfig.formatters)
|
|
34
|
+
}
|
|
35
|
+
if (loggerConfig.timestamp) {
|
|
36
|
+
loggerConfig.timestamp = buildPinoTimestamp(loggerConfig.timestamp)
|
|
37
|
+
}
|
|
38
|
+
|
|
31
39
|
if (!config.managementApi) {
|
|
32
40
|
return [pino(loggerConfig, cliStream), cliStream]
|
|
33
41
|
}
|
package/lib/prom-server.js
CHANGED
|
@@ -19,22 +19,52 @@ const DEFAULT_LIVENESS_FAIL_BODY = 'ERR'
|
|
|
19
19
|
async function checkReadiness (runtime) {
|
|
20
20
|
const workers = await runtime.getWorkers()
|
|
21
21
|
|
|
22
|
+
// check if all workers are started
|
|
22
23
|
for (const worker of Object.values(workers)) {
|
|
23
24
|
if (worker.status !== 'started') {
|
|
24
|
-
return false
|
|
25
|
+
return { status: false }
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
|
-
|
|
28
|
+
|
|
29
|
+
// perform custom readiness checks, get custom response content if any
|
|
30
|
+
const checks = await runtime.getCustomReadinessChecks()
|
|
31
|
+
|
|
32
|
+
let response
|
|
33
|
+
const status = Object.values(checks).every(check => {
|
|
34
|
+
if (typeof check === 'boolean') {
|
|
35
|
+
return check
|
|
36
|
+
} else if (typeof check === 'object') {
|
|
37
|
+
response = check
|
|
38
|
+
return check.status
|
|
39
|
+
}
|
|
40
|
+
return false
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
return { response, status }
|
|
28
44
|
}
|
|
29
45
|
|
|
30
46
|
async function checkLiveness (runtime) {
|
|
31
|
-
|
|
32
|
-
|
|
47
|
+
const { status: ready, response: readinessResponse } = await checkReadiness(runtime)
|
|
48
|
+
if (!ready) {
|
|
49
|
+
return { status: false, readiness: readinessResponse }
|
|
33
50
|
}
|
|
51
|
+
// TODO test, doc
|
|
52
|
+
// in case of readiness check failure, if custom readiness response is set, we return the readiness check response on health check endpoint
|
|
34
53
|
|
|
35
54
|
const checks = await runtime.getCustomHealthChecks()
|
|
36
55
|
|
|
37
|
-
|
|
56
|
+
let response
|
|
57
|
+
const status = Object.values(checks).every(check => {
|
|
58
|
+
if (typeof check === 'boolean') {
|
|
59
|
+
return check
|
|
60
|
+
} else if (typeof check === 'object') {
|
|
61
|
+
response = check
|
|
62
|
+
return check.status
|
|
63
|
+
}
|
|
64
|
+
return false
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
return { response, status }
|
|
38
68
|
}
|
|
39
69
|
|
|
40
70
|
async function startPrometheusServer (runtime, opts) {
|
|
@@ -88,12 +118,27 @@ async function startPrometheusServer (runtime, opts) {
|
|
|
88
118
|
handler: async (req, reply) => {
|
|
89
119
|
reply.type('text/plain')
|
|
90
120
|
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
if (
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
121
|
+
const { status, response } = await checkReadiness(runtime)
|
|
122
|
+
|
|
123
|
+
if (typeof response === 'boolean') {
|
|
124
|
+
if (status) {
|
|
125
|
+
reply.status(successStatusCode).send(successBody)
|
|
126
|
+
} else {
|
|
127
|
+
reply.status(failStatusCode).send(failBody)
|
|
128
|
+
}
|
|
129
|
+
} else if (typeof response === 'object') {
|
|
130
|
+
const { status, body, statusCode } = response
|
|
131
|
+
if (status) {
|
|
132
|
+
reply.status(statusCode || successStatusCode).send(body || successBody)
|
|
133
|
+
} else {
|
|
134
|
+
reply.status(statusCode || failStatusCode).send(body || failBody)
|
|
135
|
+
}
|
|
136
|
+
} else if (!response) {
|
|
137
|
+
if (status) {
|
|
138
|
+
reply.status(successStatusCode).send(successBody)
|
|
139
|
+
} else {
|
|
140
|
+
reply.status(failStatusCode).send(failBody)
|
|
141
|
+
}
|
|
97
142
|
}
|
|
98
143
|
},
|
|
99
144
|
})
|
|
@@ -112,12 +157,27 @@ async function startPrometheusServer (runtime, opts) {
|
|
|
112
157
|
handler: async (req, reply) => {
|
|
113
158
|
reply.type('text/plain')
|
|
114
159
|
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
if (
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
160
|
+
const { status, response, readiness } = await checkLiveness(runtime)
|
|
161
|
+
|
|
162
|
+
if (typeof response === 'boolean') {
|
|
163
|
+
if (status) {
|
|
164
|
+
reply.status(successStatusCode).send(successBody)
|
|
165
|
+
} else {
|
|
166
|
+
reply.status(failStatusCode).send(readiness?.body || failBody)
|
|
167
|
+
}
|
|
168
|
+
} else if (typeof response === 'object') {
|
|
169
|
+
const { status, body, statusCode } = response
|
|
170
|
+
if (status) {
|
|
171
|
+
reply.status(statusCode || successStatusCode).send(body || successBody)
|
|
172
|
+
} else {
|
|
173
|
+
reply.status(statusCode || failStatusCode).send(body || readiness?.body || failBody)
|
|
174
|
+
}
|
|
175
|
+
} else if (!response) {
|
|
176
|
+
if (status) {
|
|
177
|
+
reply.status(successStatusCode).send(successBody)
|
|
178
|
+
} else {
|
|
179
|
+
reply.status(failStatusCode).send(readiness?.body || failBody)
|
|
180
|
+
}
|
|
121
181
|
}
|
|
122
182
|
},
|
|
123
183
|
})
|
package/lib/runtime.js
CHANGED
|
@@ -672,6 +672,21 @@ class Runtime extends EventEmitter {
|
|
|
672
672
|
return status
|
|
673
673
|
}
|
|
674
674
|
|
|
675
|
+
async getCustomReadinessChecks () {
|
|
676
|
+
const status = {}
|
|
677
|
+
|
|
678
|
+
for (const [service, { count }] of Object.entries(this.#workers.configuration)) {
|
|
679
|
+
for (let i = 0; i < count; i++) {
|
|
680
|
+
const label = `${service}:${i}`
|
|
681
|
+
const worker = this.#workers.get(label)
|
|
682
|
+
|
|
683
|
+
status[label] = await sendViaITC(worker, 'getCustomReadinessCheck')
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
return status
|
|
688
|
+
}
|
|
689
|
+
|
|
675
690
|
async getServiceDetails (id, allowUnloaded = false) {
|
|
676
691
|
let service
|
|
677
692
|
|
package/lib/worker/itc.js
CHANGED
|
@@ -174,6 +174,14 @@ function setupITC (app, service, dispatcher) {
|
|
|
174
174
|
} catch (err) {
|
|
175
175
|
throw new errors.FailedToPerformCustomHealthCheckError(service.id, err.message)
|
|
176
176
|
}
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
async getCustomReadinessCheck () {
|
|
180
|
+
try {
|
|
181
|
+
return await app.stackable.getCustomReadinessCheck()
|
|
182
|
+
} catch (err) {
|
|
183
|
+
throw new errors.FailedToPerformCustomReadinessCheckError(service.id, err.message)
|
|
184
|
+
}
|
|
177
185
|
}
|
|
178
186
|
}
|
|
179
187
|
})
|
package/lib/worker/main.js
CHANGED
|
@@ -16,7 +16,9 @@ const {
|
|
|
16
16
|
ensureFlushedWorkerStdio,
|
|
17
17
|
executeWithTimeout,
|
|
18
18
|
ensureLoggableError,
|
|
19
|
-
getPrivateSymbol
|
|
19
|
+
getPrivateSymbol,
|
|
20
|
+
buildPinoFormatters,
|
|
21
|
+
buildPinoTimestamp
|
|
20
22
|
} = require('@platformatic/utils')
|
|
21
23
|
const dotenv = require('dotenv')
|
|
22
24
|
const pino = require('pino')
|
|
@@ -69,12 +71,23 @@ function patchLogging () {
|
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
function createLogger () {
|
|
72
|
-
const pinoOptions = {
|
|
74
|
+
const pinoOptions = {
|
|
75
|
+
level: 'trace',
|
|
76
|
+
name: workerData.serviceConfig.id,
|
|
77
|
+
...workerData.config.logger
|
|
78
|
+
}
|
|
73
79
|
|
|
74
80
|
if (workerData.worker?.count > 1) {
|
|
75
81
|
pinoOptions.base = { pid: process.pid, hostname: hostname(), worker: workerData.worker.index }
|
|
76
82
|
}
|
|
77
83
|
|
|
84
|
+
if (pinoOptions.formatters) {
|
|
85
|
+
pinoOptions.formatters = buildPinoFormatters(pinoOptions.formatters)
|
|
86
|
+
}
|
|
87
|
+
if (pinoOptions.timestamp) {
|
|
88
|
+
pinoOptions.timestamp = buildPinoTimestamp(pinoOptions.timestamp)
|
|
89
|
+
}
|
|
90
|
+
|
|
78
91
|
return pino(pinoOptions)
|
|
79
92
|
}
|
|
80
93
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/runtime",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.63.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"@fastify/express": "^4.0.0",
|
|
22
22
|
"@fastify/formbody": "^8.0.0",
|
|
23
23
|
"autocannon": "^8.0.0",
|
|
24
|
-
"borp": "^0.
|
|
24
|
+
"borp": "^0.20.0",
|
|
25
25
|
"c8": "^10.0.0",
|
|
26
26
|
"eslint": "9",
|
|
27
27
|
"execa": "^9.0.0",
|
|
@@ -37,12 +37,12 @@
|
|
|
37
37
|
"typescript": "^5.5.4",
|
|
38
38
|
"undici-oidc-interceptor": "^0.5.0",
|
|
39
39
|
"why-is-node-running": "^2.2.2",
|
|
40
|
-
"@platformatic/composer": "2.
|
|
41
|
-
"@platformatic/db": "2.
|
|
42
|
-
"@platformatic/node": "2.
|
|
43
|
-
"@platformatic/service": "2.
|
|
44
|
-
"@platformatic/sql-graphql": "2.
|
|
45
|
-
"@platformatic/sql-mapper": "2.
|
|
40
|
+
"@platformatic/composer": "2.63.1",
|
|
41
|
+
"@platformatic/db": "2.63.1",
|
|
42
|
+
"@platformatic/node": "2.63.1",
|
|
43
|
+
"@platformatic/service": "2.63.1",
|
|
44
|
+
"@platformatic/sql-graphql": "2.63.1",
|
|
45
|
+
"@platformatic/sql-mapper": "2.63.1"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@fastify/accepts": "^5.0.0",
|
|
@@ -76,13 +76,13 @@
|
|
|
76
76
|
"undici": "^7.0.0",
|
|
77
77
|
"undici-thread-interceptor": "^0.13.1",
|
|
78
78
|
"ws": "^8.16.0",
|
|
79
|
-
"@platformatic/basic": "2.
|
|
80
|
-
"@platformatic/config": "2.
|
|
81
|
-
"@platformatic/generators": "2.
|
|
82
|
-
"@platformatic/itc": "2.
|
|
83
|
-
"@platformatic/
|
|
84
|
-
"@platformatic/utils": "2.
|
|
85
|
-
"@platformatic/
|
|
79
|
+
"@platformatic/basic": "2.63.1",
|
|
80
|
+
"@platformatic/config": "2.63.1",
|
|
81
|
+
"@platformatic/generators": "2.63.1",
|
|
82
|
+
"@platformatic/itc": "2.63.1",
|
|
83
|
+
"@platformatic/telemetry": "2.63.1",
|
|
84
|
+
"@platformatic/utils": "2.63.1",
|
|
85
|
+
"@platformatic/ts-compiler": "2.63.1"
|
|
86
86
|
},
|
|
87
87
|
"scripts": {
|
|
88
88
|
"test": "pnpm run lint && borp --concurrency=1 --timeout=300000 && tsd",
|
package/schema.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://schemas.platformatic.dev/@platformatic/runtime/2.
|
|
2
|
+
"$id": "https://schemas.platformatic.dev/@platformatic/runtime/2.63.1.json",
|
|
3
3
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -733,6 +733,46 @@
|
|
|
733
733
|
}
|
|
734
734
|
},
|
|
735
735
|
"additionalProperties": false
|
|
736
|
+
},
|
|
737
|
+
"formatters": {
|
|
738
|
+
"type": "object",
|
|
739
|
+
"properties": {
|
|
740
|
+
"path": {
|
|
741
|
+
"type": "string",
|
|
742
|
+
"resolvePath": true
|
|
743
|
+
}
|
|
744
|
+
},
|
|
745
|
+
"required": [
|
|
746
|
+
"path"
|
|
747
|
+
],
|
|
748
|
+
"additionalProperties": false
|
|
749
|
+
},
|
|
750
|
+
"timestamp": {
|
|
751
|
+
"enum": [
|
|
752
|
+
"epochTime",
|
|
753
|
+
"unixTime",
|
|
754
|
+
"nullTime",
|
|
755
|
+
"isoTime"
|
|
756
|
+
]
|
|
757
|
+
},
|
|
758
|
+
"redact": {
|
|
759
|
+
"type": "object",
|
|
760
|
+
"properties": {
|
|
761
|
+
"paths": {
|
|
762
|
+
"type": "array",
|
|
763
|
+
"items": {
|
|
764
|
+
"type": "string"
|
|
765
|
+
}
|
|
766
|
+
},
|
|
767
|
+
"censor": {
|
|
768
|
+
"type": "string",
|
|
769
|
+
"default": "[redacted]"
|
|
770
|
+
}
|
|
771
|
+
},
|
|
772
|
+
"required": [
|
|
773
|
+
"paths"
|
|
774
|
+
],
|
|
775
|
+
"additionalProperties": false
|
|
736
776
|
}
|
|
737
777
|
},
|
|
738
778
|
"required": [
|