Last week, NodeSource
(where I work) announced a new product,
N|Solid
.
N|Solid
is a platform built on Node.js that provides a number of enhancements
to improve troubleshooting, debugging, managing, monitoring and securing your
Node.js applications.
N|Solid provides a
gorgeous
web-based console
to monitor/introspect your applications,
but also allows you to introspect your Node.js applications, in the same way,
at ye olde command line.
Let's explore that command line thing!
installing N|Solid Runtime
In order to introspect your Node.js applications, you'll run them
with the N|Solid Runtime,
which is shaped similarly to a typical
Node.js runtime, but provides some additional executables.
To install N|Solid Runtime, download
and unpack an N|Solid Runtime tarball
(.tar.gz
file) from the
N|Solid download site.
For the purposes of this blog post, you'll only need to download
N|Solid Runtime; the additional downloads
N|Solid Hub and
N|Solid Console are not required.
On a Mac, you can alternatively download the native installer .pkg
file.
If using the native installer, download the .pkg
file, and then
double-click the downloaded file in Finder to start the installation.
It will walk you through the process of installing
N|Solid Runtime in the usual Node.js installation location,
/usr/local/bin
.
If you just want to take a peek at N|Solid,
the easiest thing is to
download a tarball and unpack it.
On my mac, I downloaded the
"Mac OS .tar.gz" for
"N|Solid Runtime", and
then double-clicked on the .tar.gz
file in Finder to unpack it.
This created the directory nsolid-v1.0.1-darwin-x64
. Rename
that directory to nsolid
, start a terminal session, cd
into that directory,
and prepend it's bin
subdirectory to the PATH
environment variable:
$ cd Downloads/nsolid
$ PATH=./bin:$PATH
$ nsolid -v
v4.1.1
$
In the snippet above, I also ran nsolid -v
to print the version of Node.js
that the N|Solid Runtime is built on.
This will make the following executables
available on the PATH, for this shell session:
nsolid
is the binary executable version of Node.js that
N|Solid ships
node
is a symlink to nsolid
npm
is a symlink into lib/node_modules/npm/bin/npm-cli.js
, as it is with
typical Node.js installs
nsolid-cli
is a command-line interface to the
N|Solid Agent, explained later in this
blog post
Let's write a hello.js
program and run it:
$ echo 'console.log("Hello, World!")' > hello.js
$ nsolid hello
Hello, World!
$
Success!
N|Solid Runtime
version 1.0.1 provides the same Node.js runtime as
Node.js 4.1.1,
with some extra goodies. Anything that can run in
Node.js 4.1.1, can run in N|Solid 1.0.1.
NodeSource will release new versions of
N|Solid as new releases of Node.js
become available.
So what makes N|Solid different from regular Node.js?
If you run nsolid --help
, you'll see a listing of additional options and
environment variables at the end:
$ nsolid --help
...
{usual Node.js help here}
...
N|Solid Options:
--policies file provide an NSolid application policies file
N|Solid Environment variables:
NSOLID_HUB Provide the location of the NSolid Hub
NSOLID_SOCKET Provide a specific socket for the NSolid Agent listener
NSOLID_APPNAME Set a name for this application in the NSolid Console
$
N|Solid policies allow you to harden your
application in various ways. For
example, you can have all native memory allocations zero-filled by
N|Solid,
by using the zeroFillAllocations
policy. By default, Node.js does not zero-fill
memory it allocates from the operating system, for performance reasons.
For more information on policies, see the
N|Solid Policies documentation.
Besides policies, the other extra goody that N|Solid
provides is an agent that
you can enable to allow introspection of your Node.js processes. To enable the
N|Solid Agent, you'll use the environment variables
listed in the help text above.
For the purposes of the rest of this blog post, we'll just focus on interacting
with a single Node.js process, and will just use the NSOLID_SOCKET
environment
variable. The NSOLID_HUB
and NSOLID_APPNAME
environment variables are used
when interacting with multiple Node.js processes, via the
N|Solid Hub.
The N|Solid Agent is enabled if the
NSOLID_SOCKET
environment variable is set,
and is not enabled if the environment variable is not set.
Let's start a Node.js REPL
with the N|Solid Agent enabled:
$ NSOLID_SOCKET=5000 nsolid
> 1+1 // just show that things are working
2
>
This command starts up the typical Node.js REPL, with the
N|Solid Agent listening
on port 5000. When the N|Solid Agent is enabled,
you can interact with it using
N|Solid Command Line Interface (CLI), implemented as
the nsolid-cli
executable.
running nsolid-cli
commands
Let's start with a ping
command.
Leave the REPL running, start a new terminal window,
cd
into your nsolid
directory again, and set the PATH
environment variable:
$ cd Downloads/nsolid
$ PATH=./bin:$PATH
$
Now let's send the ping
command to the
N|Solid Agent running in the REPL:
$ nsolid-cli --socket 5000 ping
"PONG"
$
In this case, we passed the --socket
option on the command line,
which indicates the N|Solid Agent port to connect to. And we
told it to run the ping
command. The response was the string "PONG"
.
The ping
command just validates that the N|Solid Agent
is actually running.
Let's try the system_stats
command, with the REPL still running in the other window:
$ nsolid-cli --socket 5000 system_stats
{"freemem":2135748608,"uptime":2414371,"load_1m":1.17431640625,"load_5m":1.345703125,"load_15m":1.3447265625,"cpu_speed":2500}
$
The system_stats
command provides some system-level statistics, such as amount
of free memory (in bytes), system uptime, and load averages.
The output is a single line of JSON. To make the output more readable,
you can pipe the output through the
json
command, available at npm:
$ nsolid-cli --socket 5000 system_stats | json
{
"freemem": 1970876416,
"uptime": 2414810,
"load_1m": 1.34765625,
"load_5m": 1.26611328125,
"load_15m": 1.29052734375,
"cpu_speed": 2500
}
$
Another nsolid-cli
command is process_stats
,
which provides some process-level statistics:
$ nsolid-cli --socket 5000 process_stats | json
{
"uptime": 2225.215,
"rss": 25767936,
"heapTotal": 9296640,
"heapUsed": 6144552,
"active_requests": 0,
"active_handles": 4,
"user": "pmuellr",
"title": "nsolid",
"cpu": 0
}
$
The full list of commands you can use with nsolid-cli
is
available at the doc page
N|Solid Command Line Interface (CLI)
.
generating a CPU profile
Let's try one more thing - generating a CPU profile. Here's a
link to a sample program to run, that will keep your CPU busy:
busy-web.js
This program is an HTTP server that issues an HTTP request to itself, every
10 milliseconds. It makes use of some of the
new ES6 features available in Node.js 4.0,
like
template strings
and
arrow functions.
Since the N|Solid Runtime is using the
latest version of Node.js, you can make use of those features with
N|Solid as well.
Let's run it with the agent enabled:
$ NSOLID_SOCKET=5000 nsolid busy-web
server listing at http://localhost:53011
send: 100 requests
recv: 100 requests
...
In another terminal window, run the profile_start
command,
wait a few seconds and run the profile_stop
command, redirecting
the output to the file busy-web.cpuprofile
:
$ nsolid-cli --socket 5000 profile_start
{"started":1443108818350,"collecting":true}
... wait a few seconds ...
$ nsolid-cli --socket 5000 profile_stop > busy-web.cpuprofile
The file busy-web.cpuprofile
can then be loaded into Chrome Dev Tools
for analysis:
- in Chrome, select the menu item View / Developer / Developer Tools
- in the Developer Tools window, select the Profiles tab
- click the "Load" button
- select the
busy-web.cpuprofile
file
- in the CPU PROFILES list on the left, select "busy-web"
For more information on using Chrome Dev Tools to analyze a CPU
profile, see Google's
Speed Up JavaScript Execution
page.
Note that we didn't have to instrument our program with any special profiling
packages - access to the V8 CPU profiler is baked right into
N|Solid!
About time someone did that, eh?
You can easily write a script to automate the creation of a CPU profile, where
you add a sleep
command to wait some number of seconds between
the profile_start
and profile_stop
commands.
#!/bin/sh
echo "starting CPU profile"
nsolid-cli --socket 5000 profile_start
echo "waiting 5 seconds"
sleep 5
echo "writing profile to busy-web.cpuprofile"
nsolid-cli --socket 5000 profile_stop > busy-web.cpuprofile
Or instead of sleeping, if your app is an HTTP server, you can drive some
traffic to it with
Apache Bench (ab
),
by running something like this instead of the sleep
command:
ab -n 1000 -c 100 http://localhost:3000/
generating heap snapshots
You can use the same technique to capture heap snapshots, using the
snapshot
command. The snapshot
command produces output which
should be redirected to a file with a .heapsnapshot
extension:
$ nsolid-cli --socket 5000 snapshot > busy-web.heapsnapshot
You can then load those files in
Chrome Dev Tools for analysis, the same way the CPU profiles are loaded.
For more information on using Chrome Dev Tools to analyze a heap
snapshot, see Google's
How to Record Heap Snapshots
page.
more info
The full list of commands you can use with nsolid-cli
is
available at the doc page
N|Solid Command Line Interface (CLI)
.
All of the documentation for N|Solid
is available at the doc site
N|Solid Documentation.
If you have any questions about N|Solid, feel free to post them at
Stack Overflow, and add
a tag nsolid
.