Skip to content

Commit

Permalink
feat(@nestjs/terminus): Add MemoryHealthIndicator
Browse files Browse the repository at this point in the history
  • Loading branch information
BrunnerLivio committed Apr 7, 2019
1 parent bac4854 commit 2666161
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 23 deletions.
71 changes: 71 additions & 0 deletions e2e/health-checks/memory.health.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { INestApplication } from '@nestjs/common';

import Axios from 'axios';
import { MemoryHealthIndicator, TerminusModuleOptions } from '../../lib';
import { bootstrapModule } from '../helper/bootstrap-module';

describe('Memory Health', () => {
let app: INestApplication;
let port: number;
let getTerminusOptions: (
disk: MemoryHealthIndicator,
) => TerminusModuleOptions;
beforeEach(async () => {
getTerminusOptions = (
disk: MemoryHealthIndicator,
): TerminusModuleOptions => ({
endpoints: [
{
url: '/health',
healthIndicators: [
async () => {
const { heapUsed } = process.memoryUsage();
return disk.check('memory', { threshold: heapUsed + 1 });
},
],
},
],
});
});

it('should check if the memory threshold is not exceeded', async () => {
[app, port] = await bootstrapModule({
inject: [MemoryHealthIndicator],
useFactory: getTerminusOptions,
});
const response = await Axios.get(`http://0.0.0.0:${port}/health`);
expect(response.status).toBe(200);
expect(response.data).toEqual({
status: 'ok',
info: { memory: { status: 'up' } },
});
});

it('should check if correctly displays a threshold exceeded error', async () => {
[app, port] = await bootstrapModule({
inject: [MemoryHealthIndicator],
useFactory: (disk: MemoryHealthIndicator): TerminusModuleOptions => ({
endpoints: [
{
url: '/health',
healthIndicators: [
async () => disk.check('disk', { threshold: 0 }),
],
},
],
}),
});

try {
await Axios.get(`http://0.0.0.0:${port}/health`);
} catch (error) {
expect(error.response.status).toBe(503);
expect(error.response.data).toEqual({
status: 'error',
error: { disk: { status: 'down', message: expect.any(String) } },
});
}
});

afterEach(async () => await app.close());
});
16 changes: 0 additions & 16 deletions lib/errors/disk-threshold.error.ts

This file was deleted.

1 change: 1 addition & 0 deletions lib/errors/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './connection-not-found.error';
export * from './timeout-error';
export * from './storage-exceeded.error';
4 changes: 2 additions & 2 deletions lib/errors/messages.constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ export const CONNECTION_NOT_FOUND =
export const TIMEOUT_EXCEEDED = (timeout: number) =>
`timeout of ${timeout.toString()}ms exceeded`;

export const DISK_STORAGE_EXCEEDED =
'Available disk storage exceeded the set threshold';
export const STORAGE_EXCEEDED = (keyword: string) =>
`Used ${keyword} exceeded the set threshold`;
18 changes: 18 additions & 0 deletions lib/errors/storage-exceeded.error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { HealthCheckError } from '@godaddy/terminus';
import { STORAGE_EXCEEDED } from './messages.constant';

/**
* Error which gets thrown when the given storage threshold
* has exceeded.
*/
export class StorageExceededError extends HealthCheckError {
/**
* Initializes the error
*
* @param {string} keyword The keyword (heap, rss, disk e.g.)
* @param {unknown} cause The cause of the health check error
*/
constructor(keyword: string, cause: unknown) {
super(STORAGE_EXCEEDED(keyword), cause);
}
}
11 changes: 6 additions & 5 deletions lib/health-indicators/disk/disk.health.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import * as checkdiskspace from 'check-disk-space';
import { HealthIndicatorResult } from '../../interfaces';
import { HealthIndicator } from '../health-indicator';
import { CHECKDISKSPACE_LIB } from '../../terminus.constants';
import { DiskStorageExceededError } from '../../errors/disk-threshold.error';
import { DISK_STORAGE_EXCEEDED } from '../../errors/messages.constant';
import { StorageExceededError } from '../../errors';
import { STORAGE_EXCEEDED } from '../../errors/messages.constant';
import {
DiskHealthIndicatorOptions,
DiskOptionsWithThresholdPercent,
Expand Down Expand Up @@ -79,9 +79,10 @@ export class DiskHealthIndicator extends HealthIndicator {
}

if (!isHealthy) {
throw new DiskStorageExceededError(
throw new StorageExceededError(
'disk storage',
this.getStatus(key, false, {
message: DISK_STORAGE_EXCEEDED,
message: STORAGE_EXCEEDED('disk storage'),
}),
);
}
Expand All @@ -95,7 +96,7 @@ export class DiskHealthIndicator extends HealthIndicator {
* @param key The key which will be used for the result object
*
* @throws {HealthCheckError} In case the health indicator failed
* @throws {DiskStorageExceededError} In case the disk storage has exceeded the given threshold
* @throws {StorageExceededError} In case the disk storage has exceeded the given threshold
*
* @returns {Promise<HealthIndicatorResult>} The result of the health indicator check
*
Expand Down
1 change: 1 addition & 0 deletions lib/health-indicators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ export * from './database/mongoose.health';
export * from './database/typeorm.health';
export * from './microservice/microservice.health';
export * from './disk';
export * from './memory';

export * from './health-indicator';
1 change: 1 addition & 0 deletions lib/health-indicators/memory/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './memory.health';
83 changes: 83 additions & 0 deletions lib/health-indicators/memory/memory.health.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { Injectable } from '@nestjs/common';

import { HealthIndicatorResult } from '../../interfaces';
import { HealthIndicator } from '../health-indicator';
import { STORAGE_EXCEEDED } from '../../errors/messages.constant';
import { StorageExceededError } from '../../errors';

/**
* The MemoryHealthIndicator contains checks which are related
* to the memory storage of the current running machine
*
* @public
*/
@Injectable()
export class MemoryHealthIndicator extends HealthIndicator {
/**
* Checks the heap space and returns the status
*
* @param key The key which will be used for the result object
* @param options The options of the `MemoryHealthIndicator`
*
* @throws {StorageExceededError} In case the heap has exceeded the given threshold
*
* @public
*
* @returns {Promise<HealthIndicatorResult>} The result of the health indicator check
*
* @example
* // The process should not use more than 150MB memory
* memoryHealthIndicator.checkRSS('memory_heap', 150 * 1024 * 1024);
*/
public async checkHeap(
key: string,
heapUsedThreshold: number,
): Promise<HealthIndicatorResult> {
const { heapUsed } = process.memoryUsage();

if (heapUsedThreshold < heapUsed) {
throw new StorageExceededError(
'heap',
this.getStatus(key, false, {
message: STORAGE_EXCEEDED('heap'),
}),
);
}

return this.getStatus(key, true);
}

/**
* Checks the rss space and returns the status
*
* @param key The key which will be used for the result object
* @param options The options of the `MemoryHealthIndicator`
*
* @throws {StorageExceededError} In case the rss has exceeded the given threshold
*
* @public
*
* @returns {Promise<HealthIndicatorResult>} The result of the health indicator check
*
* @example
* // The process should not have more than 150MB allocated
* memoryHealthIndicator.checkRSS('memory_rss', 150 * 1024 * 1024);
*/
public async checkRSS(
key: string,
rssThreshold: number,
): Promise<HealthIndicatorResult> {
const { rss } = process.memoryUsage();

if (rssThreshold < rss) {
throw new StorageExceededError(
'rss',
this.getStatus(key, false, {
message: STORAGE_EXCEEDED('rss'),
}),
);
}

return this.getStatus(key, true);
}
}
5 changes: 5 additions & 0 deletions lib/terminus-core.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
DNSHealthIndicator,
MicroserviceHealthIndicator,
DiskHealthIndicator,
MemoryHealthIndicator,
} from './health-indicators';
import { DiskusageLibProvider } from './health-indicators/disk/diskusage-lib.provider';

Expand Down Expand Up @@ -55,13 +56,15 @@ export class TerminusCoreModule {
MicroserviceHealthIndicator,
DiskusageLibProvider,
DiskHealthIndicator,
MemoryHealthIndicator,
],
exports: [
TypeOrmHealthIndicator,
MongooseHealthIndicator,
DNSHealthIndicator,
MicroserviceHealthIndicator,
DiskHealthIndicator,
MemoryHealthIndicator,
],
};
}
Expand All @@ -86,13 +89,15 @@ export class TerminusCoreModule {
MicroserviceHealthIndicator,
DiskusageLibProvider,
DiskHealthIndicator,
MemoryHealthIndicator,
],
exports: [
TypeOrmHealthIndicator,
DNSHealthIndicator,
MongooseHealthIndicator,
MicroserviceHealthIndicator,
DiskHealthIndicator,
MemoryHealthIndicator,
],
};
}
Expand Down

0 comments on commit 2666161

Please sign in to comment.