Basic Node performance monitoring with Node Application Metrics

This post is more than 2 years old.

While I still have a long way to go before I consider myself a "Node.js Expert", one of the areas I've been most interested in recently is performance monitoring. There are tools out there for this purpose, of course, and I work for a group that has some. StrongLoop has performance tools as part of the commercial offering for Node.js applications, and while obviously I hope to get up to speed on them soon, I ran across an open-source project at IBM that I thought was rather neat - Node Application Metrics.

Node Application Metrics, or appmetrics, is a utility that adds interesting metric data to your Node.js application. Out of the box, you get support for:

  • CPU metrics
  • Memory metrics
  • Garbage collection
  • Event Loop data
  • MySQL, LevelDB, MySQL, MongoDB, PostgreSQL, OracleDB, and Redis database metrics
  • WebSocket monitoring
  • And more of course.

appmetrics supports reporting two ways. You can either hook it up to Health Center, a free Eclipse plugin, or you can write code to handle metric events yourself. As I don't really use Eclipse, I played around with the server-side implementation.

Right away - I have to warn you. appmetrics is not currently supposed under Node v5. I got it running (in fact, the error you get when you try to npm install it will tell you what to do), but obviously your mileage will vary unless you're using v4. Apparently v5 support is coming soon so there's that. I took an existing application that uses Mongo and simply dropped this into the top of my main application file.

var appmetrics = require('appmetrics');
var monitoring = appmetrics.monitor();

monitoring.on('initialized', function (env) {
	console.log(chalk.yellow('[appmetric] init'));
monitoring.on('http', function (data) {
	console.log(chalk.yellow('[appmetric] duration='+data.duration+' ms url='+data.url));
monitoring.on('mongo', function (data) {
	console.log(chalk.yellow('[appmetric] duration='+data.duration+' ms query='+JSON.stringify(data.query)));

The fist two lines simply turn on appmetrics. The first event is fired when metrics are ready. The http event is fired when an http request is made to your application. It is not fired when your application itself makes a HTTP request. I think that woud be a really useful metric and I've filed an ER for it. The mongo event is - obviously - fired on Mongo operations. One thing missing from the event that I think would be super useful is a metric on how many objects are returned. You may ask - why would you need that? As a developer, don't you know what your queries are doing? And the answer is - of course not. We've all dealt with code that we didn't write and unoptimized queries. I can't tell you how many times I saw code that returned thousands of results but only worked with the first one. Having a metric report on the result count would be super useful. (And yes, I filed an ER for that as well.)

In testing, it worked as expected, but the http event recorded every http request, even static resources. Luckily you can easily tweak that. Here is how that could be done:

appmetrics.setConfig('http', {

In this case, I'm simply ignoring calls to URLs that match that regex. I could also conditionally ignore stuff in my event handler too.

Here is an example of it running.

console output

Currently the Mongo data is a bit hard to grok. You can see a query of {} above, which represents me asking for all objects, but it should (imo) also return the fact that I was asking for all objects of type X.

All in all - this project feels like exactly the kind of metric tool I was looking for - something incredibly simple and easy to use - but with some rough edges that need to be tuned up a bit before I'd recommend it wholesale. The biggest issue right now is that I'd like to see the data that feeds the Eclipse plugin available over regular HTTP. That would allow me to build my own front end to it and skip using the console or Eclipse. (Mainly I want to skip Eclipse because, well, it's Eclipse. ;)

But I have to be honest - most performance tools create output that is incredibly hard for me to grasp. Seeing simple, "You requested this and I took N milliseconds to process" is night and day easier for me to process. Don't get me wrong - I know the more complex tools are there for a reason, but stuff like this feels like a good half way point between no metrics and complex CPU memory dumps.

Are any of my readers making use of it?

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA

Archived Comments

Comment 1 by Aabha Mehta posted on 4/12/2016 at 9:02 AM

Worth to read..:)

Comment 2 by Preguntón Cojonero Cabrón posted on 8/10/2016 at 4:13 PM

more code, full source code samples!

Comment 3 by harry posted on 12/30/2016 at 10:10 AM

hello i use appmatrics in my code but it will work only for "http" i am trying for mongo it will not work,please help me

Comment 4 (In reply to #3) by Raymond Camden posted on 12/30/2016 at 2:14 PM

I didn't have any issues - it just worked. Best I can suggest is reaching out to the project and asking there.

Comment 5 (In reply to #0) by Raymond Camden posted on 2/2/2017 at 1:36 PM

I'd say look at the Express events and the Request events. But I don't think that will tell you the *Mongo* times. You would need to look at the total for the route (if it works), see how long the Mongo req is associated with that route, to figure out how much of the time is Mongo.

Comment 6 (In reply to #5) by harry posted on 2/3/2017 at 6:30 AM

i had tried the same in "request" event but it is giving route level information
log are given below, but there is no mongo request related information, i need to identify how much time any route takes in mongo and redis ,
if it is posiible please share some code sample .

2017-02-03T00:26:08 - info: [init] My route request information time=1486099567948, type=HTTP, name=/search/v2/object, duration=641.948115, children=[children=[children=[], name=find(sessions), type=DB, $ref=$["request"]["children"][0], id=12, $ref=$["request"], startTime=[237070, 633860462], startTimeMillis=1486099568025, timeDelta=56.431198, cpuTimeDelta=-1, active=false, tracedStart=true, traceStopped=true], name=findOne(sessions), type=DB, $ref=$["request"], id=11, $ref=$["request"], startTime=[237070, 633447162], startTimeMillis=1486099568024, timeDelta=56.405295, cpuTimeDelta=-1, active=false, query={"_id":"ZVepyBZC1fCQuAIoHgRiPiPXgRruyzz_","$or":[{"expires":{"$exists":false}},{"expires":{"$gt":"2017-02-03T05:26:08.023Z"}}]}, tracedStart=true, traceStopped=true, children=[], name=update(sessions), type=DB, $ref=$["request"], id=13, $ref=$["request"], startTime=[237071, 155465825], startTimeMillis=1486099568546, timeDelta=30.501842, cpuTimeDelta=-1, active=false, query={"_id":"ZVepyBZC1fCQuAIoHgRiPiPXgRruyzz_"}, tracedStart=true, traceStopped=true], name=/search/v2/object, type=HTTP, parent=undefined, id=10, $ref=$["request"], startTime=[237070, 556769189], startTimeMillis=1486099567948, timeDelta=641.948115, cpuTimeDelta=-1, active=false, tracedStart=true, url=/search/v2/object, traceStopped=true

Comment 7 (In reply to #6) by Raymond Camden posted on 2/3/2017 at 3:25 PM

Well I'm confused - Mongo did work for me. You can see it in the screenshot above, right?

Comment 8 by Surya Sathya posted on 4/18/2017 at 12:19 PM

can we use this to track streaming data using twitter api with nodejs.

i just want to monitor my node app

thank you

Comment 9 (In reply to #8) by Raymond Camden posted on 4/18/2017 at 1:13 PM

I know you can track outgoing HTTP requests.

Comment 10 (In reply to #9) by Surya Sathya posted on 4/19/2017 at 5:10 AM

hi Raymond Camden thanks for the quick jump. could you pls share some example snippets about how to track http outgoing.

many thanks

Comment 11 (In reply to #10) by Raymond Camden posted on 4/19/2017 at 12:55 PM

Well, first, tell me what you tried? The docs do mention "HTTP Outbound" as a thing to track.