@lokalise/fastify-extras 30.0.0 → 30.2.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/README.md +80 -2
- package/dist/index.d.ts +5 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/plugins/healthcheck/commonHealthcheckPlugin.d.ts +13 -0
- package/dist/plugins/healthcheck/commonHealthcheckPlugin.js +1 -1
- package/dist/plugins/healthcheck/commonHealthcheckPlugin.js.map +1 -1
- package/dist/plugins/healthcheck/commonSyncHealthcheckPlugin.d.ts +19 -0
- package/dist/plugins/healthcheck/commonSyncHealthcheckPlugin.js +97 -0
- package/dist/plugins/healthcheck/commonSyncHealthcheckPlugin.js.map +1 -0
- package/dist/plugins/healthcheck/healthcheckCommons.d.ts +4 -0
- package/dist/plugins/healthcheck/healthcheckCommons.js.map +1 -1
- package/dist/plugins/healthcheck/publicHealthcheckPlugin.d.ts +3 -0
- package/dist/plugins/healthcheck/publicHealthcheckPlugin.js +3 -0
- package/dist/plugins/healthcheck/publicHealthcheckPlugin.js.map +1 -1
- package/dist/plugins/healthcheck/startupHealthcheckPlugin.d.ts +7 -0
- package/dist/plugins/healthcheck/startupHealthcheckPlugin.js +48 -0
- package/dist/plugins/healthcheck/startupHealthcheckPlugin.js.map +1 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -7,6 +7,8 @@ Reusable plugins for Fastify.
|
|
|
7
7
|
|
|
8
8
|
- [RequestContext Provider Plugin](#requestcontext-provider-plugin)
|
|
9
9
|
- [Public Healthcheck Plugin](#public-healthcheck-plugin)
|
|
10
|
+
- [Common Healthcheck Plugin](#common-healthcheck-plugin)
|
|
11
|
+
- [Common Sync Healthcheck Plugin](#common-sync-healthcheck-plugin)
|
|
10
12
|
- [Split IO Plugin](#split-io-plugin)
|
|
11
13
|
- [BugSnag Plugin](#bugsnag-plugin)
|
|
12
14
|
- [Metrics Plugin](#metrics-plugin)
|
|
@@ -72,7 +74,7 @@ Your Fastify app will reply with the status of the app when hitting the `GET /`
|
|
|
72
74
|
|
|
73
75
|
### Common Healthcheck Plugin
|
|
74
76
|
|
|
75
|
-
Plugin to monitor app status through public and private healthchecks.
|
|
77
|
+
Plugin to monitor app status through public and private healthchecks using asynchronous checks.
|
|
76
78
|
|
|
77
79
|
Add the plugin to your Fastify instance by registering it with the following options:
|
|
78
80
|
|
|
@@ -89,9 +91,77 @@ Your Fastify app will reply with the status of the app when hitting the `GET /`
|
|
|
89
91
|
}
|
|
90
92
|
```
|
|
91
93
|
|
|
94
|
+
Your Fastify app will reply with the status of the app when hitting the `GET /health` private route with detailed results from healthchecks provided, example:
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"heartbeat": "PARTIALLY_HEALTHY",
|
|
98
|
+
"checks": {
|
|
99
|
+
"check1": "HEALTHY",
|
|
100
|
+
"check2": "HEALTHY",
|
|
101
|
+
"check3": "FAIL"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
92
105
|
|
|
106
|
+
### Common Sync Healthcheck Plugin
|
|
93
107
|
|
|
94
|
-
|
|
108
|
+
Plugin to monitor app status through public and private healthchecks using synchronous checks. **This plugin is recommended when you have healthchecks that run synchronously or are executed in the background**, as it provides better performance for such use cases.
|
|
109
|
+
|
|
110
|
+
Add the plugin to your Fastify instance by registering it with the following options:
|
|
111
|
+
|
|
112
|
+
- `healthChecks`, an array of synchronous healthcheck objects, each containing:
|
|
113
|
+
- `name`, the identifier for the healthcheck;
|
|
114
|
+
- `isMandatory`, boolean indicating if this healthcheck is critical for service health;
|
|
115
|
+
- `checker`, a synchronous function that returns `null` on success or an `Error` on failure;
|
|
116
|
+
- `responsePayload` (optional), the response payload that the healthcheck should return;
|
|
117
|
+
- `logLevel` (optional), the log level for the healthcheck routes ('fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'silent'), defaults to 'info';
|
|
118
|
+
- `infoProviders` (optional), an array of info providers to include additional metadata in the `/health` response;
|
|
119
|
+
- `isRootRouteEnabled` (optional), whether to enable the public `/` route, defaults to `true`.
|
|
120
|
+
|
|
121
|
+
Example usage:
|
|
122
|
+
```typescript
|
|
123
|
+
import { commonSyncHealthcheckPlugin } from '@lokalise/fastify-extras'
|
|
124
|
+
|
|
125
|
+
app.register(commonSyncHealthcheckPlugin, {
|
|
126
|
+
healthChecks: [
|
|
127
|
+
{
|
|
128
|
+
name: 'database',
|
|
129
|
+
isMandatory: true,
|
|
130
|
+
checker: (app) => {
|
|
131
|
+
// Synchronous check - returns null if healthy, Error if not
|
|
132
|
+
return isDatabaseConnected() ? null : new Error('Database disconnected')
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: 'cache',
|
|
137
|
+
isMandatory: false, // Optional dependency
|
|
138
|
+
checker: (app) => {
|
|
139
|
+
return isCacheAvailable() ? null : new Error('Cache unavailable')
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
})
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
The plugin exposes the same routes as the async Common Healthcheck Plugin:
|
|
147
|
+
- `GET /` - Public route returning aggregated health status
|
|
148
|
+
- `GET /health` - Private route with detailed healthcheck results
|
|
149
|
+
|
|
150
|
+
The key differences from the async version:
|
|
151
|
+
- Uses synchronous healthcheck functions instead of promises
|
|
152
|
+
- Better suited for checks that are already running in the background or are inherently synchronous
|
|
153
|
+
- Supports mandatory vs optional healthchecks (optional failures result in `PARTIALLY_HEALTHY` status)
|
|
154
|
+
|
|
155
|
+
### Startup Healthcheck Plugin
|
|
156
|
+
|
|
157
|
+
Plugin to monitor app startup status, doing potentially more expensive checks than what is reasonable through periodic healthchecks.
|
|
158
|
+
|
|
159
|
+
Add the plugin to your Fastify instance by registering it with the following options:
|
|
160
|
+
|
|
161
|
+
- `healthChecks`, a list of asynchronous healthchecks to run at the app startup;
|
|
162
|
+
- `resultsLogLevel`, at what log level to report healthcheck results - default is INFO;
|
|
163
|
+
|
|
164
|
+
This is the structure of the log:
|
|
95
165
|
```json
|
|
96
166
|
{
|
|
97
167
|
"heartbeat": "PARTIALLY_HEALTHY",
|
|
@@ -103,6 +173,14 @@ Your Fastify app will reply with the status of the app when hitting the `GET /he
|
|
|
103
173
|
}
|
|
104
174
|
```
|
|
105
175
|
|
|
176
|
+
In case a non-optional healthcheck fails, an application startup will throw an error. In order to ensure that the error is thrown correctly, make sure to await the app startup:
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
const app = fastify()
|
|
180
|
+
await app.register(startupHealthcheckPlugin, opts)
|
|
181
|
+
await app.ready()
|
|
182
|
+
```
|
|
183
|
+
|
|
106
184
|
### Split IO Plugin
|
|
107
185
|
|
|
108
186
|
Plugin to handle feature flags in Split IO.
|
package/dist/index.d.ts
CHANGED
|
@@ -18,9 +18,13 @@ export type { ErrorObjectResolver, MetricsPluginOptions, } from './plugins/metri
|
|
|
18
18
|
export { publicHealthcheckPlugin } from './plugins/healthcheck/publicHealthcheckPlugin.js';
|
|
19
19
|
export type { PublicHealthcheckPluginOptions, HealthCheck, InfoProvider, } from './plugins/healthcheck/publicHealthcheckPlugin.js';
|
|
20
20
|
export { wrapHealthCheck } from './plugins/healthcheck/healthcheckCommons.js';
|
|
21
|
-
export type { HealthChecker } from './plugins/healthcheck/healthcheckCommons.js';
|
|
21
|
+
export type { HealthChecker, HealthCheckerSync } from './plugins/healthcheck/healthcheckCommons.js';
|
|
22
22
|
export { commonHealthcheckPlugin } from './plugins/healthcheck/commonHealthcheckPlugin.js';
|
|
23
23
|
export type { CommonHealthcheckPluginOptions } from './plugins/healthcheck/commonHealthcheckPlugin.js';
|
|
24
|
+
export { startupHealthcheckPlugin } from './plugins/healthcheck/startupHealthcheckPlugin.js';
|
|
25
|
+
export type { StartupHealthcheckPluginOptions } from './plugins/healthcheck/startupHealthcheckPlugin.js';
|
|
26
|
+
export { commonSyncHealthcheckPlugin } from './plugins/healthcheck/commonSyncHealthcheckPlugin.ts';
|
|
27
|
+
export type { CommonSyncHealthcheckPluginOptions } from './plugins/healthcheck/commonSyncHealthcheckPlugin.ts';
|
|
24
28
|
export { amplitudePlugin, type AmplitudeConfig, type CreateApiTrackingEventFn, } from './plugins/amplitude/amplitudePlugin.js';
|
|
25
29
|
export { Amplitude } from './plugins/amplitude/Amplitude.js';
|
|
26
30
|
export { AmplitudeAdapter, AMPLITUDE_BASE_MESSAGE_SCHEMA, type AmplitudeMessage, type AmplitudeAdapterDependencies, } from './plugins/amplitude/AmplitudeAdapter.js';
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,8 @@ export { metricsPlugin } from './plugins/metricsPlugin.js';
|
|
|
10
10
|
export { publicHealthcheckPlugin } from './plugins/healthcheck/publicHealthcheckPlugin.js';
|
|
11
11
|
export { wrapHealthCheck } from './plugins/healthcheck/healthcheckCommons.js';
|
|
12
12
|
export { commonHealthcheckPlugin } from './plugins/healthcheck/commonHealthcheckPlugin.js';
|
|
13
|
+
export { startupHealthcheckPlugin } from './plugins/healthcheck/startupHealthcheckPlugin.js';
|
|
14
|
+
export { commonSyncHealthcheckPlugin } from "./plugins/healthcheck/commonSyncHealthcheckPlugin.js";
|
|
13
15
|
export { amplitudePlugin, } from './plugins/amplitude/amplitudePlugin.js';
|
|
14
16
|
export { Amplitude } from './plugins/amplitude/Amplitude.js';
|
|
15
17
|
export { AmplitudeAdapter, AMPLITUDE_BASE_MESSAGE_SCHEMA, } from './plugins/amplitude/AmplitudeAdapter.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,GACf,MAAM,4BAA4B,CAAA;AAGnC,OAAO,EACL,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,2CAA2C,CAAA;AAGlD,OAAO,EACL,gCAAgC,EAChC,0BAA0B,GAC3B,MAAM,+CAA+C,CAAA;AAGtD,OAAO,EACL,2BAA2B,EAC3B,qBAAqB,GACtB,MAAM,0CAA0C,CAAA;AAGjD,OAAO,EACL,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,mDAAmD,CAAA;AAO1D,OAAO,EAAE,mCAAmC,EAAE,MAAM,6DAA6D,CAAA;AAEjH,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAA;AAEtE,OAAO,EACL,yBAAyB,EACzB,kCAAkC,GACnC,MAAM,+CAA+C,CAAA;AAGtD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAM1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,kDAAkD,CAAA;AAO1F,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAA;AAG7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,kDAAkD,CAAA;AAG1F,OAAO,EACL,eAAe,GAGhB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAA;AAC5D,OAAO,EACL,gBAAgB,EAChB,6BAA6B,GAG9B,MAAM,yCAAyC,CAAA;AAIhD,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAA;AAEhF,OAAO,EACL,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,uCAAuC,CAAA;AAG9C,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAA4B,MAAM,0BAA0B,CAAA;AAGnG,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAE5E,OAAO,EAAE,+BAA+B,EAAE,MAAM,kCAAkC,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,GACf,MAAM,4BAA4B,CAAA;AAGnC,OAAO,EACL,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,2CAA2C,CAAA;AAGlD,OAAO,EACL,gCAAgC,EAChC,0BAA0B,GAC3B,MAAM,+CAA+C,CAAA;AAGtD,OAAO,EACL,2BAA2B,EAC3B,qBAAqB,GACtB,MAAM,0CAA0C,CAAA;AAGjD,OAAO,EACL,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,mDAAmD,CAAA;AAO1D,OAAO,EAAE,mCAAmC,EAAE,MAAM,6DAA6D,CAAA;AAEjH,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAA;AAEtE,OAAO,EACL,yBAAyB,EACzB,kCAAkC,GACnC,MAAM,+CAA+C,CAAA;AAGtD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAM1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,kDAAkD,CAAA;AAO1F,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAA;AAG7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,kDAAkD,CAAA;AAG1F,OAAO,EAAE,wBAAwB,EAAE,MAAM,mDAAmD,CAAA;AAG5F,OAAO,EAAE,2BAA2B,EAAE,MAAM,sDAAsD,CAAA;AAGlG,OAAO,EACL,eAAe,GAGhB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAA;AAC5D,OAAO,EACL,gBAAgB,EAChB,6BAA6B,GAG9B,MAAM,yCAAyC,CAAA;AAIhD,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAA;AAEhF,OAAO,EACL,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,uCAAuC,CAAA;AAG9C,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAA4B,MAAM,0BAA0B,CAAA;AAGnG,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAE5E,OAAO,EAAE,+BAA+B,EAAE,MAAM,kCAAkC,CAAA"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Either } from '@lokalise/node-core';
|
|
1
2
|
import type { FastifyPluginCallback } from 'fastify';
|
|
2
3
|
import type { HealthChecker } from './healthcheckCommons.js';
|
|
3
4
|
export interface CommonHealthcheckPluginOptions {
|
|
@@ -7,6 +8,16 @@ export interface CommonHealthcheckPluginOptions {
|
|
|
7
8
|
infoProviders?: readonly InfoProvider[];
|
|
8
9
|
isRootRouteEnabled?: boolean;
|
|
9
10
|
}
|
|
11
|
+
type HealthcheckResult = {
|
|
12
|
+
name: string;
|
|
13
|
+
isMandatory: boolean;
|
|
14
|
+
result: Either<Error, true>;
|
|
15
|
+
};
|
|
16
|
+
type ResolvedHealthcheckResponse = {
|
|
17
|
+
isFullyHealthy: boolean;
|
|
18
|
+
isPartiallyHealthy: boolean;
|
|
19
|
+
healthChecks: Record<string, string>;
|
|
20
|
+
};
|
|
10
21
|
export type InfoProvider = {
|
|
11
22
|
name: string;
|
|
12
23
|
dataResolver: () => Record<string, unknown>;
|
|
@@ -16,4 +27,6 @@ export type HealthCheck = {
|
|
|
16
27
|
isMandatory: boolean;
|
|
17
28
|
checker: HealthChecker;
|
|
18
29
|
};
|
|
30
|
+
export declare function resolveHealthcheckResults(results: HealthcheckResult[], opts: CommonHealthcheckPluginOptions): ResolvedHealthcheckResponse;
|
|
19
31
|
export declare const commonHealthcheckPlugin: FastifyPluginCallback<CommonHealthcheckPluginOptions>;
|
|
32
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commonHealthcheckPlugin.js","sourceRoot":"","sources":["../../../lib/plugins/healthcheck/commonHealthcheckPlugin.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAwC/B,
|
|
1
|
+
{"version":3,"file":"commonHealthcheckPlugin.js","sourceRoot":"","sources":["../../../lib/plugins/healthcheck/commonHealthcheckPlugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { FastifyPluginCallback } from 'fastify';
|
|
2
|
+
import type { HealthCheckerSync } from './healthcheckCommons.js';
|
|
3
|
+
export interface CommonSyncHealthcheckPluginOptions {
|
|
4
|
+
responsePayload?: Record<string, unknown>;
|
|
5
|
+
logLevel?: 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'silent';
|
|
6
|
+
healthChecks: readonly HealthCheckSync[];
|
|
7
|
+
infoProviders?: readonly InfoProvider[];
|
|
8
|
+
isRootRouteEnabled?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export type InfoProvider = {
|
|
11
|
+
name: string;
|
|
12
|
+
dataResolver: () => Record<string, unknown>;
|
|
13
|
+
};
|
|
14
|
+
export type HealthCheckSync = {
|
|
15
|
+
name: string;
|
|
16
|
+
isMandatory: boolean;
|
|
17
|
+
checker: HealthCheckerSync;
|
|
18
|
+
};
|
|
19
|
+
export declare const commonSyncHealthcheckPlugin: FastifyPluginCallback<CommonSyncHealthcheckPluginOptions>;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import fp from 'fastify-plugin';
|
|
2
|
+
function resolveHealthcheckResults(results, opts) {
|
|
3
|
+
const healthChecks = {};
|
|
4
|
+
let isFullyHealthy = true;
|
|
5
|
+
let isPartiallyHealthy = false;
|
|
6
|
+
// Return detailed healthcheck results
|
|
7
|
+
for (let i = 0; i < results.length; i++) {
|
|
8
|
+
const entry = results[i];
|
|
9
|
+
if (!entry)
|
|
10
|
+
continue;
|
|
11
|
+
healthChecks[entry.name] = entry.healthcheckError ? 'FAIL' : 'HEALTHY';
|
|
12
|
+
if (entry.healthcheckError && opts.healthChecks[i]?.isMandatory) {
|
|
13
|
+
isFullyHealthy = false;
|
|
14
|
+
isPartiallyHealthy = false;
|
|
15
|
+
}
|
|
16
|
+
// Check if we are only partially healthy (only optional dependencies are failing)
|
|
17
|
+
if (isFullyHealthy && entry.healthcheckError && !opts.healthChecks[i]?.isMandatory) {
|
|
18
|
+
isFullyHealthy = false;
|
|
19
|
+
isPartiallyHealthy = true;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
isFullyHealthy,
|
|
24
|
+
isPartiallyHealthy,
|
|
25
|
+
healthChecks,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function addRoute(app, opts, routeOpts) {
|
|
29
|
+
const responsePayload = opts.responsePayload ?? {};
|
|
30
|
+
app.route({
|
|
31
|
+
url: routeOpts.url,
|
|
32
|
+
method: 'GET',
|
|
33
|
+
logLevel: opts.logLevel ?? 'info',
|
|
34
|
+
schema: {
|
|
35
|
+
// hide route from swagger plugins
|
|
36
|
+
hide: true,
|
|
37
|
+
},
|
|
38
|
+
handler: (_, reply) => {
|
|
39
|
+
let isFullyHealthy = true;
|
|
40
|
+
let isPartiallyHealthy = false;
|
|
41
|
+
let healthChecks = {};
|
|
42
|
+
if (opts.healthChecks.length) {
|
|
43
|
+
const results = opts.healthChecks.map((healthcheck) => {
|
|
44
|
+
const healthcheckError = healthcheck.checker(app);
|
|
45
|
+
if (healthcheckError) {
|
|
46
|
+
app.log.error(healthcheckError, `${healthcheck.name} healthcheck has failed`);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
name: healthcheck.name,
|
|
50
|
+
healthcheckError,
|
|
51
|
+
isMandatory: healthcheck.isMandatory,
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
const resolvedHealthcheckResponse = resolveHealthcheckResults(results, opts);
|
|
55
|
+
healthChecks = resolvedHealthcheckResponse.healthChecks;
|
|
56
|
+
isFullyHealthy = resolvedHealthcheckResponse.isFullyHealthy;
|
|
57
|
+
isPartiallyHealthy = resolvedHealthcheckResponse.isPartiallyHealthy;
|
|
58
|
+
}
|
|
59
|
+
const extraInfo = opts.infoProviders?.map((infoProvider) => ({
|
|
60
|
+
name: infoProvider.name,
|
|
61
|
+
value: infoProvider.dataResolver(),
|
|
62
|
+
}));
|
|
63
|
+
const heartbeat = isFullyHealthy
|
|
64
|
+
? 'HEALTHY'
|
|
65
|
+
: isPartiallyHealthy
|
|
66
|
+
? 'PARTIALLY_HEALTHY'
|
|
67
|
+
: 'FAIL';
|
|
68
|
+
const response = {
|
|
69
|
+
...responsePayload,
|
|
70
|
+
heartbeat,
|
|
71
|
+
...(routeOpts.isPublicRoute
|
|
72
|
+
? {}
|
|
73
|
+
: { checks: healthChecks, ...(extraInfo && { extraInfo }) }),
|
|
74
|
+
};
|
|
75
|
+
return reply.status(isFullyHealthy || isPartiallyHealthy ? 200 : 500).send(response);
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
const plugin = (app, opts, done) => {
|
|
80
|
+
const isRootRouteEnabled = opts.isRootRouteEnabled ?? true;
|
|
81
|
+
if (isRootRouteEnabled) {
|
|
82
|
+
addRoute(app, opts, {
|
|
83
|
+
url: '/',
|
|
84
|
+
isPublicRoute: true,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
addRoute(app, opts, {
|
|
88
|
+
url: '/health',
|
|
89
|
+
isPublicRoute: false,
|
|
90
|
+
});
|
|
91
|
+
done();
|
|
92
|
+
};
|
|
93
|
+
export const commonSyncHealthcheckPlugin = fp(plugin, {
|
|
94
|
+
fastify: '5.x',
|
|
95
|
+
name: 'common-sync-healthcheck-plugin',
|
|
96
|
+
});
|
|
97
|
+
//# sourceMappingURL=commonSyncHealthcheckPlugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commonSyncHealthcheckPlugin.js","sourceRoot":"","sources":["../../../lib/plugins/healthcheck/commonSyncHealthcheckPlugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { Either } from '@lokalise/node-core';
|
|
2
2
|
import type { AnyFastifyInstance } from '../pluginsCommon.js';
|
|
3
3
|
export type HealthChecker = (app: AnyFastifyInstance) => Promise<Either<Error, true>>;
|
|
4
|
+
/**
|
|
5
|
+
* Returns error (if fail) or null (if pass)
|
|
6
|
+
*/
|
|
7
|
+
export type HealthCheckerSync = (app: AnyFastifyInstance) => Error | null;
|
|
4
8
|
/**
|
|
5
9
|
* Return a function which executes healthcheck and throws an error if it fails
|
|
6
10
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"healthcheckCommons.js","sourceRoot":"","sources":["../../../lib/plugins/healthcheck/healthcheckCommons.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"healthcheckCommons.js","sourceRoot":"","sources":["../../../lib/plugins/healthcheck/healthcheckCommons.ts"],"names":[],"mappings":"AAUA;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAuB,EAAE,WAA0B,EAAE,EAAE;IACrF,OAAO,KAAK,IAAI,EAAE;QAChB,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,CAAA;QACvC,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;YACnB,MAAM,QAAQ,CAAC,KAAK,CAAA;QACtB,CAAC;IACH,CAAC,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publicHealthcheckPlugin.js","sourceRoot":"","sources":["../../../lib/plugins/healthcheck/publicHealthcheckPlugin.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"publicHealthcheckPlugin.js","sourceRoot":"","sources":["../../../lib/plugins/healthcheck/publicHealthcheckPlugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FastifyPluginCallback } from 'fastify';
|
|
2
|
+
import { type HealthCheck } from './commonHealthcheckPlugin.js';
|
|
3
|
+
export interface StartupHealthcheckPluginOptions {
|
|
4
|
+
resultsLogLevel?: 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'silent';
|
|
5
|
+
healthChecks: readonly HealthCheck[];
|
|
6
|
+
}
|
|
7
|
+
export declare const startupHealthcheckPlugin: FastifyPluginCallback<StartupHealthcheckPluginOptions>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import fp from 'fastify-plugin';
|
|
2
|
+
import { stdSerializers } from 'pino';
|
|
3
|
+
import { resolveHealthcheckResults } from './commonHealthcheckPlugin.js';
|
|
4
|
+
const plugin = (app, opts, done) => {
|
|
5
|
+
app.addHook('onReady', async () => {
|
|
6
|
+
let isFullyHealthy = true;
|
|
7
|
+
let isPartiallyHealthy = false;
|
|
8
|
+
let healthChecks = {};
|
|
9
|
+
const failedHealthchecks = [];
|
|
10
|
+
if (opts.healthChecks.length) {
|
|
11
|
+
const results = await Promise.all(opts.healthChecks.map(async (healthcheck) => {
|
|
12
|
+
const result = await healthcheck.checker(app);
|
|
13
|
+
if (result.error) {
|
|
14
|
+
app.log.error({
|
|
15
|
+
error: stdSerializers.err(result.error),
|
|
16
|
+
}, `${healthcheck.name} healthcheck has failed`);
|
|
17
|
+
}
|
|
18
|
+
if (result.error) {
|
|
19
|
+
failedHealthchecks.push(healthcheck.name);
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
name: healthcheck.name,
|
|
23
|
+
result,
|
|
24
|
+
isMandatory: healthcheck.isMandatory,
|
|
25
|
+
};
|
|
26
|
+
}));
|
|
27
|
+
const resolvedHealthcheckResponse = resolveHealthcheckResults(results, opts);
|
|
28
|
+
healthChecks = resolvedHealthcheckResponse.healthChecks;
|
|
29
|
+
isFullyHealthy = resolvedHealthcheckResponse.isFullyHealthy;
|
|
30
|
+
isPartiallyHealthy = resolvedHealthcheckResponse.isPartiallyHealthy;
|
|
31
|
+
}
|
|
32
|
+
const heartbeat = isFullyHealthy ? 'HEALTHY' : isPartiallyHealthy ? 'PARTIALLY_HEALTHY' : 'FAIL';
|
|
33
|
+
const resultLog = {
|
|
34
|
+
heartbeat,
|
|
35
|
+
checks: healthChecks,
|
|
36
|
+
};
|
|
37
|
+
app.log[opts.resultsLogLevel ?? 'info'](resultLog, 'Healthcheck finished');
|
|
38
|
+
if (!isPartiallyHealthy && !isFullyHealthy) {
|
|
39
|
+
throw new Error(`Healthchecks failed: ${JSON.stringify(failedHealthchecks)}`);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
done();
|
|
43
|
+
};
|
|
44
|
+
export const startupHealthcheckPlugin = fp(plugin, {
|
|
45
|
+
fastify: '5.x',
|
|
46
|
+
name: 'startup-healthcheck-plugin',
|
|
47
|
+
});
|
|
48
|
+
//# sourceMappingURL=startupHealthcheckPlugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startupHealthcheckPlugin.js","sourceRoot":"","sources":["../../../lib/plugins/healthcheck/startupHealthcheckPlugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,MAAM,CAAA;AACrC,OAAO,EAAoB,yBAAyB,EAAE,MAAM,8BAA8B,CAAA;AAO1F,MAAM,MAAM,GAA2D,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;IACzF,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;QAChC,IAAI,cAAc,GAAG,IAAI,CAAA;QACzB,IAAI,kBAAkB,GAAG,KAAK,CAAA;QAC9B,IAAI,YAAY,GAA2B,EAAE,CAAA;QAC7C,MAAM,kBAAkB,GAAa,EAAE,CAAA;QAEvC,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;YAC7B,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE;gBAC1C,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;gBAC7C,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;oBACjB,GAAG,CAAC,GAAG,CAAC,KAAK,CACX;wBACE,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;qBACxC,EACD,GAAG,WAAW,CAAC,IAAI,yBAAyB,CAC7C,CAAA;gBACH,CAAC;gBACD,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;oBACjB,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;gBAC3C,CAAC;gBACD,OAAO;oBACL,IAAI,EAAE,WAAW,CAAC,IAAI;oBACtB,MAAM;oBACN,WAAW,EAAE,WAAW,CAAC,WAAW;iBACrC,CAAA;YACH,CAAC,CAAC,CACH,CAAA;YAED,MAAM,2BAA2B,GAAG,yBAAyB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YAC5E,YAAY,GAAG,2BAA2B,CAAC,YAAY,CAAA;YACvD,cAAc,GAAG,2BAA2B,CAAC,cAAc,CAAA;YAC3D,kBAAkB,GAAG,2BAA2B,CAAC,kBAAkB,CAAA;QACrE,CAAC;QAED,MAAM,SAAS,GAAG,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,MAAM,CAAA;QAEhG,MAAM,SAAS,GAAG;YAChB,SAAS;YACT,MAAM,EAAE,YAAY;SACrB,CAAA;QAED,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,IAAI,MAAM,CAAC,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAA;QAE1E,IAAI,CAAC,kBAAkB,IAAI,CAAC,cAAc,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAA;QAC/E,CAAC;IACH,CAAC,CAAC,CAAA;IACF,IAAI,EAAE,CAAA;AACR,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC,MAAM,EAAE;IACjD,OAAO,EAAE,KAAK;IACd,IAAI,EAAE,4BAA4B;CACnC,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lokalise/fastify-extras",
|
|
3
|
-
"version": "30.
|
|
3
|
+
"version": "30.2.0",
|
|
4
4
|
"description": "Opinionated set of fastify plugins, commonly used in Lokalise",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Lokalise",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"@lokalise/background-jobs-common": "^14.0.2",
|
|
66
66
|
"@lokalise/biome-config": "^2.0.0",
|
|
67
67
|
"@lokalise/node-core": "^14.4.1",
|
|
68
|
-
"@lokalise/tsconfig": "^
|
|
68
|
+
"@lokalise/tsconfig": "^3.0.0",
|
|
69
69
|
"@types/newrelic": "^9.14.8",
|
|
70
70
|
"@types/node": "^22.18.0",
|
|
71
71
|
"@vitest/coverage-v8": "^3.2.4",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"fastify": "^5.5.0",
|
|
75
75
|
"fastify-type-provider-zod": "^6.0.0",
|
|
76
76
|
"ioredis": "^5.6.1",
|
|
77
|
-
"newrelic": "13.2
|
|
77
|
+
"newrelic": "13.3.2",
|
|
78
78
|
"pino": "^9.9.0",
|
|
79
79
|
"pino-pretty": "^13.1.1",
|
|
80
80
|
"rimraf": "^6.0.1",
|