Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/banzaicloud/service-tools
Prepare your Node.js application for production
https://github.com/banzaicloud/service-tools
express koa kubernetes middleware prometheus shutdown
Last synced: about 2 months ago
JSON representation
Prepare your Node.js application for production
- Host: GitHub
- URL: https://github.com/banzaicloud/service-tools
- Owner: banzaicloud
- License: apache-2.0
- Archived: true
- Created: 2018-07-23T15:10:28.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2022-06-23T05:22:10.000Z (about 2 years ago)
- Last Synced: 2024-07-08T22:12:23.959Z (2 months ago)
- Topics: express, koa, kubernetes, middleware, prometheus, shutdown
- Language: TypeScript
- Homepage: https://banzaicloud.com/blog/nodejs-in-production/
- Size: 1.1 MB
- Stars: 99
- Watchers: 20
- Forks: 10
- Open Issues: 7
-
Metadata Files:
- Readme: README.md
- Contributing: .github/CONTRIBUTING.md
- License: LICENSE
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
Node.js Service Tools
Prepare your Node.js application for production!This library provides common functionalities, like graceful error handling & shutdown, structured JSON logging and several HTTP middleware to make your application truly ready for modern containerised environments, like [Kubernetes](http://kubernetes.io/).
- [Installation](#installation)
- [Usage](#usage)
- [Main exports](#main-exports)
- [`catchErrors(options)`](#catcherrorsoptions)
- [`gracefulShutdown(handlers, options)`](#gracefulshutdownhandlers-options)
- [`logger`](#logger)
- [Use provided logger instead of `console`](#use-provided-logger-instead-of-console)
- [Config](#config)
- [`config.environment`](#configenvironment)
- [`config.pino`](#configpino)
- [Middleware (Koa)](#middleware-koa)
- [`errorHandler(options)`](#errorhandleroptions)
- [`healthCheck(checks, options)`](#healthcheckchecks-options)
- [`prometheusMetrics(options)`](#prometheusmetricsoptions)
- [`requestValidator(options)`](#requestvalidatoroptions)
- [`requestLogger(options)`](#requestloggeroptions)
- [Middleware (Express)](#middleware-express)
- [`errorHandler(options)`](#errorhandleroptions-1)
- [`healthCheck(checks, options)`](#healthcheckchecks-options-1)
- [`prometheusMetrics(options)`](#prometheusmetricsoptions-1)
- [`requestValidator(options)`](#requestvalidatoroptions-1)## Installation
```sh
npm i @banzaicloud/service-tools
# or
yarn add @banzaicloud/service-tools
```## Usage & Examples
This library is written in TypeScript, refer to the published types or the source code for argument and return types.
Examples are available for [Express](https://expressjs.com/) and [Koa](https://koajs.com/) frameworks. Check out the _[examples](/examples)_ folder!
### Main exports
#### `catchErrors(options)`
Catch uncaught exceptions and unhandled Promise rejections. It is not safe to resume normal operation after ['uncaughtException'](https://nodejs.org/api/process.html#process_event_uncaughtexception).
```js
const { catchErrors } = require('@banzaicloud/service-tools')// ...
// the handlers return a Promise
// the handlers are called in order
catchErrors([closeServer, closeDB])// the error will be caught and the handlers will be called before exiting
throw new Error()
```#### `gracefulShutdown(handlers, options)`
Graceful shutdown: release resources (databases, HTTP connections, ...) before exiting. When the application receives `SIGTERM` or `SIGINT` signals, the close handlers will be called. The handlers should return a `Promise`.
```js
const { gracefulShutdown } = require('@banzaicloud/service-tools')// ...
// the handlers return a Promise
// the handlers are called in order
gracefulShutdown([closeServer, closeDB])
```#### `logger`
A [pino](https://github.com/pinojs/pino) structured JSON logger instance configured with [`config.pino`](#config).
```js
const { logger } = require('@banzaicloud/service-tools')logger.info({ metadata: true }, 'log message')
// > {"level":30,"time":,"msg":"log message","pid":0,"hostname":"local","metadata":true,"v":1}
```##### Use provided logger instead of `console`
Globally overwrite the `console` and use the logger provided by the library to print out messages.
```js
const { logger } = require('@banzaicloud/service-tools')console.log('log message')
// > log messagelogger.interceptConsole()
console.log('log message')
// > {"level":30,"time":,"msg":"log message","pid":0,"hostname":"local","v":1}
```### Config
Load configurations dynamically.
#### `config.environment`
Uses the `NODE_ENV` environment variable, with accepted values of: production, development, test.
```js
const { config } = require('@banzaicloud/service-tools')
// validates the NODE_ENV environment variable
console.log(config.environment)
// > { nodeEnv: 'production' }
```#### `config.pino`
Used by the provided [logger](#logger). Uses the `LOGGER_LEVEL` and `LOGGER_REDACT_FIELDS` environment variables. The `LOGGER_LEVEL` can be one of the following: fatal, error, warn, info, debug, trace. `LOGGER_REDACT_FIELDS` is a comma separated list of field names to mask out in the output (defaults to: `'password, pass, authorization, auth, cookie, _object'`).
```js
const pino = require('pino')
const { config } = require('@banzaicloud/service-tools')const logger = pino(config.pino)
logger.info({ metadata: true, password: 'secret' }, 'log message')
// > {"level":30,"time":,"msg":"log message","pid":0,"hostname":"local","metadata":true,"password":"[REDACTED]","v":1}
```### Middleware (Koa)
Several middleware for the [Koa](https://koajs.com/) web framework.
#### `errorHandler(options)`
Koa error handler middleware.
```js
const Koa = require('koa')
const { koa: middleware } = require('@banzaicloud/service-tools').middlewareconst app = new Koa()
// this should be the first middleware
app.use(middleware.errorHandler())
```#### `healthCheck(checks, options)`
Koa health check endpoint handler.
```js
const Koa = require('koa')
const Router = require('koa-router')
const { koa: middleware } = require('@banzaicloud/service-tools').middleware// ...
const app = new Koa()
const router = new Router()// the checks return a Promise
router.get('/health', middleware.healthCheck([checkDB]))app.use(router.routes())
app.use(router.allowedMethods())
```#### `prometheusMetrics(options)`
Koa [Prometheus](https://prometheus.io/) metrics endpoint handler. By default it collects some [default metrics](https://github.com/siimon/prom-client#default-metrics).
```js
const Koa = require('koa')
const Router = require('koa-router')
const { koa: middleware } = require('@banzaicloud/service-tools').middleware// ...
const app = new Koa()
const router = new Router()router.get('/metrics', middleware.prometheusMetrics())
app.use(router.routes())
app.use(router.allowedMethods())
```#### `requestValidator(options)`
Koa request validator middleware. Accepts [Joi](https://github.com/hapijs/joi) schemas for `body` (body parser required), `params` and `query` (query parser required). Returns with `400` if the request is not valid. Assigns validated values to `ctx.state.validated`.
```js
const joi = require('joi')
const qs = require('qs')
const Koa = require('koa')
const Router = require('koa-router')
const bodyParser = require('koa-bodyparser')
const { koa: middleware } = require('@banzaicloud/service-tools').middleware// ...
const app = new Koa()
const router = new Router()const paramsSchema = joi
.object({
id: joi
.string()
.hex()
.length(64)
.required(),
})
.required()const bodySchema = joi.object({ name: joi.string().required() }).required()
const querySchema = joi.object({ include: joi.array().default([]) }).required()
router.get(
'/',
middleware.requestValidator({ params: paramsSchema, body: bodySchema, query: querySchema }),
async function routeHandler(ctx) {
const { params, body, query } = ctx.state.validated
// ...
}
)app.use(bodyParser())
// query parser
app.use(async function parseQuery(ctx, next) {
ctx.query = qs.parse(ctx.querystring, options)
ctx.request.query = ctx.query
await next()
})
app.use(router.routes())
app.use(router.allowedMethods())
```#### `requestLogger(options)`
Koa request logger middleware. Useful for local development and debugging.
```js
const Koa = require('koa')
const { koa: middleware } = require('@banzaicloud/service-tools').middleware// ...
const app = new Koa()
// this should be the second middleware after the error handler
// ...
app.use(middleware.requestLogger())
```### Middleware (Express)
Several middleware for the [Express](https://expressjs.com/) web framework.
#### `errorHandler(options)`
Express error handler middleware.
```js
const express = require('express')
const { express: middleware } = require('@banzaicloud/service-tools').middlewareconst app = express()
// this should be the last middleware
app.use(middleware.errorHandler())
```#### `healthCheck(checks, options)`
Express health check endpoint handler.
```js
const express = require('express')
const { express: middleware } = require('@banzaicloud/service-tools').middleware// ...
const app = express()
// the checks return a Promise
app.get('/health', middleware.healthCheck([checkDB]))
```#### `prometheusMetrics(options)`
Express [Prometheus](https://prometheus.io/) metrics endpoint handler. By default it collects some [default metrics](https://github.com/siimon/prom-client#default-metrics).
```js
const express = require('express')
const { express: middleware } = require('@banzaicloud/service-tools').middleware// ...
const app = express()
app.get('/metrics', middleware.prometheusMetrics())
```#### `requestValidator(options)`
Express request validator middleware. Accepts [Joi](https://github.com/hapijs/joi) schemas for `body` (body parser required), `params` and `query`. Returns with `400` if the request is not valid. Assigns validated values to `req`.
```js
const joi = require('joi')
const express = require('express')
const { express: middleware } = require('@banzaicloud/service-tools').middleware// ...
const app = express()
const paramsSchema = joi
.object({
id: joi
.string()
.hex()
.length(64)
.required(),
})
.required()const bodySchema = joi.object({ name: joi.string().required() }).required()
const querySchema = joi.object({ include: joi.array().default([]) }).required()
app.use(express.json())
app.get(
'/',
middleware.requestValidator({ params: paramsSchema, body: bodySchema, query: querySchema }),
function routeHandler(req, res) {
const { params, body, query } = req
// ...
}
)
```