Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1226,7 +1226,9 @@ module.exports = function (name, version, isLatest) {
'x-my-exit-options-request-multi-header':
'x-my-exit-options-request-multi-header-value-1, x-my-exit-options-request-multi-header-value-2'
}),
span => expect(span.data.http.url).to.match(/\/request-only-opts/)
span => expect(span.data.http.url).to.match(/\/request-only-opts/),
span => expect(span.data.http.requestHeader).to.not.exist,
span => expect(span.data.http.responseHeader).to.not.exist
]);
})
)
Expand All @@ -1250,7 +1252,9 @@ module.exports = function (name, version, isLatest) {
'x-my-exit-set-on-request-multi-header':
'x-my-exit-set-on-request-multi-header-value-1, x-my-exit-set-on-request-multi-header-value-2'
}),
span => expect(span.data.http.url).to.match(/\/request-only-opts/)
span => expect(span.data.http.url).to.match(/\/request-only-opts/),
span => expect(span.data.http.requestHeader).to.not.exist,
span => expect(span.data.http.responseHeader).to.not.exist
]);
})
)
Expand All @@ -1273,7 +1277,9 @@ module.exports = function (name, version, isLatest) {
expect(span.data.http.header['x-my-exit-response-header']).to.equal(
'x-my-exit-response-header-value'
),
span => expect(span.data.http.url).to.match(/\/request-only-opts/)
span => expect(span.data.http.url).to.match(/\/request-only-opts/),
span => expect(span.data.http.requestHeader).to.not.exist,
span => expect(span.data.http.responseHeader).to.not.exist
]);
})
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1137,6 +1137,8 @@ module.exports = function (name, version, isLatest) {
} else {
expect(span.data.http.header).to.not.exist;
}
expect(span.data.http.requestHeader).to.not.exist;
expect(span.data.http.responseHeader).to.not.exist;
}

function verifyHttpExitEc({ spans, expectedEc, expectedStatus }) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ module.exports = function (name, version, isLatest) {
'x-my-entry-request-multi-header': 'value1,value2'
});
}
expect(span.data.http.requestHeader).to.not.exist;
expect(span.data.http.responseHeader).to.not.exist;
})
)
);
Expand All @@ -314,6 +316,8 @@ module.exports = function (name, version, isLatest) {
'x-my-entry-response-header': expectedResponeHeaderValue,
'x-my-entry-response-multi-header': 'value1, value2'
});
expect(span.data.http.requestHeader).to.not.exist;
expect(span.data.http.responseHeader).to.not.exist;
})
)
);
Expand All @@ -336,6 +340,8 @@ module.exports = function (name, version, isLatest) {
'x-write-head-response-header': expectedResponeHeaderValue,
'x-write-head-response-multi-header': 'value1, value2'
});
expect(span.data.http.requestHeader).to.not.exist;
expect(span.data.http.responseHeader).to.not.exist;
})
)
);
Expand Down Expand Up @@ -374,6 +380,8 @@ module.exports = function (name, version, isLatest) {
'x-my-entry-response-multi-header': 'value1, value2'
});
}
expect(span.data.http.requestHeader).to.not.exist;
expect(span.data.http.responseHeader).to.not.exist;
})
)
);
Expand Down Expand Up @@ -420,6 +428,8 @@ module.exports = function (name, version, isLatest) {
'x-write-head-response-multi-header': 'value1, value2'
});
}
expect(span.data.http.requestHeader).to.not.exist;
expect(span.data.http.responseHeader).to.not.exist;
})
)
);
Expand All @@ -437,6 +447,8 @@ module.exports = function (name, version, isLatest) {
agentControls.getSpans().then(spans => {
const span = verifyThereIsExactlyOneHttpEntry(spans, controls, '/', 'GET', 200, false, false);
expect(span.data.http.header).to.not.exist;
expect(span.data.http.requestHeader).to.not.exist;
expect(span.data.http.responseHeader).to.not.exist;
})
)
));
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/tracing/backend_mappers/mapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ const fieldMappings = {
http: {
operation: 'method',
endpoints: 'url',
connection: 'host'
connection: 'host',
// The null mapping indicates the field is internal-only and will be dropped
requestHeader: null,
responseHeader: null
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,10 @@ function instrumentClientHttp2Session(clientHttp2Session) {

const origin = readSymbolProperty(stream, originS);
const reqHeaders = readSymbolProperty(stream, sentHeadersS);
let capturedHeaders = getExtraHeadersCaseInsensitive(reqHeaders, extraHttpHeadersToCapture);
const requestHeader = getExtraHeadersCaseInsensitive(reqHeaders, extraHttpHeadersToCapture);

let responseHeader;
let combinedHeader = requestHeader;

let method;
let path;
Expand All @@ -126,8 +129,11 @@ function instrumentClientHttp2Session(clientHttp2Session) {

stream.on('response', resHeaders => {
status = resHeaders[HTTP2_HEADER_STATUS];
capturedHeaders = mergeExtraHeadersFromNormalizedObjectLiteral(
capturedHeaders,

responseHeader = getExtraHeadersCaseInsensitive(resHeaders, extraHttpHeadersToCapture);

combinedHeader = mergeExtraHeadersFromNormalizedObjectLiteral(
combinedHeader,
resHeaders,
extraHttpHeadersToCapture
);
Expand All @@ -137,8 +143,16 @@ function instrumentClientHttp2Session(clientHttp2Session) {
span.d = Date.now() - span.ts;
span.ec = tracingUtil.shouldMarkAsError(status) ? 1 : 0;
span.data.http.status = status;
if (capturedHeaders) {
span.data.http.header = capturedHeaders;
if (requestHeader) {
span.data.http.requestHeader = requestHeader;
}

if (responseHeader) {
span.data.http.responseHeader = responseHeader;
}

if (combinedHeader) {
span.data.http.header = combinedHeader;
}
span.transmit();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,16 @@ function shimEmit(realEmit) {
if (pathParts.length >= 2) {
pathParts[1] = filterParams(pathParts[1]);
}

const requestHeader = getExtraHeadersFromNormalizedObjectLiteral(headers, extraHttpHeadersToCapture);
const spanData = {
http: {
operation: method,
endpoints: sanitizeUrl(pathParts.shift()),
params: pathParts.length > 0 ? pathParts.join('?') : undefined,
connection: authority,
header: getExtraHeadersFromNormalizedObjectLiteral(headers, extraHttpHeadersToCapture)
header: requestHeader,
requestHeader
}
};

Expand Down Expand Up @@ -167,8 +170,12 @@ function shimEmit(realEmit) {
// take over the span) but did not actually transmit this span.
span.data.http = span.data.http || {};
span.data.http.status = status;

const responseHeader = getExtraHeadersFromNormalizedObjectLiteral(resHeaders, extraHttpHeadersToCapture);
span.data.http.responseHeader = responseHeader;

span.data.http.header = mergeExtraHeadersCaseInsensitive(
span.data.http.header,
span.data.http.requestHeader,
resHeaders,
extraHttpHeadersToCapture
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ function instrument(coreModule, forceHttps) {

span.stack = tracingUtil.getStackTrace(request);

let requestHeader;

const boundCallback = cls.ns.bind(function boundCallback(res) {
span.data.http = {
operation: clientRequest.method,
Expand All @@ -237,9 +239,21 @@ function instrument(coreModule, forceHttps) {
params
};

const headers = captureRequestHeaders(options, clientRequest, res);
if (headers) {
span.data.http.header = headers;
const responseHeader = captureResponseHeaders(res);
const combinedHeader = mergeExtraHeadersFromIncomingMessage(
requestHeader ? Object.assign({}, requestHeader) : undefined,
res,
extraHttpHeadersToCapture
);

if (requestHeader) {
span.data.http.requestHeader = requestHeader;
}
if (responseHeader) {
span.data.http.responseHeader = responseHeader;
}
if (combinedHeader) {
span.data.http.header = combinedHeader;
}

span.d = Date.now() - span.ts;
Expand All @@ -262,6 +276,8 @@ function instrument(coreModule, forceHttps) {
try {
instanaHeadersHaveBeenAdded = tryToAddHeadersToOpts(options, span, w3cTraceContext);
clientRequest = originalRequest.apply(coreModule, originalArgs);
// Capture outgoing request headers now that clientRequest exists and before any async response arrives.
requestHeader = captureRequestHeaders(options, clientRequest);
removeInstanaHeadersFromOpts(options);
} catch (e) {
removeInstanaHeadersFromOpts(options);
Expand Down Expand Up @@ -466,9 +482,12 @@ function setW3cHeadersOnRequest(clientRequest, w3cTraceContext) {
}
}

function captureRequestHeaders(options, clientRequest, response) {
function captureRequestHeaders(options, clientRequest) {
let headers = getExtraHeadersFromOptions(options, extraHttpHeadersToCapture);
headers = mergeExtraHeadersFromServerResponseOrClientRequest(headers, clientRequest, extraHttpHeadersToCapture);
headers = mergeExtraHeadersFromIncomingMessage(headers, response, extraHttpHeadersToCapture);
return headers;
}

function captureResponseHeaders(response) {
return mergeExtraHeadersFromIncomingMessage(undefined, response, extraHttpHeadersToCapture);
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,16 @@ function shimEmit(realEmit) {
if (urlParts.length >= 2) {
urlParts[1] = filterParams(urlParts[1]);
}

const requestHeader = getExtraHeadersFromMessage(req, extraHttpHeadersToCapture);
const spanData = {
http: {
operation: req.method,
endpoints: sanitizeUrl(urlParts.shift()),
params: urlParts.length > 0 ? urlParts.join('?') : undefined,
connection: req.headers.host,
header: getExtraHeadersFromMessage(req, extraHttpHeadersToCapture)
header: requestHeader ? Object.assign({}, requestHeader) : undefined,
requestHeader
}
};

Expand Down Expand Up @@ -183,6 +186,11 @@ function shimEmit(realEmit) {
res,
extraHttpHeadersToCapture
);
span.data.http.responseHeader = mergeExtraHeadersFromServerResponseOrClientRequest(
undefined,
res,
extraHttpHeadersToCapture
);
}

if (!span.postponeTransmit) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ function instrument() {
const resource = originalArgs[0];
let params;
let capturedHeaders;
let capturedRequestHeaders;

if (resource != null) {
let rawUrl;
Expand All @@ -127,6 +128,7 @@ function instrument() {
rawUrl = resource.url;
method = resource.method;
capturedHeaders = getExtraHeadersFromFetchHeaders(resource.headers, extraHttpHeadersToCapture);
capturedRequestHeaders = capturedHeaders ? Object.assign({}, capturedHeaders) : undefined;
} else if (typeof resource.toString === 'function') {
// This also handles the case when the resource is a URL object, as well as any object that has a custom
// stringifier.
Expand All @@ -153,6 +155,7 @@ function instrument() {
} else {
capturedHeaders = getExtraHeadersCaseInsensitive(options.headers, extraHttpHeadersToCapture);
}
capturedRequestHeaders = capturedHeaders ? Object.assign({}, capturedHeaders) : undefined;
}
}

Expand All @@ -171,6 +174,12 @@ function instrument() {
.then(response => {
span.data.http.status = response.status;
span.ec = tracingUtil.shouldMarkAsError(response.status) ? 1 : 0;

const capturedResponseHeaders = mergeExtraHeadersFromFetchHeaders(
undefined,
response.headers,
extraHttpHeadersToCapture
);
capturedHeaders = mergeExtraHeadersFromFetchHeaders(
capturedHeaders,
response.headers,
Expand All @@ -181,6 +190,12 @@ function instrument() {
if (capturedHeaders != null && Object.keys(capturedHeaders).length > 0) {
span.data.http.header = capturedHeaders;
}
if (capturedRequestHeaders != null && Object.keys(capturedRequestHeaders).length > 0) {
span.data.http.requestHeader = capturedRequestHeaders;
}
if (capturedResponseHeaders != null && Object.keys(capturedResponseHeaders).length > 0) {
span.data.http.responseHeader = capturedResponseHeaders;
}
span.transmit();
})
.catch(err => {
Expand Down
33 changes: 33 additions & 0 deletions packages/core/test/tracing/backend_mappers/mapper_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -327,5 +327,38 @@ describe('tracing/backend_mappers', () => {
const result = transform(span);
expect(result).to.deep.equal(span);
});

it('should strip requestHeader and responseHeader from http span data', () => {
span = {
n: 'node.http.server',
data: {
http: {
operation: 'GET',
endpoints: '/api/users',
connection: 'localhost',
status: 200,
header: { 'content-type': 'application/json' },
requestHeader: { accept: 'application/json' },
responseHeader: { 'cache-control': 'no-cache' }
}
}
};

const result = transform(span);

expect(result.data.http).to.deep.equal({
method: 'GET',
url: '/api/users',
host: 'localhost',
status: 200,
header: { 'content-type': 'application/json' }
});

expect(result.data.http).to.not.have.property('operation');
expect(result.data.http).to.not.have.property('endpoints');
expect(result.data.http).to.not.have.property('connection');
expect(result.data.http).to.not.have.property('requestHeader');
expect(result.data.http).to.not.have.property('responseHeader');
});
});
});