in src/plugins/HttpPlugin.ts [50:147]
module.request = function () {
const url: URL | string | RequestOptions = arguments[0];
const { host, pathname } =
url instanceof URL
? url
: typeof url === 'string'
? new URL(url) // TODO: this may throw invalid URL
: {
host: (url.host || url.hostname || 'unknown') + ':' + (url.port || 80),
pathname: url.path || '/',
};
const operation = pathname.replace(/\?.*$/g, '');
const method = arguments[url instanceof URL || typeof url === 'string' ? 1 : 0]?.method || 'GET';
const span = ignoreHttpMethodCheck(method)
? DummySpan.create()
: ContextManager.current.newExitSpan(operation, Component.HTTP);
if (span.depth)
// if we inherited from a higher level plugin then do nothing, higher level should do all the work and we don't duplicate here
return _request.apply(this, arguments);
span.start();
try {
span.component = Component.HTTP;
span.layer = SpanLayer.HTTP;
span.peer = host;
span.tag(Tag.httpURL(protocol + '://' + host + pathname));
span.tag(Tag.httpMethod(method));
const copyStatusAndWrapEmit = (res: any) => {
span.tag(Tag.httpStatusCode(res.statusCode));
if (res.statusCode && res.statusCode >= 400) span.errored = true;
if (res.statusMessage) span.tag(Tag.httpStatusMsg(res.statusMessage));
wrapEmit(span, res, false);
};
const responseCB = function (this: any, res: any) {
// may wrap callback instead of event because it procs first
span.resync();
copyStatusAndWrapEmit(res);
try {
if (callback) return callback.apply(this, arguments);
} catch (err) {
span.error(err);
throw err;
} finally {
span.async();
}
};
const idxCallback = typeof arguments[2] === 'function' ? 2 : typeof arguments[1] === 'function' ? 1 : 0;
const callback = arguments[idxCallback];
if (idxCallback) arguments[idxCallback] = responseCB;
let arg0 = arguments[0];
const expect = arg0.headers && (arg0.headers.Expect || arg0.headers.expect);
if (expect === '100-continue') {
span.inject().items.forEach((item) => {
arg0.headers[item.key] = item.value;
});
}
const req: ClientRequest = _request.apply(this, arguments);
span
.inject()
.items.filter((item) => expect != '100-continue')
.forEach((item) => req.setHeader(item.key, item.value));
wrapEmit(span, req, true, 'close');
req.on('timeout', () => span.log('Timeout', true));
req.on('abort', () => span.log('Abort', (span.errored = true)));
if (!idxCallback) req.on('response', copyStatusAndWrapEmit);
span.async();
return req;
} catch (err) {
span.error(err);
span.stop();
throw err;
}
};