@platformatic/service 3.4.1 → 3.5.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/LICENSE +1 -1
- package/config.d.ts +450 -94
- package/eslint.config.js +4 -6
- package/index.d.ts +55 -48
- package/index.js +44 -179
- package/lib/application.js +35 -0
- package/lib/capability.js +281 -0
- package/lib/compile.js +2 -52
- package/lib/generator.js +426 -0
- package/lib/plugins/cors.js +5 -8
- package/lib/plugins/graphql.js +16 -14
- package/lib/plugins/health-check.js +6 -8
- package/lib/plugins/openapi.js +43 -32
- package/lib/plugins/plugins.js +6 -53
- package/lib/{root-endpoint/index.js → plugins/root.js} +9 -8
- package/lib/plugins/sandbox-wrapper.js +65 -63
- package/lib/schema.js +1075 -203
- package/lib/upgrade.js +6 -8
- package/lib/utils.js +30 -83
- package/lib/versions/0.16.0.js +14 -15
- package/lib/versions/{from-zero-twenty-eight-to-will-see.js → 0.28.0.js} +3 -6
- package/lib/versions/2.0.0.js +4 -7
- package/lib/versions/3.0.0.js +14 -0
- package/package.json +28 -36
- package/schema.json +1452 -165
- package/tsconfig.json +16 -6
- package/.c8rc +0 -6
- package/help/compile.txt +0 -19
- package/help/create.txt +0 -11
- package/help/help.txt +0 -8
- package/help/schema.txt +0 -9
- package/help/start.txt +0 -23
- package/index.test-d.ts +0 -107
- package/lib/create.mjs +0 -85
- package/lib/gen-schema.js +0 -15
- package/lib/gen-types.mjs +0 -38
- package/lib/generator/README.md +0 -31
- package/lib/generator/service-generator.d.ts +0 -11
- package/lib/generator/service-generator.js +0 -126
- package/lib/openapi-schema-defs.js +0 -1108
- package/lib/plugins/clients.js +0 -16
- package/lib/plugins/metrics.js +0 -244
- package/lib/plugins/typescript.js +0 -20
- package/lib/stackable.js +0 -306
- package/lib/start.js +0 -175
- package/service.mjs +0 -71
- /package/{lib/root-endpoint/public → public}/images/dark_mode.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/favicon.ico +0 -0
- /package/{lib/root-endpoint/public → public}/images/light_mode.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/platformatic-logo-dark.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/platformatic-logo-light.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/triangle_dark.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/triangle_light.svg +0 -0
- /package/{lib/root-endpoint/public → public}/index.html +0 -0
package/lib/plugins/clients.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const fp = require('fastify-plugin')
|
|
4
|
-
const client = require('@platformatic/client')
|
|
5
|
-
|
|
6
|
-
async function setupClients (app, opts) {
|
|
7
|
-
for (const { path, url, serviceId, name, schema, type, fullRequest, fullResponse, validateResponse } of opts) {
|
|
8
|
-
if (path) {
|
|
9
|
-
app.register(require(path), { url, serviceId })
|
|
10
|
-
} else {
|
|
11
|
-
app.register(client, { url, serviceId, name, path: schema, type, fullRequest, fullResponse, validateResponse })
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
module.exports = fp(setupClients)
|
package/lib/plugins/metrics.js
DELETED
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const os = require('node:os')
|
|
4
|
-
const http = require('node:http')
|
|
5
|
-
const { eventLoopUtilization } = require('node:perf_hooks').performance
|
|
6
|
-
const fastify = require('fastify')
|
|
7
|
-
const fp = require('fastify-plugin')
|
|
8
|
-
|
|
9
|
-
const metricsPlugin = fp(async function (app, opts = {}) {
|
|
10
|
-
const promClient = require('prom-client')
|
|
11
|
-
|
|
12
|
-
const register = new promClient.Registry()
|
|
13
|
-
|
|
14
|
-
const defaultMetrics = opts.defaultMetrics ?? { enabled: true }
|
|
15
|
-
|
|
16
|
-
if (opts.labels) {
|
|
17
|
-
const labels = opts.labels ?? {}
|
|
18
|
-
register.setDefaultLabels(labels)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
app.register(require('fastify-metrics'), {
|
|
22
|
-
defaultMetrics: {
|
|
23
|
-
...defaultMetrics,
|
|
24
|
-
register,
|
|
25
|
-
},
|
|
26
|
-
endpoint: null,
|
|
27
|
-
name: 'metrics',
|
|
28
|
-
clearRegisterOnInit: false,
|
|
29
|
-
promClient: {
|
|
30
|
-
...promClient,
|
|
31
|
-
register,
|
|
32
|
-
},
|
|
33
|
-
routeMetrics: {
|
|
34
|
-
enabled: true,
|
|
35
|
-
customLabels: {
|
|
36
|
-
// TODO: check if this is set in prom
|
|
37
|
-
telemetry_id: (req) => req.headers['x-plt-telemetry-id'] ?? 'unknown',
|
|
38
|
-
},
|
|
39
|
-
overrides: {
|
|
40
|
-
histogram: {
|
|
41
|
-
name: 'http_request_duration_seconds',
|
|
42
|
-
registers: [register],
|
|
43
|
-
},
|
|
44
|
-
summary: {
|
|
45
|
-
name: 'http_request_summary_seconds',
|
|
46
|
-
registers: [register],
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
app.register(fp(async (app) => {
|
|
53
|
-
const httpLatencyMetric = new app.metrics.client.Summary({
|
|
54
|
-
name: 'http_request_all_summary_seconds',
|
|
55
|
-
help: 'request duration in seconds summary for all requests',
|
|
56
|
-
collect: () => {
|
|
57
|
-
process.nextTick(() => httpLatencyMetric.reset())
|
|
58
|
-
},
|
|
59
|
-
registers: [register],
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
const ignoredMethods = ['HEAD', 'OPTIONS', 'TRACE', 'CONNECT']
|
|
63
|
-
const timers = new WeakMap()
|
|
64
|
-
app.addHook('onRequest', async (req) => {
|
|
65
|
-
if (ignoredMethods.includes(req.method)) return
|
|
66
|
-
const timer = httpLatencyMetric.startTimer()
|
|
67
|
-
timers.set(req, timer)
|
|
68
|
-
})
|
|
69
|
-
app.addHook('onResponse', async (req) => {
|
|
70
|
-
if (ignoredMethods.includes(req.method)) return
|
|
71
|
-
const timer = timers.get(req)
|
|
72
|
-
if (timer) {
|
|
73
|
-
timer()
|
|
74
|
-
timers.delete(req)
|
|
75
|
-
}
|
|
76
|
-
})
|
|
77
|
-
}, {
|
|
78
|
-
encapsulate: false,
|
|
79
|
-
}))
|
|
80
|
-
|
|
81
|
-
if (defaultMetrics.enabled) {
|
|
82
|
-
app.register(async (app) => {
|
|
83
|
-
let startELU = eventLoopUtilization()
|
|
84
|
-
const eluMetric = new app.metrics.client.Gauge({
|
|
85
|
-
name: 'nodejs_eventloop_utilization',
|
|
86
|
-
help: 'The event loop utilization as a fraction of the loop time. 1 is fully utilized, 0 is fully idle.',
|
|
87
|
-
collect: () => {
|
|
88
|
-
const endELU = eventLoopUtilization()
|
|
89
|
-
const result = eventLoopUtilization(endELU, startELU).utilization
|
|
90
|
-
eluMetric.set(result)
|
|
91
|
-
startELU = endELU
|
|
92
|
-
},
|
|
93
|
-
registers: [register],
|
|
94
|
-
})
|
|
95
|
-
app.metrics.client.register.registerMetric(eluMetric)
|
|
96
|
-
|
|
97
|
-
let previousIdleTime = 0
|
|
98
|
-
let previousTotalTime = 0
|
|
99
|
-
const cpuMetric = new app.metrics.client.Gauge({
|
|
100
|
-
name: 'process_cpu_percent_usage',
|
|
101
|
-
help: 'The process CPU percent usage.',
|
|
102
|
-
collect: () => {
|
|
103
|
-
const cpus = os.cpus()
|
|
104
|
-
let idleTime = 0
|
|
105
|
-
let totalTime = 0
|
|
106
|
-
|
|
107
|
-
cpus.forEach(cpu => {
|
|
108
|
-
for (const type in cpu.times) {
|
|
109
|
-
totalTime += cpu.times[type]
|
|
110
|
-
if (type === 'idle') {
|
|
111
|
-
idleTime += cpu.times[type]
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
const idleDiff = idleTime - previousIdleTime
|
|
117
|
-
const totalDiff = totalTime - previousTotalTime
|
|
118
|
-
|
|
119
|
-
const usagePercent = 100 - ((100 * idleDiff) / totalDiff)
|
|
120
|
-
const roundedUsage = Math.round(usagePercent * 100) / 100
|
|
121
|
-
cpuMetric.set(roundedUsage)
|
|
122
|
-
|
|
123
|
-
previousIdleTime = idleTime
|
|
124
|
-
previousTotalTime = totalTime
|
|
125
|
-
},
|
|
126
|
-
registers: [register],
|
|
127
|
-
})
|
|
128
|
-
app.metrics.client.register.registerMetric(cpuMetric)
|
|
129
|
-
})
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function cleanMetrics () {
|
|
133
|
-
const httpMetrics = ['http_request_duration_seconds', 'http_request_summary_seconds', 'http_request_all_summary_seconds']
|
|
134
|
-
const metrics = app.metrics.client.register._metrics
|
|
135
|
-
for (const metricName in metrics) {
|
|
136
|
-
if (defaultMetrics.enabled || httpMetrics.includes(metricName)) {
|
|
137
|
-
delete metrics[metricName]
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
app.addHook('onClose', async () => {
|
|
143
|
-
cleanMetrics()
|
|
144
|
-
})
|
|
145
|
-
}, {
|
|
146
|
-
encapsulate: false,
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
// This is a global httpServer to match global
|
|
150
|
-
// prometheus. It's an antipattern, so do
|
|
151
|
-
// not use it elsewhere.
|
|
152
|
-
let httpServer = null
|
|
153
|
-
|
|
154
|
-
async function createMetricsServer (app, hostname, port) {
|
|
155
|
-
if (httpServer && httpServer.address().port !== port) {
|
|
156
|
-
await closeMetricsServer()
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (!httpServer) {
|
|
160
|
-
httpServer = http.createServer()
|
|
161
|
-
httpServer.listen(port, hostname)
|
|
162
|
-
httpServer.unref()
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const promServer = fastify({
|
|
166
|
-
name: 'Prometheus server',
|
|
167
|
-
serverFactory: (handler) => {
|
|
168
|
-
httpServer.removeAllListeners('request')
|
|
169
|
-
httpServer.removeAllListeners('clientError')
|
|
170
|
-
httpServer.on('request', handler)
|
|
171
|
-
return httpServer
|
|
172
|
-
},
|
|
173
|
-
loggerInstance: app.log.child({ name: 'prometheus' }),
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
app.addHook('onClose', async () => {
|
|
177
|
-
await promServer.close()
|
|
178
|
-
})
|
|
179
|
-
|
|
180
|
-
return promServer
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
async function closeMetricsServer () {
|
|
184
|
-
if (httpServer) {
|
|
185
|
-
await new Promise((resolve) => httpServer.close(resolve))
|
|
186
|
-
httpServer = null
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
module.exports = fp(async function (app, opts) {
|
|
191
|
-
const server = opts.server ?? 'own'
|
|
192
|
-
const hostname = opts.hostname ?? '0.0.0.0'
|
|
193
|
-
const port = opts.port ?? 9090
|
|
194
|
-
const metricsEndpoint = opts.endpoint ?? '/metrics'
|
|
195
|
-
const auth = opts.auth ?? null
|
|
196
|
-
|
|
197
|
-
app.register(metricsPlugin, opts)
|
|
198
|
-
|
|
199
|
-
let metricsServer = app
|
|
200
|
-
if (server === 'own') {
|
|
201
|
-
metricsServer = await createMetricsServer(app, hostname, port)
|
|
202
|
-
} else {
|
|
203
|
-
await closeMetricsServer()
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (server !== 'hide') {
|
|
207
|
-
let onRequestHook
|
|
208
|
-
if (auth) {
|
|
209
|
-
const { username, password } = auth
|
|
210
|
-
|
|
211
|
-
await metricsServer.register(require('@fastify/basic-auth'), {
|
|
212
|
-
validate: function (user, pass, req, reply, done) {
|
|
213
|
-
if (username !== user || password !== pass) {
|
|
214
|
-
return reply.code(401).send({ message: 'Unauthorized' })
|
|
215
|
-
}
|
|
216
|
-
return done()
|
|
217
|
-
},
|
|
218
|
-
})
|
|
219
|
-
onRequestHook = metricsServer.basicAuth
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
metricsServer.register(require('@fastify/accepts'))
|
|
223
|
-
|
|
224
|
-
metricsServer.route({
|
|
225
|
-
url: metricsEndpoint,
|
|
226
|
-
method: 'GET',
|
|
227
|
-
logLevel: 'warn',
|
|
228
|
-
onRequest: onRequestHook,
|
|
229
|
-
handler: async (req, reply) => {
|
|
230
|
-
const promRegistry = app.metrics.client.register
|
|
231
|
-
const accepts = req.accepts()
|
|
232
|
-
if (!accepts.type('text/plain') && accepts.type('application/json')) {
|
|
233
|
-
return promRegistry.getMetricsAsJSON()
|
|
234
|
-
}
|
|
235
|
-
reply.type('text/plain')
|
|
236
|
-
return promRegistry.metrics()
|
|
237
|
-
},
|
|
238
|
-
})
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
if (server === 'own') {
|
|
242
|
-
await metricsServer.ready()
|
|
243
|
-
}
|
|
244
|
-
})
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const fp = require('fastify-plugin')
|
|
4
|
-
const compiler = require('@platformatic/ts-compiler')
|
|
5
|
-
const { extractTypeScriptCompileOptionsFromConfig } = require('../compile')
|
|
6
|
-
|
|
7
|
-
async function setupTsCompiler (app, opts) {
|
|
8
|
-
const configManager = app.platformatic.configManager
|
|
9
|
-
const config = configManager.current
|
|
10
|
-
const workingDir = opts?.context?.directory ?? configManager.dirname
|
|
11
|
-
|
|
12
|
-
await compiler.compile({
|
|
13
|
-
...extractTypeScriptCompileOptionsFromConfig(config),
|
|
14
|
-
cwd: workingDir,
|
|
15
|
-
clean: false,
|
|
16
|
-
logger: app.log,
|
|
17
|
-
})
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
module.exports = fp(setupTsCompiler)
|
package/lib/stackable.js
DELETED
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { dirname } = require('node:path')
|
|
4
|
-
const { printSchema } = require('graphql')
|
|
5
|
-
const pino = require('pino')
|
|
6
|
-
const httpMetrics = require('@platformatic/fastify-http-metrics')
|
|
7
|
-
const { extractTypeScriptCompileOptionsFromConfig } = require('./compile')
|
|
8
|
-
const { compile } = require('@platformatic/ts-compiler')
|
|
9
|
-
const { deepmerge } = require('@platformatic/utils')
|
|
10
|
-
|
|
11
|
-
class ServiceStackable {
|
|
12
|
-
constructor (options) {
|
|
13
|
-
this.app = null
|
|
14
|
-
this._init = options.init
|
|
15
|
-
this.stackable = options.stackable
|
|
16
|
-
this.metricsRegistry = null
|
|
17
|
-
|
|
18
|
-
this.configManager = options.configManager
|
|
19
|
-
this.context = options.context ?? {}
|
|
20
|
-
this.context.stackable = this
|
|
21
|
-
|
|
22
|
-
this.configManager.on('error', err => {
|
|
23
|
-
/* c8 ignore next */
|
|
24
|
-
this.stackable.log({
|
|
25
|
-
message: 'error reloading the configuration' + err,
|
|
26
|
-
level: 'error'
|
|
27
|
-
})
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
this.#updateConfig()
|
|
31
|
-
|
|
32
|
-
// Setup globals
|
|
33
|
-
this.registerGlobals({
|
|
34
|
-
setOpenapiSchema: this.setOpenapiSchema.bind(this),
|
|
35
|
-
setGraphqlSchema: this.setGraphqlSchema.bind(this),
|
|
36
|
-
setBasePath: this.setBasePath.bind(this)
|
|
37
|
-
})
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async init () {
|
|
41
|
-
this.#initLogger()
|
|
42
|
-
|
|
43
|
-
if (this.app === null) {
|
|
44
|
-
this.app = await this._init()
|
|
45
|
-
|
|
46
|
-
if (this.metricsRegistry) {
|
|
47
|
-
this.#setHttpMetrics()
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return this.app
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async start (options = {}) {
|
|
54
|
-
await this.init()
|
|
55
|
-
|
|
56
|
-
if (options.listen === false) {
|
|
57
|
-
await this.app.ready()
|
|
58
|
-
return
|
|
59
|
-
}
|
|
60
|
-
await this.app.start()
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async stop () {
|
|
64
|
-
if (this.app === null) return
|
|
65
|
-
await this.app.close()
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async build () {
|
|
69
|
-
this.#initLogger()
|
|
70
|
-
const typeScriptCompileOptions = extractTypeScriptCompileOptionsFromConfig(this.configManager.current)
|
|
71
|
-
const cwd = dirname(this.configManager.fullPath)
|
|
72
|
-
const compileOptions = {
|
|
73
|
-
...typeScriptCompileOptions,
|
|
74
|
-
cwd,
|
|
75
|
-
logger: this.logger
|
|
76
|
-
}
|
|
77
|
-
if (!(await compile(compileOptions))) {
|
|
78
|
-
throw new Error(`Failed to compile ${cwd}`)
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
getUrl () {
|
|
83
|
-
return this.app !== null ? this.app.url : null
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
async getInfo () {
|
|
87
|
-
const type = this.stackable.configType
|
|
88
|
-
const version = this.stackable.configManagerConfig.version ?? null
|
|
89
|
-
return { type, version }
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async getConfig () {
|
|
93
|
-
const config = Object.assign({}, this.configManager.current)
|
|
94
|
-
config.server = Object.assign({}, config.server)
|
|
95
|
-
const logger = config.server.loggerInstance
|
|
96
|
-
|
|
97
|
-
if (logger) {
|
|
98
|
-
config.server.logger = {}
|
|
99
|
-
|
|
100
|
-
if (logger.level) {
|
|
101
|
-
config.server.logger.level = logger.level
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
delete config.server.loggerInstance
|
|
106
|
-
|
|
107
|
-
return config
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
async getEnv () {
|
|
111
|
-
return this.configManager.env
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
getMeta () {
|
|
115
|
-
const config = this.configManager.current
|
|
116
|
-
|
|
117
|
-
return {
|
|
118
|
-
composer: {
|
|
119
|
-
prefix: config.basePath ?? this.basePath ?? this.context?.serviceId,
|
|
120
|
-
wantsAbsoluteUrls: false,
|
|
121
|
-
needsRootRedirect: false
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
async getWatchConfig () {
|
|
127
|
-
const config = this.configManager.current
|
|
128
|
-
|
|
129
|
-
const enabled = config.watch?.enabled !== false && config.plugins !== undefined
|
|
130
|
-
|
|
131
|
-
return {
|
|
132
|
-
enabled,
|
|
133
|
-
path: dirname(this.configManager.fullPath),
|
|
134
|
-
allow: config.watch?.allow,
|
|
135
|
-
ignore: config.watch?.ignore
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
async getDispatchFunc () {
|
|
140
|
-
await this.init()
|
|
141
|
-
return this.app
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
async getOpenapiSchema () {
|
|
145
|
-
await this.init()
|
|
146
|
-
await this.app.ready()
|
|
147
|
-
return this.app.swagger ? this.app.swagger() : null
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
async getGraphqlSchema () {
|
|
151
|
-
await this.init()
|
|
152
|
-
await this.app.ready()
|
|
153
|
-
return this.app.graphql ? printSchema(this.app.graphql.schema) : null
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
async collectMetrics ({ registry }) {
|
|
157
|
-
this.metricsRegistry = registry
|
|
158
|
-
|
|
159
|
-
return {
|
|
160
|
-
defaultMetrics: true,
|
|
161
|
-
httpMetrics: false
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
async inject (injectParams) {
|
|
166
|
-
await this.init()
|
|
167
|
-
|
|
168
|
-
const { statusCode, statusMessage, headers, body } = await this.app.inject(injectParams)
|
|
169
|
-
return { statusCode, statusMessage, headers, body }
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
async log (options = {}) {
|
|
173
|
-
await this.init()
|
|
174
|
-
|
|
175
|
-
const logLevel = options.level ?? 'info'
|
|
176
|
-
|
|
177
|
-
const message = options.message
|
|
178
|
-
if (!message) return
|
|
179
|
-
|
|
180
|
-
this.app.log[logLevel](message)
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
async updateContext (context) {
|
|
184
|
-
this.context = { ...this.context, ...context }
|
|
185
|
-
this.#updateConfig()
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
setOpenapiSchema (schema) {
|
|
189
|
-
this.openapiSchema = schema
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
setGraphqlSchema (schema) {
|
|
193
|
-
this.graphqlSchema = schema
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
setBasePath (basePath) {
|
|
197
|
-
this.basePath = basePath
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
registerGlobals (globals) {
|
|
201
|
-
globalThis.platformatic = Object.assign(globalThis.platformatic ?? {}, globals)
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
#setHttpMetrics () {
|
|
205
|
-
this.app.register(httpMetrics, {
|
|
206
|
-
registry: this.metricsRegistry,
|
|
207
|
-
customLabels: ['telemetry_id'],
|
|
208
|
-
getCustomLabels: req => {
|
|
209
|
-
const telemetryId = req.headers['x-plt-telemetry-id'] ?? 'unknown'
|
|
210
|
-
return { telemetry_id: telemetryId }
|
|
211
|
-
}
|
|
212
|
-
})
|
|
213
|
-
|
|
214
|
-
this.app.register(httpMetrics, {
|
|
215
|
-
registry: this.metricsRegistry,
|
|
216
|
-
customLabels: ['telemetry_id'],
|
|
217
|
-
getCustomLabels: req => {
|
|
218
|
-
const telemetryId = req.headers['x-plt-telemetry-id'] ?? 'unknown'
|
|
219
|
-
return { telemetry_id: telemetryId }
|
|
220
|
-
},
|
|
221
|
-
histogram: {
|
|
222
|
-
name: 'http_request_all_duration_seconds',
|
|
223
|
-
help: 'request duration in seconds summary for all requests',
|
|
224
|
-
collect: function () {
|
|
225
|
-
process.nextTick(() => this.reset())
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
summary: {
|
|
229
|
-
name: 'http_request_all_summary_seconds',
|
|
230
|
-
help: 'request duration in seconds histogram for all requests',
|
|
231
|
-
collect: function () {
|
|
232
|
-
process.nextTick(() => this.reset())
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
})
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
#updateConfig () {
|
|
239
|
-
if (!this.context) return
|
|
240
|
-
|
|
241
|
-
const { serviceId, telemetryConfig, metricsConfig, serverConfig, hasManagementApi, isEntrypoint, isProduction } =
|
|
242
|
-
this.context
|
|
243
|
-
|
|
244
|
-
const config = this.configManager.current
|
|
245
|
-
|
|
246
|
-
if (telemetryConfig) {
|
|
247
|
-
config.telemetry = telemetryConfig
|
|
248
|
-
}
|
|
249
|
-
if (metricsConfig) {
|
|
250
|
-
config.metrics = metricsConfig
|
|
251
|
-
}
|
|
252
|
-
if (serverConfig) {
|
|
253
|
-
config.server = deepmerge(config.server ?? {}, serverConfig ?? {})
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
if ((hasManagementApi && config.metrics === undefined) || config.metrics) {
|
|
257
|
-
const labels = config.metrics?.labels || {}
|
|
258
|
-
config.metrics = {
|
|
259
|
-
server: 'hide',
|
|
260
|
-
defaultMetrics: { enabled: isEntrypoint },
|
|
261
|
-
...config.metrics,
|
|
262
|
-
labels: { serviceId, ...labels }
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
if (!isEntrypoint) {
|
|
267
|
-
config.server = config.server ?? {}
|
|
268
|
-
config.server.trustProxy = true
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
if (isProduction) {
|
|
272
|
-
if (config.plugins) {
|
|
273
|
-
config.plugins.typescript = false
|
|
274
|
-
}
|
|
275
|
-
config.watch = { enabled: false }
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
this.configManager.update(config)
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
#initLogger () {
|
|
282
|
-
if (this.configManager.current.server?.loggerInstance) {
|
|
283
|
-
this.logger = this.configManager.current.server?.loggerInstance
|
|
284
|
-
return
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
this.configManager.current.server ??= {}
|
|
288
|
-
this.loggerConfig = deepmerge(this.context.loggerConfig ?? {}, this.configManager.current.server?.logger ?? {})
|
|
289
|
-
|
|
290
|
-
const pinoOptions = {
|
|
291
|
-
level: this.loggerConfig?.level ?? 'trace'
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
if (this.context?.serviceId) {
|
|
295
|
-
pinoOptions.name = this.context.serviceId
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
this.logger = pino(pinoOptions)
|
|
299
|
-
|
|
300
|
-
// Only one of logger and loggerInstance should be set
|
|
301
|
-
delete this.configManager.current.server.logger
|
|
302
|
-
this.configManager.current.server.loggerInstance = this.logger
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
module.exports = { ServiceStackable }
|