Skip to content

Commit

Permalink
Merge pull request #101 from srinandan/master
Browse files Browse the repository at this point in the history
add support for opentracing
  • Loading branch information
srinandan authored Oct 18, 2018
2 parents bf02c0c + 7fb80f8 commit edbc0ae
Show file tree
Hide file tree
Showing 5 changed files with 1,568 additions and 3 deletions.
4 changes: 4 additions & 0 deletions lib/gateway.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ module.exports.start = function(plugins, cb) {
],
function(err) {
errors(err, req, res)
if (err) {
var traceHelper = require('./trace-helper');
traceHelper.finishRequestSpan();
}
})
}

Expand Down
44 changes: 43 additions & 1 deletion lib/plugins-middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ const buildNonTunnelOptions = require('./build-non-tunnel-options')
const checkNoProxy = require('./no-proxy-parser')
const empty_buffer = new Buffer(0);

//opentracing
var traceHelper = require('./trace-helper');
//


/**
* injects plugins into gateway
* @param plugins
Expand All @@ -28,6 +33,11 @@ module.exports = function(plugins) {
return function(sourceRequest, sourceResponse, next) {
const startTime = Date.now();
const correlation_id = uuid.v1();

//opentracing
sourceRequest = traceHelper.initTracer(sourceResponse.proxy.name, sourceRequest, correlation_id);
//

var len = JSON.stringify(sourceRequest.headers).length;
debug("Request header: " + len);
if (configService.get().edgemicro.maxHttpHeaderSize && len > configService.get().edgemicro.maxHttpHeaderSize) {
Expand All @@ -36,6 +46,9 @@ module.exports = function(plugins) {
sourceResponse.write('{"error":"header length more than allowed size"}');
sourceResponse.end();
logger.error('header length more than allowed size');
//opentracing
traceHelper.setRequestError('','header length more than allowed size','', 400);
//
return next(false);
} else {
logger.info({
Expand All @@ -58,7 +71,10 @@ module.exports = function(plugins) {
if (err) {
return next(err)
}

//opentrace
traceHelper.startTargetSpan(correlation_id, sourceRequest.targetHostname);
//closetrace

//create target request
const targetRequest = getTargetRequest(sourceRequest, sourceResponse, plugins, startTime, correlation_id,
//callback for when response is initiated
Expand All @@ -80,6 +96,9 @@ module.exports = function(plugins) {
if (err) {
next(err);
} else {
//opentracing
traceHelper.finishRequestSpan();
//
next();
}
} catch (errors) {
Expand Down Expand Up @@ -249,13 +268,22 @@ function getTargetRequest(sourceRequest, sourceResponse, plugins, startTime, cor
function(e) {
if (e) {
logger.error(e);
//opentracing
traceHelper.setResponseError(e, e.message, e.stack, e.statusCode);
//
cb(e);
} else {
if (targetRequest._timedOut) {
sourceResponse.statusCode = 504; // Gateway Time-out
//opentracing
traceHelper.setResponseError('','','', 504);
//
cb(new Error("Gateway timed out trying to reach target"));
} else {
sourceResponse.statusCode = 502; // Bad Gateway
//opentracing
traceHelper.setResponseError('','','', 502);
//
cb(err);
}

Expand Down Expand Up @@ -317,6 +345,9 @@ function handleTargetResponse(targetRequest, targetResponse, options, cb) {
return;
}
if (err) {
//opentracing
traceHelper.setResponseError(err, err.message, err.stack, err.statusCode);
//
return cb(err);
}
if (results !== undefined && results.length !== 0 && results[0] !== null) {
Expand All @@ -340,6 +371,14 @@ function handleTargetResponse(targetRequest, targetResponse, options, cb) {
sourceResponse.statusMessage = targetResponse.statusMessage;
}

//opentrace
if (targetResponse.statusCode > 399) {
traceHelper.setResponseError('','','', targetResponse.statusCode);
} else {
traceHelper.endTargetSpan(targetResponse.statusCode);
}
//closetrace

if (_configured(config, 'x-response-time')) {
sourceResponse.setHeader('x-response-time', Date.now() - start);
}
Expand Down Expand Up @@ -378,6 +417,9 @@ function subscribeToSourceRequestEvents(plugins, sourceRequest, sourceResponse,
sourceRequest.on('end', () => {
onend_request_handlers(empty_buffer,
function(err, result) {
//opentracing
traceHelper.endRequestSpan();
//
if (err) {
return logger.error(err);
}
Expand Down
135 changes: 135 additions & 0 deletions lib/trace-helper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
const resolve = require('path').resolve;
const debug = require('debug')('trace-helper');
//relative path to the opentracing implementation
if (process.env.EDGEMICRO_TRACE_MODULE) {
const {
initTracer
} = require(resolve(process.env.EDGEMICRO_TRACE_MODULE));
}

const {
Tags,
FORMAT_HTTP_HEADERS
} = require('opentracing');

var targetTrace;
var proxyTrace;
var requestspan;
var responsespan;

module.exports = {
initTracer: function(name, req, correlation_id) {
if (process.env.EDGEMICRO_OPENTRACE) {
try {
proxyTrace = initTracer(name);
//check if there is a parent id
if (checkUberParentId(req.headers)) {
debug("opentracing parentid found");
requestspan = proxyTrace.extract(FORMAT_HTTP_HEADERS, req.headers);
} else {
debug("opentracing parentid not found");
requestspan = proxyTrace.startSpan("request_start");
}
requestspan.setTag(Tags.HTTP_URL, req.url);
requestspan.setTag(Tags.HTTP_METHOD, req.method);
requestspan.setBaggageItem('correlation_id', correlation_id);
var traceheaders = {};
proxyTrace.inject(requestspan, FORMAT_HTTP_HEADERS, traceheaders);
for (var tracekey in traceheaders) {
if (!traceheaders.hasOwnProperty(tracekey)) {
continue;
} else {
req.headers[tracekey] = traceheaders[tracekey];
}
}
} catch (err) {}
}
return req;
},
endRequestSpan: function() {
if (process.env.EDGEMICRO_OPENTRACE) {
try {
requestspan.log({
'event': 'request_end'
});
} catch (err) {}
}
},
setRequestError: function(obj, msg, stack, statusCode) {
if (process.env.EDGEMICRO_OPENTRACE) {
try {
requestspan.setTag(Tags.ERROR, true);
requestspan.setTag(Tags.HTTP_STATUS_CODE, statusCode);
requestspan.log({
'event': 'error',
'error.object': obj,
'message': msg,
'stack': stack
});
requestspan.finish();
} catch (err) {}
}
},
setResponseError: function(obj, msg, stack, statusCode) {
if (process.env.EDGEMICRO_OPENTRACE) {
try {
responsespan.setTag(Tags.ERROR, true);
responsespan.setTag(Tags.HTTP_STATUS_CODE, statusCode);
responsespan.log({
'event': 'error',
'error.object': obj,
'message': msg,
'stack': stack
});
responsespan.finish();
} catch (err) {}
}
},
endTargetSpan: function(statusCode) {
if (process.env.EDGEMICRO_OPENTRACE) {
try {
responsespan.log({
'event': 'target_end'
});
responsespan.setTag(Tags.HTTP_STATUS_CODE, statusCode);
responsespan.finish();
} catch (err) {}
}
},
startTargetSpan: function(correlation_id, targetHostname) {
if (process.env.EDGEMICRO_OPENTRACE) {
try {
targetTrace = initTracer(targetHostname);
responsespan = targetTrace.startSpan("target_start", {
childOf: requestspan.context()
});
responsespan.setBaggageItem('correlation_id', correlation_id);
} catch (err) {}
}
},
finishRequestSpan: function() {
if (process.env.EDGEMICRO_OPENTRACE) {
try {
requestspan.finish();
} catch (err) {}
}
},
setChildErrorSpan: function(name, traceheaders) {
if (process.env.EDGEMICRO_OPENTRACE) {
try {
var childtracer = initTracer(name);
var parentSpanContext = childtracer.extract(FORMAT_HTTP_HEADERS, traceheaders);
var span = childtracer.startSpan(name + '_error', {
childOf: parentSpanContext
});
span.setTag(Tags.ERROR, true);
span.finish();
} catch (err) {}
}
}
}

function checkUberParentId(traceheaders) {
const uberHeader = 'Uber-Trace-Id';
return traceheaders.hasOwnProperty(uberHeader.toLowerCase()) ? true : false;
}
Loading

0 comments on commit edbc0ae

Please sign in to comment.