From 35cda77238d8f33f62d1b9e80d55e51c9aa86a18 Mon Sep 17 00:00:00 2001 From: Valentin Marchaud Date: Mon, 11 May 2020 19:40:44 +0200 Subject: [PATCH] fix(http-plugin): strip otel custom http header #983 (#984) --- packages/opentelemetry-plugin-http/src/http.ts | 6 +++++- packages/opentelemetry-plugin-http/src/utils.ts | 13 ++++++++++++- .../test/functionals/http-enable.test.ts | 8 ++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/packages/opentelemetry-plugin-http/src/http.ts b/packages/opentelemetry-plugin-http/src/http.ts index c6c9aaa933..b145b4a49e 100644 --- a/packages/opentelemetry-plugin-http/src/http.ts +++ b/packages/opentelemetry-plugin-http/src/http.ts @@ -392,8 +392,12 @@ export class HttpPlugin extends BasePlugin { extraOptions ); + if (utils.isOpenTelemetryRequest(optionsParsed)) { + delete optionsParsed.headers[utils.OT_REQUEST_HEADER]; + return original.apply(this, [optionsParsed, ...args]); + } + if ( - utils.isOpenTelemetryRequest(optionsParsed) || utils.isIgnored( origin + pathname, plugin._config.ignoreOutgoingUrls, diff --git a/packages/opentelemetry-plugin-http/src/utils.ts b/packages/opentelemetry-plugin-http/src/utils.ts index e97e421c46..ef5cb100f2 100644 --- a/packages/opentelemetry-plugin-http/src/utils.ts +++ b/packages/opentelemetry-plugin-http/src/utils.ts @@ -33,6 +33,10 @@ import { AttributeNames } from './enums/AttributeNames'; import * as url from 'url'; import { Socket } from 'net'; +/** + * Specific header used by exporters to "mark" outgoing request to avoid creating + * spans for request that export them which would create a infinite loop. + */ export const OT_REQUEST_HEADER = 'x-opentelemetry-outgoing-request'; export const HTTP_STATUS_SPECIAL_CASES: SpecialHttpStatusCodeMapping = { @@ -298,9 +302,16 @@ export const isValidOptionsType = (options: unknown): boolean => { * Use case: Typically, exporter `SpanExporter` can use http module to send spans. * This will also generate spans (from the http-plugin) that will be sended through the exporter * and here we have loop. + * + * TODO: Refactor this logic when a solution is found in + * https://github.com/open-telemetry/opentelemetry-specification/issues/530 + * + * * @param {RequestOptions} options */ -export const isOpenTelemetryRequest = (options: RequestOptions) => { +export const isOpenTelemetryRequest = ( + options: RequestOptions +): options is { headers: {} } & RequestOptions => { return !!(options && options.headers && options.headers[OT_REQUEST_HEADER]); }; diff --git a/packages/opentelemetry-plugin-http/test/functionals/http-enable.test.ts b/packages/opentelemetry-plugin-http/test/functionals/http-enable.test.ts index 7197a7410d..1fec14144f 100644 --- a/packages/opentelemetry-plugin-http/test/functionals/http-enable.test.ts +++ b/packages/opentelemetry-plugin-http/test/functionals/http-enable.test.ts @@ -180,6 +180,10 @@ describe('HttpPlugin', () => { }; const result = await httpRequest.get(options); + assert( + result.reqHeaders[OT_REQUEST_HEADER] === undefined, + 'custom header should be stripped' + ); const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(result.data, 'Ok'); assert.strictEqual(spans.length, 0); @@ -293,6 +297,10 @@ describe('HttpPlugin', () => { }; const result = await httpRequest.get(options); + assert( + result.reqHeaders[OT_REQUEST_HEADER] === undefined, + 'custom header should be stripped' + ); const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(result.data, 'Ok'); assert.strictEqual(spans.length, 0);