NodeJS – Wrapping the Request() Module to Point Fingers at Services

Lately, I’ve been looking into tracing the route of service calls through chained services. Since many companies are moving toward a Service-Oriented-Architecture model, tracing when services are called is a crucial step in debugging. This way, when there’s an issue with a service, we know which one is breaking and causing everyone downstream to fail.

As a quick example of what I’m talking about, I’ve made a simple model:

Service A: returns “Hello”

Service B: returns “world”

Service C: calls A and B, then returns “Hello world”

 

Now, imagine service B is taking a long time to respond. Service C will be stuck, and we couldn’t be sure whether it was A or B who is causing the problem!

My goal is to get in the middle of those calls to services A and B and attach headers that track when those calls are made. First, I tried digging into my services’ Bunyan() logging modules and adding my interceptors there. Didn’t work.

Instead, after asking around work and on StackOverflow, I’ve decided to make my own NodeJS module that wraps around Request() and handles all of this for developers with them doing a minimal amount of work. Here’s what I came up with:


'use strict';
var request = require('request');

function spRequest( options, callback ) {

options.incoming_req.headers['id'];

// check for our specific headers
if (options.incoming_req.headers['id'] == undefined) {
   console.log('No id passed to this service');
}
else{
   console.log('I was given id ' + options.incoming_req.headers['id']);
}

// pass those headers boldly forward where no service call has gone before
var forwardHeaders = {
   id: options.incoming_req.headers['id']
   //add other headers here as needed
};

var forwardOptions = { //these are the options we'll use to call request()
   url: options.url,
   headers: forwardHeaders
};

// get start time for the call
var hrTime = process.hrtime()

// we use hrTime because it's more accurate than Date.now()
var start = hrTime[0] * 1000000 + hrTime[1] / 1000;

// called when request() comes back with our data
function _onResponse( start, cb ) {
   var hrTime = process.hrtime()
   var end = hrTime[0] * 1000000 + hrTime[1] / 1000; //since hrTime is an array{milliseconds, nanoseconds} we have to do a bit of conversion
   var responseTime = end - start;
   console.log('request took ' + responseTime + ' milliseconds');

   return cb;
}

// and...GO!
   return request(forwardOptions, _onResponse(start, callback));
}

module.exports = spRequest

What’s really cool about this is that developers really only have to change one thing in their code. When making a HTTP request, they just have to include the request object in the call, like so:

Old way:

request('http://localhost:3000/hello', function (error, response, body) {...});

New way:

request({incoming_req: req, url: 'http://localhost:3000/hello'}, function (error, response, body) {...});

I learned a lot about functional programming today.

Do you like this? Is this something you’d like to read more about? Do you hate this and want me to write more about cooking or building physical things?

Let me know in the comments!

Happy Thursday, everybody!