@adonisjs/lucid
Version:
SQL ORM built on top of Active Record pattern
143 lines (142 loc) • 4.84 kB
JavaScript
/*
* @adonisjs/lucid
*
* (c) AdonisJS
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import { BaseCheck, Result } from '@adonisjs/core/health';
/**
* The DbConnectionCountCheck can be used to monitor the active
* database connections and report a warning or error after
* a certain threshold has been execeeded.
*/
export class DbConnectionCountCheck extends BaseCheck {
#client;
/**
* Method to compute the memory consumption
*/
#computeFn = async (client) => {
if (client.dialect.name === 'postgres') {
const response = await client.query().from('pg_stat_activity').count('* as connections');
return Number(response[0].connections);
}
if (client.dialect.name === 'mysql') {
const response = await client
.query()
.from('information_schema.PROCESSLIST')
.count('* as connections');
return Number(response[0].connections);
}
return null;
};
/**
* Connections count threshold after which a warning will be created
*/
#warnThreshold = 10;
/**
* Connections count threshold after which an error will be created
*/
#failThreshold = 15;
/**
* Health check public name
*/
name;
constructor(client) {
super();
this.#client = client;
this.name = `Connection count health check (${client.connectionName})`;
}
/**
* Returns connection metadata to be shared in the health checks
* report
*/
#getConnectionMetadata() {
return {
connection: {
name: this.#client.connectionName,
dialect: this.#client.dialect.name,
},
};
}
/**
* Returns connections count metadata to be shared in the
* health checks report
*/
#getConnectionsCountMetadata(active) {
return {
connectionsCount: {
active,
warningThreshold: this.#warnThreshold,
failureThreshold: this.#failThreshold,
},
};
}
/**
* Define the connections count threshold after which a
* warning should be created.
*
* ```
* .warnWhenExceeds(20)
* ```
*/
warnWhenExceeds(connectionsCount) {
this.#warnThreshold = connectionsCount;
return this;
}
/**
* Define the connections count threshold after which an
* error should be created.
*
* ```
* .failWhenExceeds(30)
* ```
*/
failWhenExceeds(connectionsCount) {
this.#failThreshold = connectionsCount;
return this;
}
/**
* Define a custom callback to compute database connections count.
* The return value must be a number of active connections
* or null (if dialect is not supported).
*/
compute(callback) {
this.#computeFn = callback;
return this;
}
/**
* Executes the health check
*/
async run() {
try {
const connectionsCount = await this.#computeFn(this.#client);
if (!connectionsCount) {
return Result.ok(`Check skipped. Unable to get active connections for ${this.#client.dialect.name} dialect`).mergeMetaData(this.#getConnectionMetadata());
}
/**
* Check if we have crossed the failure threshold
*/
if (connectionsCount > this.#failThreshold) {
return Result.failed(`There are ${connectionsCount} active connections, which is above the threshold of ${this.#failThreshold} connections`)
.mergeMetaData(this.#getConnectionMetadata())
.mergeMetaData(this.#getConnectionsCountMetadata(connectionsCount));
}
/**
* Check if we have crossed the warning threshold
*/
if (connectionsCount > this.#warnThreshold) {
return Result.warning(`There are ${connectionsCount} active connections, which is above the threshold of ${this.#warnThreshold} connections`)
.mergeMetaData(this.#getConnectionMetadata())
.mergeMetaData(this.#getConnectionsCountMetadata(connectionsCount));
}
return Result.ok(`There are ${connectionsCount} active connections, which is under the defined thresholds`)
.mergeMetaData(this.#getConnectionMetadata())
.mergeMetaData(this.#getConnectionsCountMetadata(connectionsCount));
}
catch (error) {
return Result.failed(error.message || 'Connection failed', error).mergeMetaData(this.#getConnectionMetadata());
}
}
}