Custom Development

Debugging in Node

Doug DiFilippo

Using a proper debugger was something I avoided in Node for the first few months. I made some assumptions that it would be hard to set up or cumbersome to use so I plugged away with my `console.log` statements when I needed to track down a bug. When I finally decided to try it out I was pleasantly surprised. Not only was it extremely easy to get started, but I also had options!

Quick aside: I am a huge proponent of testing your code! Unit tests can greatly reduce your need to fire up the debugger by exposing bugs or incorrect assumptions early and in isolation. However, tests should not be used as an excuse to hide from the debugger. Even with tests in place I have still encountered instances where I find great value in seeing code execute. For this, there is nothing better than attaching a debugger and stepping through the code.

In this post I’ll discuss two options for debugging your NodeJS code. The first uses the core debugger from the console. The second utilizes the Chrome Developer Tools as part of an open source project called node-inspector.

Debugging with the Console

Node actually ships with a built in debugger client for V8. You can read about it in the documentation, but we’ll walk through an example to show how easy it is. I’ve set up a very simple script so we can follow along with the same code. To get started you’ll need to clone the repository:
git clone https://github.com/dougflip/debugging-node-blog.git
In the console-debugging directory open program.js in an editor and have a look at the code. It is only a few lines long and is very basic. What may be new to you is the debugger statement on line 1. This is an extremely simple way to instruct the debugger to stop on a particular line. In our case, running the script in debug mode will cause the debugger to pause on the first line.

Run the following command from the console:
node debug console-debugging/program.js

This will display something similar to:
< debugger listening on port 5858
connecting... ok
break in console-debugging/program.js:1
1 debugger;
2 var example = "this is a string";
3 printExampleText();
debug>

Our debugger statement on line 1 has caused execution to pause. The console does a pretty nice job of visually displaying the current state of the application. From here, the client exposes quite a few commands to allow us to navigate our code. If you are following along, try typing `help` to display a listing of these options.

Let’s continue along our program to see the debugger in action. Type the `n` command to tell the debugger to move to the next line. You should see something similar to the following:

1 debugger;
2 var example = "this is a string";
3 printExampleText();
4

We can see the code has advanced to line 2. Type `n` one more time to move to the next line again:

1 debugger;
2 var example = "this is a string";
3 printExampleText();
4
5 example = "updated string";

The code is about to call a function that is defined further down in the source. No debugger would be complete without providing a way to “step in” to this method and Node is no exception! Type `s` and you will see the following:

10
11 function printExampleText(){
12 console.log("========================");
13 console.log(example);
14 console.log("========================");

As was mentioned above, we have now stepped into the invocation of the `printExampleText` function. Try typing `bt` to see a “backtrace” of the current execution:

#0 program.js:12:2
#1 program.js:3:1

This is the debugger telling us both where we are and where we have come from. Speaking of where we came from, the remaining code in `printExampleText` does not have anything interesting so lets avoid stepping through it. Type `o` to “step out” of this method and back to our previous point in time:

3 printExampleText();
4
5 example = "updated string";
6 printExampleText();
7

Another interesting option provided by the debugger is evaluating code. From our current debugger output we can see that we are about to update the value of the `example` variable, but we may not remember what it stores right now. We can ask the debugger to tell us! Type `repl`, press enter and then type `example`, and press enter:

debug< repl
Press Ctrl + C to leave debug repl
> example
'this is a string'

We can evaluate more than just our own variables too. Try typing `process.argv` or `console` for example. When you are finished with the repl simply press ctrl+c to return to the debugger.

At this point we have touched on the basics of the built in debugger. Remember, the `help` command lists all of available options so feel free to experiment. When you are finished, pressing ctrl+c (twice) will exit the debugger.

Debugging with Node Inspector

The built in debugger is great for simple scripts, but when you want to debug a larger application it can feel a little limiting. Next, we’ll take a look at a project that utilizes the powerful Blink (think Chrome) developer tools to visually debug your NodeJS application. before we get started though, lets make sure our dependencies are installed. Run the following at the console:

npm install

The server.js file located in the http-debugging directory is a simple web server that listens on port 9000 for requests. Let’s first fire up the web server with debugging enabled. Run this from the console:

node --debug http-debugging/server.js

You should see something similar to the following confirming that both the debugger and server are operational:

debugger listening on port 5858
Server running port 9000

Alright, now for the fun part - debugging! Normally, I install node-inspector globally, but for simplicity it is listed as a dependency in package.json. The npm install command (run above) installs node-inspector into the local node_modules directory. We need to run node-inspector in a new console window because our web server is already running in the existing window. Open a new console and run the following:

node_modules/.bin/node-inspector

Take note of the last line presented at the console:

Visit http://127.0.0.1:8080/debug?port=5858 to start debugging.

Open Chrome and navigate to the provided url. This should take you into the debugger itself. So what do we do now? Let’s start with setting up a breakpoint. Click on line 4 and you should see a blue arrow appear. Additionally, you will see an entry listed in the “Breakpoints” window on the right of the screen.

set-breakpoint

Open a new tab in Chrome and navigate to localhost:9000 - our web server. You’ll notice that the page is “hanging” as it tries to load. Switch back to the node inspector tab in Chrome and you will see why. The debugger is paused on the break point we established on line 4.

active-breakpoint

This is where a more visual debugger really stands out. Take a moment to familiarize yourself with the panels that are available to you. There is a Watch Expressions window where you can track variable values. A Call Stack window to show the current execution path. A Scope Variables window which allows you to inspect locals. You even have access to a console window which allows you to evaluate code while debugging.

To actually step code, try pressing F10 to move to the next line. You should see the blue highlighted line advance to line 5. If you are feeling adventurous, press F11 to step into the end method of the Response object. To step out you can press shift + F11 and return back to our module. Pressing F8 resumes execution and allows the response be written back to the browser. If you switch back to your other Chrome tab you should see that the browser rendered the page.

The best part is we can do this as many times as needed to track down an issue. If you refresh localhost:9000 you will see that the breakpoint is activated again. Remember, this project is based on the Chrome Dev Tools, so your knowledge from client side debugging should carry over. For example, try pressing ctrl + o to open a source file or ctrl + shift + f to search across all sources. You even use escape to open the quick console to evaluate code.

Debug!

Hopefully this gives you a good starting point for debugging your own NodeJS scripts and applications. Both the console debugger and Node Inspector provide more features than discussed here. I definitely encourage you to read the documentation and experiment on your own. Happy debugging!

References and Further Reading

http://nodejs.org/api/debugger.html
https://github.com/node-inspector/node-inspector
https://developers.google.com/chrome-developer-tools/
https://developers.google.com/chrome-developer-tools/docs/javascript-debugging

Doug DiFilippo
ABOUT THE AUTHOR

Summa Alumni