npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

maikai

v0.8.1

Published

RFC-compliant health check middleware for HTTP APIs and microservices written in Node

Downloads

1,296

Readme

Node Health Middleware

Maikaʻi (Hawaiian) - (stative) to be well, fine, in a state of goodness

NPM Version Build Status Coverage Status

Node health middleware is an unobtrusive module that you can easily integrate into your API code written in Node. This module is targeting multiple frameworks, while currently supporting: Express.js, Koa.js and vanilla Node http.

Maikai has full support for Kubernetes Readiness and Liveness Probes, making it a great solution for implementing healthchecks in your microservices.

While the module is extremely configurable, you can also use it out of the box, with zero configuration. If you use default configuration, health check endpoint will be mounted at /health URI path and will respond with HTTP 200 as long as your Node server is up. In more involved setups you can add all kinds of custom health checks (e.g. database) and expose wide variety of metrics as defined in the healthcheck draft RFC.

Implementation Status

Immediate Priority

  • [x] Express/Connect
  • [x] Koa
  • [x] Pure Node, no frameworks

Open to Community Contributions

  • [ ] Sails.js
  • [ ] hapi.js
  • [ ] Restify

Installation

> npm i -S maikai

Usage

Examples for Express.js

Basic Usage:

const healthcheck = require('maikai');

// Add middleware to your Express app:
app.use(healthcheck().express());
app.listen(3535);

Advanced usage with custom health checker:

const healthcheck = require('maikai');
const check = healthcheck();

// If you need/want to add custom health checker functions:
check.addCheck('cassandra', 'timeout', async () => {
    // Returning fake data here, for brevity, but you
    // could be making DB calls, to check its health, making
    // API calls to downstream dependencies, or anything else
    // that your health check logic requires.
    return {
        status : 'pass',
        metricValue: 250,
        metricUnit: "ms"
    };
}, {minCacheMs: 10000});

// Add middleware to your Express app:
app.use(check.express());
app.listen(3535);

Caching and Backend Protection

Please note the fourth argument {minCacheMs: 10000} in the .addCheck() call for the cassandra metric. It sets minimal cache duration, indicated in milliseconds. Meaning: you can tell the health check endpoint to only run an expensive, downstream healthcheck probe against Cassandra every 10 seconds (10,000 milliseconds), at most!

Even if your health probing infrastructure (e.g. Kubernetes) calls your health check endpoint very frequently, they will only trigger the calls you deemed light enough. For more heavy calls (e.g. DB calls like that to Cassandra), Maikai will serve cached values, avoiding stress on downstream systems.

This unique capability of Maikai is critical for preventing health monitoring software from DDOS-ing your valuable systems. Throttling calls in Maikai itself keeps both your infrastructure, as well as you custom healtcheck code's logic straightforward, operations inexpensive, while still providing very timely health information about more lightweight metrics.

Example for Koa.js

const Koa = require('koa');
const app = new Koa();
const Router = require('koa-router');
const router = new Router();
  
const healthcheck = require("maikai");
const check = healthcheck();

router.get('/hello', (ctx, next) => {
    ctx.body = 'Hello, World!';
});

app.use(check.koa())
   .use(router.routes())
   .use(router.allowedMethods());

app.listen(3535);

Example for no-Frameworks, Pure Node Implementation

const http = require('http');
const healthcheck = require('maikai');

http.createServer( (request, response) => {
  const check = healthcheck();
  const checkHandler = check.http();
  const isHealthCheckCall = checkHandler(request, response);
  if (isHealthCheckCall) return;

  response.end("HELLO! This is pretty amaziiiiing");
}).listen(3535);
console.log('Server running on port 3535');

Kubernetes Liveness and Readiness Probes

When implementing Kubernetes Liveness and Readiness probes you may decide that each one of those probes should be at different URI paths. Implementing this is very easy with Maikai. Let's assume your liveness probe is deployed at '/health', while your readiness probe is deployed at '/ping':

const express = require('express');
const app = express();
const healthcheck = require("maikai");

// For Liveness Probe, defaults may be all you need. 
const livenessCheck = healthcheck();
app.use(livenessCheck.express());

// For Readiness probe, we override the path and provide more checks:
const readinessCheck = healthcheck({"path" : "/ping"});
readinessCheck.addCheck('cassandra', 'timeout', dbQueryCheck);
app.use(readinessCheck.express());

// Implementation of the dbQueryCheck:
async function dbQueryCheck() {
    // ... implementation of checking your database works
}

// -- rest of your server startup logic

function responder(req, res) {
    res.send('Hello Worldie!');
}

app.get('/', responder);

app.listen(3535, () => console.log('Example app listening on port 3535!'));

Customizations

By default the health endpoint is mounted at the default /health path. However you can modify it by setting NODE_HEALTH_ENDPOINT_PATH environmental variable to anything you wish.

The biggest customization opportunity, when using Maikai, is the ability to develop custom health checkers. The overall health of the service is the sum of all checkers. Meaning: if all of them "pass" then the service is "pass" (healthy) as well, if any of them is "warn" the overall health is "warn" as well and if any of them "fail", the health of the service is a "fail" as well. Next section explains how you can go about writing custom health checks.

Writing Custom Health Checkers

Every APi and application is different. The kind of metrics you may need to track can be different from what others do. This module is all about being flexible, while being designed for consistency and RFC-compliance. Adding custom health checks is very easy. All you need to do is to call an addCheck() method with the name of the component and metrics that the check is related to, as well as pass a health check executor function that will be executed to retrieve the health values. Executor function must be a function that returns a fresh promise at every execution (usually: it is an ES2018 async function).

The return JSON object MUST have status field that is either 'pass', 'warn' or 'fail' and MAY have following additional fields:

  • componentId
  • componentType
  • metricValue
  • metricUnit
  • status
  • time
  • output

Roadmap

  1. [x] Cached checks - expensive checks, like database calls, should not be called every time a monitoring service decides to invoke health check endpoint to prevent accidental self-denial-of-service outages. Ability to cache expensive checks is important for a quality health check system.

  2. Circuit Breaking - if health check is calling a downstream service and sees it failing, circuit-breaking should be implemented to prevent cascading failures.

License

MIT