divillysausages.com

Hacking how Node.js launches in Visual Studio Code

I've been using Visual Studio Code lately, working on getting my socket sever, Sir, off its feet. As any good dev will tell you, the first step for good debugging is good logging, so I was on the search for a small, fast Node.js logging module.

And thus I came across Bunyan.

Bunyan does a lot of things, but when you run it, a simple

log.info( "Hello world" );

becomes

{"name":"Sir","hostname":"divillysausa-PC","pid":2244,"level":30,"msg":"Hello world!","time":"2015-07-12T21:47:30.576Z","v":0}

in your console.

While undoubtedly useful, it also makes actually reading them a bit awkward. Happily, they've thought of this, and have included a CLI that takes that output and transforms it to:

[2015-07-12T22:12:45.698Z]  INFO: Sir/4900 on divillysausa-PC: Hello world!

They've even colour coded it for your convenience!

Where Visual Studio Code comes in

All of this is relevant to the title, I promise.

In order to get this wonderful output, you simply need to change your node call from

node app.js

to

node app.js | "node_modules/.bin/bunyan"

In essence, what you're doing here is piping the output coming from node and sending it to bunyan.

So, how do you actually do that?

The first time you hit F5 to launch your app, Visual Studio Code will create a launch.json file for you that looks like this:

{
	"version": "0.1.0",
	// List of configurations. Add new configurations or edit existing ones.  
	// ONLY "node" and "mono" are supported, change "type" to switch.
	"configurations": [
		{
			// Name of configuration; appears in the launch configuration drop down menu.
			"name": "Launch app.js",
			// Type of configuration. Possible values: "node", "mono".
			"type": "node",
			// Workspace relative or absolute path to the program.
			"program": "app.js",
			// Automatically stop program after launch.
			"stopOnEntry": false,
			// Command line arguments passed to the program.
			"args": [],
			// Workspace relative or absolute path to the working directory of the program being debugged. Default is the current workspace.
			"cwd": ".",
			// Workspace relative or absolute path to the runtime executable to be used. Default is the runtime executable on the PATH.
			"runtimeExecutable": null,
			// Optional arguments passed to the runtime executable.
			"runtimeArgs": [],
			// Environment variables passed to the program.
			"env": {},
			// Use JavaScript source maps (if they exist).
			"sourceMaps": false,
			// If JavaScript source maps are enabled, the generated code is expected in this directory.
			"outDir": null
		}, 
		{
			"name": "Attach",
			"type": "node",
			// TCP/IP address. Default is "localhost".
			"address": "localhost",
			// Port to attach to.
			"port": 4000,
			"sourceMaps": false
		}
	]
}

I tried adding my | "node_modules/.bin/bunyan" line first in args, then runtimeArgs, then env, before finally realising that these were being passed to your app.js program rather than to node itself. Then I tried modifying the program parameter to read "app.js | \"node_modules/.bin/bunyan\"", but it complained that the file didn't exist :)

The key to getting this hack working is with the runtimeExecutable property. By default it's null, which means that VSC will search in your PATH directory for node. If you specify a path, then VSC will run that instead.

With that in mind, I created a small bat file (I'm on Windows), nodeWithBunyan.bat:

@echo off
node %* | "node_modules/.bin/bunyan" -o short

Basically, what it's doing is calling node, passing all the parameters that VSC is passing (%*), before piping the output through bunyan (the -o short at the end is just telling bunyan to use its "short" output mode, which is even more concise). As we're passing all the VSC parameters, we even get to keep debugging.

If you're working in a bash environment, then I think the equivalent is

node $@ | ./node_modules/.bin/bunyan -o short

Back in VSC, we replace the runtimeExecutable property so it reads

"runtimeExecutable": "./nodeWithBunyan.bat"

hit F5, and *jazzhands*!

Final Bunyan output

If, for some reason, you want to switch between the default launch and the new, snazzy one, you can simply create another config, add it to the configurations array in your launch.json file, then choose between them in dropdown menu on the Debug tab.

You can also use this technique if, for example, you want to set the DEBUG or NODE_DEBUG environment variables when launching:

NODE_DEBUG=http,fs,timers node %*

Enjoy!

Comments

Baldur

I was trying to figure out how I should feed my 50+ environment variables (stored in a file) into the debug session without manually adding them to launch.json. This post was very helpful. Thanks :)

Mark Norgate

Hooray! I've been wrestling with a webpack dev server issue and your .bat file solution is inspired. Solved my problem. Thanks!

Avner

Great post and thank you very much :)

FYI in Linux this would be an .sh file with contents :

#!/bin/bash
node "$@" | bunyan

Don't forget to chmod +x yourFile.sh

Thanks again !

Felipe Kautzmann

Awesome! Works great, which it could be colored :-)

Chris

This is awesome thanks!

Lifeng

thanks a lot, and it is a great job

Submit a comment

* indicates required