This lesson is for PRO members.

Unlock this lesson NOW!
Already subscribed? sign in

hapi.js - Logging with good and good-console

2:45 Node.js lesson by

hapi doesn't ship with logging support baked in. Luckily, hapi's rich plugin ecosystem includes everything needed to configure logging for your application. This video will introduce good, a process monitor for hapi, and good-console, a reporter for good that outputs to standard out.

Get the Code Now
click to level up

egghead.io comment guidelines

Avatar
egghead.io

hapi doesn't ship with logging support baked in. Luckily, hapi's rich plugin ecosystem includes everything needed to configure logging for your application. This video will introduce good, a process monitor for hapi, and good-console, a reporter for good that outputs to standard out.

Avatar
John

When I try to run this code I get the following:

Invalid monitorOptions options child "reporters" fails because ["reporters" must be an object]

Any ideas?

Avatar
Rahul

I am having the same problem. I tried googling it and found responses indicating a version mismatch between good and good-console packages. I tried having the same versions for both the packages and still get the same error.

In reply to John
Avatar
Rahul

The versions that do work well with each other are the ones mentioned in the video, good@6.4.0 and good-console@5.1.0

In reply to Rahul
Avatar

I'm not off to a good start here– I'm seeing the same Error: Invalid monitorOptions options child "reporters" fails because ["reporters" must be an array] message that others are reporting. I've even tried specifying exact versions to match the package.json in the video.

"good": "6.4.0",
"good-console": "5.1.0",
"hapi": "11.0.3"

$ node -v 
> v6.2.0
Avatar
Mike

Your Node.js version may be the issue. Hapi before v13.4 is known not to be compatible with Node.js v6.

In reply to
Avatar
Mike

I just cut and pasted the example code with the same hapi, good and good-console versions as you, and tried with Node.js v5.2 and it worked without an issue.

In reply to
Avatar
Daniel Minshew

I also got this error.

As of a few weeks ago (today being June 23rd), the current version of Good is at 7.0.1.

The maintainers seem to have significantly changed the way plugin configurations are defined, so instead of reporters being an array, like it is in the video, you now pass it keys with array values. Based on the example from their readme, the new options object should be something like:

let goodOptions = {
  reporters: {
    console: [{
            module: 'good-squeeze',
            name: 'Squeeze',
            args: [{ log: '*', response: '*' }]
        }, {
            module: 'good-console'
        }, 'stdout'],
  }
}

That seems to work in Node 4+

cheers!

In reply to Mike
Avatar
Vincent

I am new to programming, but i am tired to waste time on tutorial that never work because of out of date stuff. I have the last version of all the things (node 6 and
"dependencies": {
"good": "^7.0.1",
"good-console": "^6.1.2",
"hapi": "^13.5.0"
})

Avatar
Roman

let goodOptions = {
reporters: {
console: [{
module: 'good-console'
}, 'stdout'],
}
}

Its work

Avatar
Charles

Correct ;) in this lesson, the goodOptions object should be:

let goodOptions = {
  reporters: {
    console: [
      {
        module: 'good-console',
        args: [{ log: '*', response: '*' }]
      },
      'stdout'
    ]
  }
}

The good-squeeze transform stream isn't needed

cheers!

In reply to Daniel Minshew
Avatar
Julia

Thanks Charles!

In reply to Charles
Avatar
Joseph

This is the working solution goodOptions variable for the current version of Node. Thank You

In reply to Roman
Avatar
Dave Kingsnorth

Thanks!

In reply to Charles
Avatar
Chris Kobrzak

I was trying to get the Good plugin to filter log messages by event type, e.g. to exclude info-level statements, the same way it's been demonstrated in the video.

But when I tried the solution provided by Charles and others, I realised the stuff assigned to the args config key gets completely ignored. If you go

args: [{ log: ['error'], response: '*' }]

you will still be seeing non-error log entries.

So I've poked around the Good plugins documentation and examples and the conclusion is you do need Squeeze to gain more granular control over what actually gets logged.

The configuration below seems to do the job:

let goodOptions = {
  reporters: {
    console: [
      {
        module: 'good-squeeze',
        name: 'Squeeze',
        args: [{
          log: ['error', 'warn'],
          response: '*'
        }]
      }, {
        module: 'good-console',
        args: [{ format: 'YYYYMMDD/HHmmss.SSS' }]
      },
      'stdout'
    ]
  }
}

Please note, I've included the format setting for illustrative purposes only. This is just to point out the config passed to args needs to conform to the good-console config object format (see the project's README) and not the events object format expected by the Squeeze constructor.

In reply to Charles

Out of the box, Hapi doesn't ship with logging support beyond basic console log. If I make a request to a Hapi server, no feedback shows up in the console. Hapi does, however, have a rich ecosystem of modules and plugins that enhance Hapi in numerous ways, one of which is logging.

I'm going to go ahead and install a couple of modules, good and good-console. Good is a process monitor for Hapi that listens for different event types, then passes those events on to reporters. Good-console is a good reporter that outputs events to standard out.

Now that they are installed, I'll create an options object that will be used to configure good. The only required option is reporters, which is an array of objects that will configure each reporter. I'm only going to use one reporter, that's good-console. There will only be one item in my array.

I need to tell good which event to pass on to good-console. In this case, I'm only listening for log and response event types. Next, I need to register the good plugin with my server using server.register, passing in a reference to the good module and the options I specified above.

Server.register requires a callback as its last argument. The body of this callback is where I should complete my server setup, including defining routes and starting the server.

Now that good is configured, let's see how it shows up in the terminal. I'll start the app and refresh the browser a few times. We now see events tagged with response coming through to the terminal.

Speaking of tagged events, let's look at a couple of examples of how we can log tagged events. I'll add a couple of server log calls to my root route. The first argument should be a string or array of strings, each containing a tag. The second argument is the message to log. An error and info log should do.

After restarting the server and refreshing the browser, we can see the two new events in the terminal, one tagged with error and one tagged with info. Now suppose I don't want to show log events tagged with info in my terminal.

Instead of setting the log config to star, I can set it to an array of tags instead. Only events with those tags will be passed to the reporter. Now when I start the app and refresh the browser, only the logged events with an error tag show up.

HEY, QUICK QUESTION!
Joel's Head
Why are we asking?