• Stars
    star
    148
  • Rank 240,989 (Top 5 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created about 8 years ago
  • Updated 9 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

🌲 Hapi plugin for the Pino logger

hapi-pino  Tests Status

Hapi plugin for the Pino logger. It logs in JSON for easy post-processing.

Hapi and Pino versions supported by hapi-pino

hapi-pino hapi pino
v12.x v21 v8
v11.x v20 v8
v9.x - v10.x v20 v7
v8.x v18, v19, v20 v6
v6.x v17, v18, v19 v5
v5.x v17, v18 v5
v3.x - v4.x v17 v4
v2.x v16 v4

Install

npm install hapi-pino

Usage

'use strict'

const Hapi = require('@hapi/hapi')

async function start () {
  // Create a server with a host and port
  const server = Hapi.server({
    host: 'localhost',
    port: 3000,
    debug: false, // disable Hapi debug console logging
  })

  // Add the route
  server.route({
    method: 'GET',
    path: '/',
    handler: async function (request, h) {
      // request.log is HAPI standard way of logging
      request.log(['a', 'b'], 'Request into hello world')

      // you can also use a pino instance, which will be faster
      request.logger.info('In handler %s', request.path)

      return 'hello world'
    }
  })

  await server.register({
    plugin: require('hapi-pino'),
    options: {
      // Redact Authorization headers, see https://getpino.io/#/docs/redaction
      redact: ['req.headers.authorization']
    }
  })

  // also as a decorated API
  server.logger.info('another way for accessing it')

  // and through Hapi standard logging system
  server.log(['subsystem'], 'third way for accessing it')

  await server.start()

  return server
}

start().catch((err) => {
  console.log(err)
  process.exit(1)
})

API

hapi-pino goal is to enable Hapi applications to log via pino. To enable this, it decorates both the server and the request. Moreover, hapi-pino binds to the Hapi events system as described in the "Hapi events" section.

Options

options.logPayload: boolean

Default: false

When enabled, add the request payload as payload to the response event log.

options.logQueryParams: boolean

Default: false

When enabled, add the request query as queryParams to the response event log.

options.logPathParams: boolean

Default: false

When enabled, add the request params as pathParams to the response event log.

options.logRouteTags: boolean

Default: false

When enabled, add the request route tags (as configured in hapi route.options.tags) tags to the response event log.

options.log4xxResponseErrors: boolean

Default: false

When enabled, responses with status codes in the 400-500 range will have the value returned by the hapi lifecycle method added to the response event log as err.

options.logRequestStart: boolean | (Request) => boolean

Default: false

Whether hapi-pino should add a log.info() at the beginning of Hapi requests for the given Request.

For convenience, you can pass in true to always log request start events, or false to disable logging request start events

Note: when logRequestStart is enabled and getChildBindings is configured to omit the req field, then the req field will be omitted from the request completed log event but the req field will always be there for the start log. This behavior is useful if you want to separate requests from responses and link the two via requestId (frequently done via headers['x-request-id']) , where "request start" only logs the request and a requestId, and request completed only logs the response and the requestId.

options.customRequestStartMessage

Default: (request) => { return 'request start' }

Set to a function (request) => { /* returns message string */ }. This function will be invoked at each request received, setting the "msg" property to the returned string. If not set, default value will be used.

options.logRequestComplete: boolean | (Request) => Boolean

Default: true

Whether hapi-pino should add a log.info() at the completion of Hapi requests for the given Request.

For convenience, you can pass in true to always log request complete events, or false to disable logging request complete events

options.customRequestCompleteMessage

Default: (request, responseTime) => { return `[response] ${request.method} ${request.path} ${request.raw.res.statusCode} (${responseTime}ms)` }

Set to a function (request, responseTime) => { /* returns message string */ }. This function will be invoked at each completed request, setting the "msg" property to the returned string. If not set, default value will be used.

options.customRequestErrorMessage

Default: (request, err) => { return err.message }

Set to a function (request, err) => { /* returns message string */ }. This function will be invoked at each failed request, setting the "msg" property to the returned string. If not set, default value will be used.

options.customRequestStartLevel: pino.Level

Default: 'info'

The log level to use for request start events.

options.customRequestCompleteLevel: pino.Level

Default: 'info'

The log level to use for request complete events.

options.customRequestErrorLevel: pino.Level

Default: 'error'

The logging level to use for request-error events.

options.stream Pino.DestinationStream

Default: process.stdout

the binary stream to write stuff to

options.tags: ({ [key in pino.Level]?: string })

Default: exposed via hapi-pino.levelTags

A map to specify pairs of Hapi log tags and levels. The tags trace, debug, info, warn, and error map to their corresponding level. Any mappings you supply take precedence over the default mappings.

options.allTags: pino.Level

Default: 'info'

The logging level to apply to all tags not matched by tags

options.serializers: { [key: string]: pino.SerializerFn }

An object to overwrite the default serializers. You can but don't have to overwrite all of them.

Example:
To redact the authorization header in the logs:

{
  req: require('pino-noir')(['req.headers.authorization']).req
  res: ...
  err: ...
}

options.wrapSerializers: boolean

Default: true

When false, custom serializers will be passed the raw value directly.

Example: If you prefer to work with the raw value directly, or you want to honor the custom serializers already defined by options.instance, you can pass in options.wrapSerializers as false:

{
  wrapSerializers: false,
  serializers: {
    req (req) {
      // `req` is the raw hapi's `Request` object, not the already serialized request from `pino.stdSerializers.req`.
      return {
        message: req.foo
      };
    }
  }
}

options.instance: Pino

Uses a previously created Pino instance as the logger. The instance's stream and serializers take precedence.

options.logEvents: string[] | false | null

Default: ['onPostStart', 'onPostStop', 'response', 'request-error'] (all events)

Takes an array of strings with the events to log.

Set to false/null to disable all events. Even though there is no request-error Hapi Event, the options enables the logging of failed requests.

options.mergeHapiLogData: boolean

Default: false

When enabled, Hapi-pino will merge the data received from Hapi's logging interface (server.log(tags, data) or request.log(tags, data)) into Pino's logged attributes at root level. If data is a string, it will be used as the value for the msg key. When disabled, Hapi-pino will keep data under a data key.

Example:

server.log(['info'], {hello: 'world'})

// with mergeHapiLogData: true
{ level: 30, hello: 'world', ...}

// with mergeHapiLogData: false (Default)
{ level: 30, data: { hello: 'world' }}

options.getChildBindings: (request) => { [key]: any }

Default: () => { req: Request }, which automatically adds the request to every pino log call

Takes a function with the request as an input, and returns the object that will be passed into pinoLogger.child().

Note: Omitting req from the child bindings will omit it from all logs, most notably the response log, except "request start".

options.ignorePaths: string[]

Takes an array of string routes and disables logging for each. Useful for health checks or any route that does not need logging.

Example:
Do not log for /health route

ignorePaths: ['/health']

options.ignoreTags: string[]

Takes an array of string tags and disables logging for each. Useful for health checks or any route that does not need logging.

Example:
Do not log for route with healthcheck tag

ignoreTags: ['healthcheck']

options.ignoreFunc: (options, request) => boolean

Takes a function that receives the plugin options and the request as parameters, and returns a boolean. Logging will be disabled if the return value is true. Useful for scenarios where the ignorePaths or ignoreTags options can't achieve what is intended.

Example: Do not log routes relative to static content

ignoreFunc: (options, request) => request.path.startsWith('/static')

Note: if ignoreFunc is used, the other two options that can be used to ignore / disable logging (ignorePaths and ignoreTags) are effectively discarded. So ignoreFunc can be seen a more advanced option. For instance, you can easily re-implement the ignorePaths functionality as follows:

ignoreFunc: (options, request) => myIgnorePaths.include(request.path)

(where myIgnorePaths would be an array with paths to be ignored).

options.ignoredEventTags: object[]

Takes an array of object tags and disables logging for each. Useful for debug logs or any other tags that does not need logging.

Default: { log: '*', request: '*' }, Logs all the events emitted by server.log and request.log without filtering event tags

Example: Do not log the events for DEBUG and TEST tag

ignoredEventTags: { log: ['DEBUG', 'TEST'], request: ['DEBUG', 'TEST'] }
server.log(['DEBUG'], 'DEBUG')

options.level: Pino.Level

Default: 'info'

Set the minimum level that Pino should log out. See Level.

Example:
Configure Pino to output all debug or higher events:

level: 'debug'

options.redact: string[] | pino.redactOptions

Path to be redacted in the log lines. See the log redaction docs for more details.

Server Decorations

hapi-pino decorates the Hapi server with server.logger, which is an instance of pino. See its doc for the way to actual log.

Request Decorations

hapi-pino decorates the Hapi request with:

  • request.logger, which is an instance of pino bound to the current request, so you can trace all the logs of a given request. See pino doc for the way to actual log.

Hapi Events

hapi-pino listens to some Hapi events:

  • 'onRequest', to create a request-specific child logger
  • 'response', to log at 'info' level when a request is completed
  • 'request', to support logging via the Hapi request.log() method and to log at 'warn' level when a request errors or when request received contains an invalid accept-encoding header, see tags and allTags options.
  • 'log', to support logging via the Hapi server.log() method and to log in case of an internal server event, see tags and allTags options.
  • 'onPostStart', to log when the server is started
  • 'onPostStop', to log when the server is stopped

Acknowledgements

This project was kindly sponsored by nearForm.

License

MIT

More Repositories

1

joi

The most powerful data validation library for JS
JavaScript
20,598
star
2

hapi

The Simple, Secure Framework Developers Trust
JavaScript
14,458
star
3

boom

HTTP-friendly error objects
JavaScript
2,928
star
4

lab

Node test utility
JavaScript
738
star
5

iron

Encapsulated tokens (encrypted and mac'ed objects)
JavaScript
633
star
6

bell

Third-party login plugin for hapi
JavaScript
624
star
7

good

hapi process monitoring
JavaScript
525
star
8

nes

WebSocket adapter plugin for hapi routes
JavaScript
500
star
9

catbox

Multi-strategy object caching service
JavaScript
495
star
10

hoek

Node utilities shared among the extended hapi universe
JavaScript
481
star
11

wreck

HTTP Client Utilities
JavaScript
382
star
12

glue

Server composer for hapi.js
JavaScript
245
star
13

inert

Static file and directory handlers for hapi.js
JavaScript
238
star
14

code

Assertion library
JavaScript
233
star
15

cookie

Cookie authentication plugin
JavaScript
228
star
16

shot

Injects a fake HTTP request/response into your node server logic
JavaScript
197
star
17

vision

Templates rendering support for hapi.js
JavaScript
195
star
18

cryptiles

General purpose crypto utilities
JavaScript
181
star
19

bounce

Selective error catching and rewrite rules
JavaScript
177
star
20

crumb

CSRF crumb generation and validation for hapi
JavaScript
171
star
21

h2o2

Proxy handler for hapi.js
JavaScript
165
star
22

bourne

JSON.parse() drop-in replacement with prototype poisoning protection
JavaScript
162
star
23

basic

Basic authentication plugin
JavaScript
148
star
24

yar

A hapi session manager
JavaScript
133
star
25

topo

Topological sorting with grouping support
JavaScript
110
star
26

podium

Event emitter with async features
JavaScript
88
star
27

joi-date

Joi extensions for dates
JavaScript
83
star
28

heavy

Measure process load
JavaScript
74
star
29

good-console

Console reporting for Good process monitor
JavaScript
73
star
30

catbox-redis

Redis adapter for catbox
JavaScript
69
star
31

accept

HTTP Accept-* headers parsing
JavaScript
52
star
32

hapi.dev

The hapi.dev developer portal
Vue
51
star
33

good-squeeze

Simple transform stream for event filtering with good.
JavaScript
49
star
34

scooter

User-agent information plugin for hapi
JavaScript
46
star
35

bossy

Command line options parser
JavaScript
45
star
36

b64

Base64 streaming encoder and decoder
JavaScript
39
star
37

call

HTTP Router
JavaScript
37
star
38

jwt

JWT (JSON Web Token) Authentication
JavaScript
35
star
39

pez

Multipart parser
JavaScript
34
star
40

catbox-memory

Memory adapter for catbox
JavaScript
33
star
41

address

Validate email addresses
TypeScript
32
star
42

items

Bare minimum async methods
JavaScript
30
star
43

oppsy

An EventEmitter useful for collecting hapi server ops information
JavaScript
25
star
44

subtext

HTTP payload parser
JavaScript
24
star
45

eslint-config-hapi

Shareable ESLint config for the hapi ecosystem
JavaScript
22
star
46

eslint-plugin

ESLint plugin containing hapi style guide rules
JavaScript
21
star
47

statehood

HTTP State Management Utilities
JavaScript
20
star
48

mimos

Mime database interface
JavaScript
19
star
49

nigel

Boyer–Moore–Horspool algorithms
JavaScript
15
star
50

teamwork

Wait for multiple events
JavaScript
14
star
51

formula

Math and string operations
JavaScript
14
star
52

catbox-memcached

Memcached adapter for catbox
JavaScript
11
star
53

content

HTTP Content-* headers parsing
JavaScript
8
star
54

vise

Treat multiple buffers or strings as one
JavaScript
7
star
55

pinpoint

Return the filename and line number of the calling function
JavaScript
6
star
56

log

hapi logging plugin
JavaScript
6
star
57

.github

Default organization policies
6
star
58

rule-no-arrowception

ESLint rule preventing arrow functions that implicitly create arrow functions
JavaScript
5
star
59

beam

HTTP benchmark API
JavaScript
4
star
60

file

File utilities
JavaScript
4
star
61

joi.dev

Vue
2
star
62

validate

hapi core internal validation support
JavaScript
2
star
63

catbox-object

Object cache adapter for catbox
JavaScript
2
star
64

assets

Images and other community resources
2
star
65

rule-capitalize-modules

ESLint rule to enforce the capitalization of imported module variables
JavaScript
2
star
66

rule-for-loop

hapi style guide ESLint rule dealing with for loops
JavaScript
1
star
67

rule-no-var

ESLint rule to enforce the usage of var declarations only in try-catch scope
JavaScript
1
star
68

ammo

HTTP Range processing utilities
JavaScript
1
star
69

rule-scope-start

ESLint rule to enforce new line at the beginning of function scope
JavaScript
1
star