@platformatic/runtime 1.24.0 → 1.26.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/fixtures/configs/monorepo-hotreload.json +5 -0
- package/fixtures/management-api/platformatic.json +4 -0
- package/fixtures/management-api/services/service-1/platformatic.json +0 -8
- package/fixtures/management-api/services/service-2/platformatic.json +0 -4
- package/lib/api.js +0 -2
- package/lib/app.js +5 -3
- package/lib/management-api.js +45 -42
- package/lib/worker.js +31 -18
- package/package.json +11 -10
package/lib/api.js
CHANGED
package/lib/app.js
CHANGED
|
@@ -248,10 +248,12 @@ class PlatformaticApp {
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
#setuplogger (configManager) {
|
|
251
|
-
// Set the logger if not present
|
|
252
251
|
configManager.current.server = configManager.current.server || {}
|
|
253
|
-
const
|
|
254
|
-
|
|
252
|
+
const level = configManager.current.server.logger?.level
|
|
253
|
+
|
|
254
|
+
configManager.current.server.logger = level
|
|
255
|
+
? this.#logger.child({ level })
|
|
256
|
+
: this.#logger
|
|
255
257
|
}
|
|
256
258
|
|
|
257
259
|
#startFileWatching () {
|
package/lib/management-api.js
CHANGED
|
@@ -2,30 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
const { tmpdir, platform } = require('node:os')
|
|
4
4
|
const { join } = require('node:path')
|
|
5
|
-
const {
|
|
5
|
+
const { createReadStream } = require('node:fs')
|
|
6
|
+
const { readFile, readdir, mkdir, unlink } = require('node:fs/promises')
|
|
6
7
|
const fastify = require('fastify')
|
|
7
|
-
const { prettyFactory } = require('pino-pretty')
|
|
8
8
|
const errors = require('./errors')
|
|
9
9
|
const platformaticVersion = require('../package.json').version
|
|
10
10
|
|
|
11
|
-
const PLATFORMATIC_TMP_DIR = join(tmpdir(), 'platformatic', '
|
|
12
|
-
|
|
13
|
-
const pinoLogLevels = {
|
|
14
|
-
fatal: 60,
|
|
15
|
-
error: 50,
|
|
16
|
-
warn: 40,
|
|
17
|
-
info: 30,
|
|
18
|
-
debug: 20,
|
|
19
|
-
trace: 10
|
|
20
|
-
}
|
|
11
|
+
const PLATFORMATIC_TMP_DIR = join(tmpdir(), 'platformatic', 'runtimes')
|
|
12
|
+
const runtimeTmpDir = join(PLATFORMATIC_TMP_DIR, process.pid.toString())
|
|
21
13
|
|
|
22
14
|
async function createManagementApi (configManager, runtimeApiClient, loggingPort) {
|
|
23
|
-
|
|
24
|
-
if (!apiConfig || apiConfig === true) {
|
|
25
|
-
apiConfig = {}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const app = fastify(apiConfig)
|
|
15
|
+
const app = fastify()
|
|
29
16
|
app.log.warn(
|
|
30
17
|
'Runtime Management API is in the experimental stage. ' +
|
|
31
18
|
'The feature is not subject to semantic versioning rules. ' +
|
|
@@ -128,27 +115,10 @@ async function createManagementApi (configManager, runtimeApiClient, loggingPort
|
|
|
128
115
|
.send(res.body)
|
|
129
116
|
})
|
|
130
117
|
|
|
131
|
-
app.get('/logs', { websocket: true }, async (connection, req) => {
|
|
132
|
-
const logLevel = req.query.level || 'info'
|
|
133
|
-
const pretty = req.query.pretty !== 'false'
|
|
134
|
-
const serviceId = req.query.serviceId || null
|
|
135
|
-
|
|
136
|
-
const logLevelNumber = pinoLogLevels[logLevel]
|
|
137
|
-
const prettify = prettyFactory()
|
|
138
|
-
|
|
118
|
+
app.get('/logs/live', { websocket: true }, async (connection, req) => {
|
|
139
119
|
const handler = (message) => {
|
|
140
|
-
for (
|
|
141
|
-
|
|
142
|
-
const parsedLog = JSON.parse(log)
|
|
143
|
-
if (parsedLog.level < logLevelNumber) continue
|
|
144
|
-
if (serviceId && parsedLog.name !== serviceId) continue
|
|
145
|
-
if (pretty) {
|
|
146
|
-
log = prettify(parsedLog)
|
|
147
|
-
}
|
|
148
|
-
connection.socket.send(log)
|
|
149
|
-
} catch (err) {
|
|
150
|
-
console.error('Failed to parse log message: ', log, err)
|
|
151
|
-
}
|
|
120
|
+
for (const log of message.logs) {
|
|
121
|
+
connection.socket.send(log)
|
|
152
122
|
}
|
|
153
123
|
}
|
|
154
124
|
|
|
@@ -163,7 +133,41 @@ async function createManagementApi (configManager, runtimeApiClient, loggingPort
|
|
|
163
133
|
loggingPort.off('message', handler)
|
|
164
134
|
})
|
|
165
135
|
})
|
|
166
|
-
|
|
136
|
+
|
|
137
|
+
app.get('/logs/history', { websocket: true }, async (connection, req) => {
|
|
138
|
+
const runtimeTmpFiles = await readdir(runtimeTmpDir)
|
|
139
|
+
const runtimeLogFiles = runtimeTmpFiles
|
|
140
|
+
.filter((file) => file.startsWith('logs'))
|
|
141
|
+
.map((file) => join(runtimeTmpDir, file))
|
|
142
|
+
.sort()
|
|
143
|
+
|
|
144
|
+
if (runtimeLogFiles.length === 0) {
|
|
145
|
+
connection.end()
|
|
146
|
+
return
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const streamLogFile = (fileIndex) => {
|
|
150
|
+
const file = runtimeLogFiles[fileIndex]
|
|
151
|
+
const isLastFile = fileIndex === runtimeLogFiles.length - 1
|
|
152
|
+
|
|
153
|
+
const stream = createReadStream(file)
|
|
154
|
+
stream.pipe(connection, { end: isLastFile })
|
|
155
|
+
|
|
156
|
+
stream.on('error', (err) => {
|
|
157
|
+
app.log.error(err, 'Error streaming log file')
|
|
158
|
+
connection.end()
|
|
159
|
+
})
|
|
160
|
+
stream.on('end', () => {
|
|
161
|
+
if (isLastFile) {
|
|
162
|
+
connection.end()
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
streamLogFile(fileIndex + 1)
|
|
166
|
+
})
|
|
167
|
+
}
|
|
168
|
+
streamLogFile(0)
|
|
169
|
+
})
|
|
170
|
+
}, { prefix: '/api/v1' })
|
|
167
171
|
|
|
168
172
|
return app
|
|
169
173
|
}
|
|
@@ -175,12 +179,11 @@ async function startManagementApi (configManager, runtimeApiClient, loggingPort)
|
|
|
175
179
|
if (platform() === 'win32') {
|
|
176
180
|
socketPath = '\\\\.\\pipe\\platformatic-' + runtimePID
|
|
177
181
|
} else {
|
|
178
|
-
|
|
179
|
-
socketPath = join(PLATFORMATIC_TMP_DIR, `${runtimePID}.sock`)
|
|
182
|
+
socketPath = join(runtimeTmpDir, 'socket')
|
|
180
183
|
}
|
|
181
184
|
|
|
182
185
|
try {
|
|
183
|
-
await mkdir(
|
|
186
|
+
await mkdir(runtimeTmpDir, { recursive: true })
|
|
184
187
|
await unlink(socketPath).catch((err) => {
|
|
185
188
|
if (err.code !== 'ENOENT') {
|
|
186
189
|
throw new errors.FailedToUnlinkManagementApiSocket(err.message)
|
package/lib/worker.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const inspector = require('node:inspector')
|
|
4
|
+
const { tmpdir } = require('node:os')
|
|
4
5
|
const { register, createRequire } = require('node:module')
|
|
5
6
|
const { isatty } = require('node:tty')
|
|
6
7
|
const { pathToFileURL } = require('node:url')
|
|
@@ -18,6 +19,8 @@ const RuntimeApi = require('./api')
|
|
|
18
19
|
const { MessagePortWritable } = require('./message-port-writable')
|
|
19
20
|
let loaderPort
|
|
20
21
|
|
|
22
|
+
const PLATFORMATIC_TMP_DIR = join(tmpdir(), 'platformatic', 'runtimes')
|
|
23
|
+
|
|
21
24
|
if (typeof register === 'function' && workerData.config.loaderFile) {
|
|
22
25
|
const { port1, port2 } = new MessageChannel()
|
|
23
26
|
register(workerData.config.loaderFile, {
|
|
@@ -34,31 +37,41 @@ globalThis.fetch = undici.fetch
|
|
|
34
37
|
|
|
35
38
|
const config = workerData.config
|
|
36
39
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
loggerConfig = { ...loggerConfig }
|
|
41
|
-
} else {
|
|
42
|
-
loggerConfig = {}
|
|
43
|
-
}
|
|
40
|
+
function createLogger (config) {
|
|
41
|
+
const loggerConfig = { ...config.server?.logger }
|
|
42
|
+
const cliStream = isatty(1) ? pretty() : pino.destination(1)
|
|
44
43
|
|
|
45
|
-
|
|
44
|
+
if (!config.loggingPort && !config.managementApi) {
|
|
45
|
+
return pino(loggerConfig, cliStream)
|
|
46
|
+
}
|
|
46
47
|
|
|
47
|
-
let logger = null
|
|
48
|
-
if (config.loggingPort) {
|
|
49
|
-
const portStream = new MessagePortWritable({
|
|
50
|
-
metadata: config.loggingMetadata,
|
|
51
|
-
port: config.loggingPort
|
|
52
|
-
})
|
|
53
48
|
const multiStream = pino.multistream([
|
|
54
|
-
{ stream: portStream, level: 'trace' },
|
|
55
49
|
{ stream: cliStream, level: loggerConfig.level || 'info' }
|
|
56
50
|
])
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
51
|
+
|
|
52
|
+
if (loggerConfig.transport) {
|
|
53
|
+
const transport = pino.transport(loggerConfig.transport)
|
|
54
|
+
multiStream.add({ level: loggerConfig.level || 'info', stream: transport })
|
|
55
|
+
}
|
|
56
|
+
if (config.loggingPort) {
|
|
57
|
+
const portStream = new MessagePortWritable({
|
|
58
|
+
metadata: config.loggingMetadata,
|
|
59
|
+
port: config.loggingPort
|
|
60
|
+
})
|
|
61
|
+
multiStream.add({ level: 'trace', stream: portStream })
|
|
62
|
+
}
|
|
63
|
+
if (config.managementApi) {
|
|
64
|
+
const logsPath = join(PLATFORMATIC_TMP_DIR, process.pid.toString(), 'logs')
|
|
65
|
+
const pinoRoll = pino.transport({
|
|
66
|
+
target: 'pino-roll',
|
|
67
|
+
options: { file: logsPath, size: '5m', mkdir: true }
|
|
68
|
+
})
|
|
69
|
+
multiStream.add({ level: 'trace', stream: pinoRoll })
|
|
70
|
+
}
|
|
71
|
+
return pino({ level: 'trace' }, multiStream)
|
|
60
72
|
}
|
|
61
73
|
|
|
74
|
+
const logger = createLogger(config)
|
|
62
75
|
if (config.server) {
|
|
63
76
|
config.server.logger = logger
|
|
64
77
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/runtime",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.26.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"typescript": "^5.3.3",
|
|
33
33
|
"undici-oauth-interceptor": "^0.4.2",
|
|
34
34
|
"ws": "^8.16.0",
|
|
35
|
-
"@platformatic/sql-graphql": "1.
|
|
36
|
-
"@platformatic/sql-mapper": "1.
|
|
35
|
+
"@platformatic/sql-graphql": "1.26.0",
|
|
36
|
+
"@platformatic/sql-mapper": "1.26.0"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@fastify/error": "^3.4.1",
|
|
@@ -53,15 +53,16 @@
|
|
|
53
53
|
"minimist": "^1.2.8",
|
|
54
54
|
"pino": "^8.17.2",
|
|
55
55
|
"pino-pretty": "^10.3.1",
|
|
56
|
+
"pino-roll": "1.0.0-rc.1",
|
|
56
57
|
"undici": "^6.6.0",
|
|
57
58
|
"why-is-node-running": "^2.2.2",
|
|
58
|
-
"@platformatic/composer": "1.
|
|
59
|
-
"@platformatic/config": "1.
|
|
60
|
-
"@platformatic/
|
|
61
|
-
"@platformatic/
|
|
62
|
-
"@platformatic/service": "1.
|
|
63
|
-
"@platformatic/
|
|
64
|
-
"@platformatic/
|
|
59
|
+
"@platformatic/composer": "1.26.0",
|
|
60
|
+
"@platformatic/config": "1.26.0",
|
|
61
|
+
"@platformatic/generators": "1.26.0",
|
|
62
|
+
"@platformatic/db": "1.26.0",
|
|
63
|
+
"@platformatic/service": "1.26.0",
|
|
64
|
+
"@platformatic/utils": "1.26.0",
|
|
65
|
+
"@platformatic/telemetry": "1.26.0"
|
|
65
66
|
},
|
|
66
67
|
"standard": {
|
|
67
68
|
"ignore": [
|