Health check
The health check module of AdonisJS allows you and the installed packages to report the health of your application.
Health checks are usually helpful when performing rolling deployments, as you can check the health of the newly deployed code before sending any traffic to it. All major platforms, including: DigitalOcean Apps , Kubernetes and Amazon ECS has support for performing health checks.
How do health checks work?
The health checks' main goals are to perform operations and ensure that your application will work fine in production. It covers operations like:
- Checking database connectivity
- Making sure all the environment variables are in place to run the app
- The database does not have any pending migrations and so on.
The health checks system CANNOT check if your application will cause an error during some specific flow, as that is more of a logical or runtime exception and not something that we can detect beforehand.
Exposing health checks endpoint
A common practice is to expose an HTTP endpoint that the deployment systems can ping to check the health of your application. You can expose this endpoint by registering a route.
import Route from '@ioc:Adonis/Core/Route'
import HealthCheck from '@ioc:Adonis/Core/HealthCheck'
Route.get('health', async ({ response }) => {
const report = await HealthCheck.getReport()
return report.healthy
? response.ok(report)
: response.badRequest(report)
})
The getReport
method returns a JSON object with the report of all the registered health checkers. The object is formatted as follows:
{
healthy: true,
report: {
env: {
displayName: 'Node env check',
health: {
healthy: true,
}
}
}
}
healthy
The top-level healthy
property tells if all the checks have passed or not.
report
The report
property includes a key-value pair of all the registered health checks and their respective state.
displayName
The displayName
sub-property is usually helpful when you visualize the report on a dashboard and want a readable name.
health
The health
sub-property includes the health status and an error message (if the report is unhealthy).
{
health: {
healthy: true
}
}
{
health: {
healthy: false,
message: 'One or more connections are not healthy.'
}
}
meta
The health checkers can also attach custom metadata to their respective nodes, and the shape of metadata may vary depending upon the checker.
Existing health checkers
Following is the list of existing health checkers.
App key checker
The checker is configured implicitly and cannot be disabled. It checks for the existence of the APP_KEY
environment variable and ensures a minimum length of 32 characters.
You can generate the app key using the node ace generate:key
command and then use the output as the value for the APP_KEY
environment variable.
Node env checker
Checks the existence of the NODE_ENV
environment variable and fails if it has not been defined explicitly. You should never run your application in unknown environment.
Lucid checker
The @adonisjs/lucid
package allows to optionally enable health checks for a given or all the registered connections. It will then try to establish a connection
with the database and reports its status.
Make sure to enable health checks for a given connection by modifying the config/database.ts
file.
{
pg: {
client: 'pg',
connection: {
// ... connection details
},
healthCheck: true, // 👈 enabled
}
}
The top-level lucid
node contains an aggregated status of all the registered connections, and the meta
array includes the individual status of all the connections.
{
lucid: {
displayName: 'Database',
health: {
healthy: true,
message: 'All connections are healthy'
},
meta: [
{
connection: 'pg',
message: 'Connection is healthy',
error: null
}
]
}
}
In case of an error, the meta[index].error
property will contain the error stack.
Redis checker
You can also optionally enabled health checks for the @adonisjs/redis
module by modifying the config/redis.ts
file.
{
local: {
host: '127.0.0.1',
port: 6379,
password: '',
healthCheck: true // 👈 enabled
}
}
The top-level redis
node contains an aggregated status of all the registered connections, and the meta
array includes the individual status of all the connections.
{
displayName: 'Redis',
health: {
healthy: true,
message: 'All connections are healthy',
},
meta: [
{
connection: 'local',
status: 'ready',
used_memory: '1.00M',
error: null
}
]
}
In case of an error, the meta[index].error
property will contain the error stack, and the used_memory
property will be set to null
.
Adding a custom health checker
You can also register your custom health checkers within your application codebase or provide them as a package. You can register it inside the boot
method of a service provider.
The addChecker
method takes a unique name for the checker and a callback function that performs the health check and returns the report.
import { ApplicationContract } from '@ioc:Adonis/Core/Application'
export default class AppProvider {
constructor(protected app: ApplicationContract) {}
public async boot() {
const HealthCheck = this.app.container.use('Adonis/Core/HealthCheck')
HealthCheck.addChecker('my-checker', async () => {
return {
displayName: 'Checker Name',
health: {
healthy: true,
message: 'Everything works fine'
},
meta: {},
}
})
}
}