From d4de43ef27e65ac91a74144ebbe261da27380f0a Mon Sep 17 00:00:00 2001 From: vladislav-kiva Date: Thu, 16 Jan 2020 12:46:09 +0300 Subject: [PATCH 01/25] feat: add jaeger http trace format (#696) --- .../propagation/JaegerHttpTraceFormat.ts | 116 ++++++++++++++++++ .../context/JaegerHttpTraceFormat.test.ts | 80 ++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts create mode 100644 packages/opentelemetry-core/test/context/JaegerHttpTraceFormat.test.ts diff --git a/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts b/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts new file mode 100644 index 0000000000..ca25723b91 --- /dev/null +++ b/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts @@ -0,0 +1,116 @@ +/*! + * Copyright 2019, OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { SpanContext, HttpTextFormat, TraceFlags } from '@opentelemetry/types'; + +export const UBER_TRACE_ID_HEADER = 'uber-trace-id'; + +/** + * Propagates {@link SpanContext} through Trace Context format propagation. + * {trace-id}:{span-id}:{parent-span-id}:{flags} + * {trace-id} + * 64-bit or 128-bit random number in base16 format + * Can be variable length, shorter values are 0-padded on the left + * Clients in some languages support 128-bit, migration pending + * Value of 0 is invalid + * {span-id} + * 64-bit random number in base16 format + * {parent-span-id} + * 64-bit value in base16 format representing parent span id + * Deprecated, most Jaeger clients ignore on the receiving side, but still include it on the sending side + * 0 value is valid and means “root span” (when not ignored) + * {flags} + * One byte bitmap, as two hex digits + * Bit 1 (right-most, least significant) is “sampled” flag + * 1 means the trace is sampled and all downstream services are advised to respect that + * 0 means the trace is not sampled and all downstream services are advised to respect that + * We’re considering a new feature that allows downstream services to upsample if they find their tracing level is too low + * Bit 2 is “debug” flag + * Debug flag should only be set when the sampled flag is set + * Instructs the backend to try really hard not to drop this trace + * Other bits are unused. + * Inspired by jaeger-client-node project + */ +export class JaegerHttpTraceFormat implements HttpTextFormat { + inject( + spanContext: SpanContext, + format: string, + carrier: { [key: string]: unknown } + ) { + const hexTraceId = removeLeadingZeros(spanContext.traceId); + const hexSpanId = removeLeadingZeros(spanContext.spanId); + const parentSpanId = '0'; + const flags = TraceFlags.SAMPLED; + + carrier[UBER_TRACE_ID_HEADER] = `${hexTraceId}:${hexSpanId}:${parentSpanId}:${flags}`; + } + + extract( + format: string, + carrier: { [key: string]: unknown } + ): SpanContext | null { + const uberTraceIdHeader = carrier[UBER_TRACE_ID_HEADER]; + if (!uberTraceIdHeader) return null; + const uberTraceId = Array.isArray(uberTraceIdHeader) + ? uberTraceIdHeader[0] + : uberTraceIdHeader; + + return deserializeSpanContext(uberTraceId); + } + +} + +/** + * @param {string} input - the input for which leading zeros should be removed. + * @return {string} - returns the input string without leading zeros. + **/ +function removeLeadingZeros(input: string): string { + let counter = 0; + let length = input.length - 1; + for (let i = 0; i < length; i++) { + if (input.charAt(i) === '0') { + counter++; + } else { + break; + } + } + + return input.substring(counter); +} + +/** + * @param {string} serializedString - a serialized span context. + * @return {SpanContext} - returns a span context represented by the serializedString. + **/ +function deserializeSpanContext(serializedString: string): SpanContext | null { + let headers = serializedString.split(':'); + if (headers.length !== 4) { + return null; + } + const [traceId, spanId, , flags] = headers; + + const traceFlags = Number( + '0x' + + (isNaN(Number(flags)) + ? 1 + : Number(flags)) + ) & 1; + + const isRemote = true; + + return { traceId, spanId, isRemote, traceFlags }; +} + diff --git a/packages/opentelemetry-core/test/context/JaegerHttpTraceFormat.test.ts b/packages/opentelemetry-core/test/context/JaegerHttpTraceFormat.test.ts new file mode 100644 index 0000000000..c2a4ab6b85 --- /dev/null +++ b/packages/opentelemetry-core/test/context/JaegerHttpTraceFormat.test.ts @@ -0,0 +1,80 @@ +/*! + * Copyright 2019, OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as assert from 'assert'; +import { + JaegerHttpTraceFormat, + UBER_TRACE_ID_HEADER +} from '../../src/context/propagation/JaegerHttpTraceFormat'; +import { SpanContext, TraceFlags } from '@opentelemetry/types'; + +describe('JaegerHttpTraceFormat', () => { + const jaegerHttpTraceFormat = new JaegerHttpTraceFormat(); + let carrier: { [key: string]: unknown }; + + beforeEach(() => { + carrier = {}; + }); + + describe('.inject()', () => { + it('should set uber trace id header', () => { + const spanContext: SpanContext = { + traceId: 'd4cda95b652f4a1592b449d5929fda1b', + spanId: '6e0c63257de34c92', + traceFlags: TraceFlags.SAMPLED, + }; + + jaegerHttpTraceFormat.inject(spanContext, '', carrier); + assert.deepStrictEqual( + carrier[UBER_TRACE_ID_HEADER], + 'd4cda95b652f4a1592b449d5929fda1b:6e0c63257de34c92:0:1' + ); + }); + }); + + describe('.extract()', () => { + it('should extract context of a sampled span from carrier', () => { + carrier[UBER_TRACE_ID_HEADER] = + 'd4cda95b652f4a1592b449d5929fda1b:6e0c63257de34c92:0:1'; + const extractedSpanContext = jaegerHttpTraceFormat.extract( + '', + carrier + ); + + assert.deepStrictEqual(extractedSpanContext, { + spanId: '6e0c63257de34c92', + traceId: 'd4cda95b652f4a1592b449d5929fda1b', + isRemote: true, + traceFlags: TraceFlags.SAMPLED, + }); + }); + + it('returns null if UBER_TRACE_ID_HEADER header is missing', () => { + assert.deepStrictEqual( + jaegerHttpTraceFormat.extract('', carrier), + null + ); + }); + + it('returns null if UBER_TRACE_ID_HEADER header is invalid', () => { + carrier[UBER_TRACE_ID_HEADER] = 'invalid!'; + assert.deepStrictEqual( + jaegerHttpTraceFormat.extract('HttpTraceContext', carrier), + null + ); + }); + }); +}); From ae93d80fb6880ee9cbdae0ce865b446f387b163a Mon Sep 17 00:00:00 2001 From: vladislav-kiva Date: Thu, 16 Jan 2020 13:14:35 +0300 Subject: [PATCH 02/25] feat: add jaeger http trace format (#696) --- .../context/propagation/JaegerHttpTraceFormat.ts | 14 +++++--------- .../test/context/JaegerHttpTraceFormat.test.ts | 12 +++--------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts b/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts index ca25723b91..51f4fd86c1 100644 --- a/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts +++ b/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts @@ -55,7 +55,9 @@ export class JaegerHttpTraceFormat implements HttpTextFormat { const parentSpanId = '0'; const flags = TraceFlags.SAMPLED; - carrier[UBER_TRACE_ID_HEADER] = `${hexTraceId}:${hexSpanId}:${parentSpanId}:${flags}`; + carrier[ + UBER_TRACE_ID_HEADER + ] = `${hexTraceId}:${hexSpanId}:${parentSpanId}:${flags}`; } extract( @@ -70,7 +72,6 @@ export class JaegerHttpTraceFormat implements HttpTextFormat { return deserializeSpanContext(uberTraceId); } - } /** @@ -102,15 +103,10 @@ function deserializeSpanContext(serializedString: string): SpanContext | null { } const [traceId, spanId, , flags] = headers; - const traceFlags = Number( - '0x' + - (isNaN(Number(flags)) - ? 1 - : Number(flags)) - ) & 1; + const traceFlags = + Number('0x' + (isNaN(Number(flags)) ? 1 : Number(flags))) & 1; const isRemote = true; return { traceId, spanId, isRemote, traceFlags }; } - diff --git a/packages/opentelemetry-core/test/context/JaegerHttpTraceFormat.test.ts b/packages/opentelemetry-core/test/context/JaegerHttpTraceFormat.test.ts index c2a4ab6b85..d315cbbca0 100644 --- a/packages/opentelemetry-core/test/context/JaegerHttpTraceFormat.test.ts +++ b/packages/opentelemetry-core/test/context/JaegerHttpTraceFormat.test.ts @@ -17,7 +17,7 @@ import * as assert from 'assert'; import { JaegerHttpTraceFormat, - UBER_TRACE_ID_HEADER + UBER_TRACE_ID_HEADER, } from '../../src/context/propagation/JaegerHttpTraceFormat'; import { SpanContext, TraceFlags } from '@opentelemetry/types'; @@ -49,10 +49,7 @@ describe('JaegerHttpTraceFormat', () => { it('should extract context of a sampled span from carrier', () => { carrier[UBER_TRACE_ID_HEADER] = 'd4cda95b652f4a1592b449d5929fda1b:6e0c63257de34c92:0:1'; - const extractedSpanContext = jaegerHttpTraceFormat.extract( - '', - carrier - ); + const extractedSpanContext = jaegerHttpTraceFormat.extract('', carrier); assert.deepStrictEqual(extractedSpanContext, { spanId: '6e0c63257de34c92', @@ -63,10 +60,7 @@ describe('JaegerHttpTraceFormat', () => { }); it('returns null if UBER_TRACE_ID_HEADER header is missing', () => { - assert.deepStrictEqual( - jaegerHttpTraceFormat.extract('', carrier), - null - ); + assert.deepStrictEqual(jaegerHttpTraceFormat.extract('', carrier), null); }); it('returns null if UBER_TRACE_ID_HEADER header is invalid', () => { From 4b2a9d3979bd31d2e89821dd9cf0116ee3de82c3 Mon Sep 17 00:00:00 2001 From: vladislav-kiva Date: Thu, 16 Jan 2020 13:26:34 +0300 Subject: [PATCH 03/25] feat: add jaeger http trace format (#696) --- .../src/context/propagation/JaegerHttpTraceFormat.ts | 2 +- .../test/context/JaegerHttpTraceFormat.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts b/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts index 51f4fd86c1..a2f758b1ec 100644 --- a/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts +++ b/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts @@ -1,5 +1,5 @@ /*! - * Copyright 2019, OpenTelemetry Authors + * Copyright 2020, OpenTelemetry Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/packages/opentelemetry-core/test/context/JaegerHttpTraceFormat.test.ts b/packages/opentelemetry-core/test/context/JaegerHttpTraceFormat.test.ts index d315cbbca0..d7395ed0a0 100644 --- a/packages/opentelemetry-core/test/context/JaegerHttpTraceFormat.test.ts +++ b/packages/opentelemetry-core/test/context/JaegerHttpTraceFormat.test.ts @@ -1,5 +1,5 @@ /*! - * Copyright 2019, OpenTelemetry Authors + * Copyright 2020, OpenTelemetry Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 1a206cb006024a8a25335652bcd2fe5f1445cf81 Mon Sep 17 00:00:00 2001 From: vladislav-kiva Date: Thu, 16 Jan 2020 16:36:35 +0300 Subject: [PATCH 04/25] feat: add jaeger http trace format (#696) --- .../propagation/JaegerHttpTraceFormat.ts | 44 ++++--------------- 1 file changed, 8 insertions(+), 36 deletions(-) diff --git a/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts b/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts index a2f758b1ec..e1dbbf999c 100644 --- a/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts +++ b/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts @@ -14,9 +14,9 @@ * limitations under the License. */ -import { SpanContext, HttpTextFormat, TraceFlags } from '@opentelemetry/types'; +import { SpanContext, HttpTextFormat, TraceFlags } from "@opentelemetry/types"; -export const UBER_TRACE_ID_HEADER = 'uber-trace-id'; +export const UBER_TRACE_ID_HEADER = "uber-trace-id"; /** * Propagates {@link SpanContext} through Trace Context format propagation. @@ -24,24 +24,12 @@ export const UBER_TRACE_ID_HEADER = 'uber-trace-id'; * {trace-id} * 64-bit or 128-bit random number in base16 format * Can be variable length, shorter values are 0-padded on the left - * Clients in some languages support 128-bit, migration pending * Value of 0 is invalid * {span-id} * 64-bit random number in base16 format - * {parent-span-id} - * 64-bit value in base16 format representing parent span id - * Deprecated, most Jaeger clients ignore on the receiving side, but still include it on the sending side - * 0 value is valid and means “root span” (when not ignored) + * {parent-span-id} set to 0 because this field is deprecated * {flags} * One byte bitmap, as two hex digits - * Bit 1 (right-most, least significant) is “sampled” flag - * 1 means the trace is sampled and all downstream services are advised to respect that - * 0 means the trace is not sampled and all downstream services are advised to respect that - * We’re considering a new feature that allows downstream services to upsample if they find their tracing level is too low - * Bit 2 is “debug” flag - * Debug flag should only be set when the sampled flag is set - * Instructs the backend to try really hard not to drop this trace - * Other bits are unused. * Inspired by jaeger-client-node project */ export class JaegerHttpTraceFormat implements HttpTextFormat { @@ -52,12 +40,9 @@ export class JaegerHttpTraceFormat implements HttpTextFormat { ) { const hexTraceId = removeLeadingZeros(spanContext.traceId); const hexSpanId = removeLeadingZeros(spanContext.spanId); - const parentSpanId = '0'; const flags = TraceFlags.SAMPLED; - carrier[ - UBER_TRACE_ID_HEADER - ] = `${hexTraceId}:${hexSpanId}:${parentSpanId}:${flags}`; + carrier[UBER_TRACE_ID_HEADER] = `${hexTraceId}:${hexSpanId}:0:${flags}`; } extract( @@ -79,17 +64,7 @@ export class JaegerHttpTraceFormat implements HttpTextFormat { * @return {string} - returns the input string without leading zeros. **/ function removeLeadingZeros(input: string): string { - let counter = 0; - let length = input.length - 1; - for (let i = 0; i < length; i++) { - if (input.charAt(i) === '0') { - counter++; - } else { - break; - } - } - - return input.substring(counter); + return input.replace(/^0+/, ""); } /** @@ -97,16 +72,13 @@ function removeLeadingZeros(input: string): string { * @return {SpanContext} - returns a span context represented by the serializedString. **/ function deserializeSpanContext(serializedString: string): SpanContext | null { - let headers = serializedString.split(':'); + let headers = serializedString.split(":"); if (headers.length !== 4) { return null; } const [traceId, spanId, , flags] = headers; - const traceFlags = - Number('0x' + (isNaN(Number(flags)) ? 1 : Number(flags))) & 1; - - const isRemote = true; + const traceFlags = flags.match(/^[0-9a-f]{2}$/i) ? parseInt(flags) & 1 : 1; - return { traceId, spanId, isRemote, traceFlags }; + return { traceId, spanId, isRemote: true, traceFlags }; } From b7a345f7f1043559cf2131f93add42b2aa4e5848 Mon Sep 17 00:00:00 2001 From: vladislav-kiva Date: Thu, 16 Jan 2020 16:39:12 +0300 Subject: [PATCH 05/25] feat: add jaeger http trace format (#696) --- .../src/context/propagation/JaegerHttpTraceFormat.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts b/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts index e1dbbf999c..5f27073f53 100644 --- a/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts +++ b/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts @@ -14,9 +14,9 @@ * limitations under the License. */ -import { SpanContext, HttpTextFormat, TraceFlags } from "@opentelemetry/types"; +import { SpanContext, HttpTextFormat, TraceFlags } from '@opentelemetry/types'; -export const UBER_TRACE_ID_HEADER = "uber-trace-id"; +export const UBER_TRACE_ID_HEADER = 'uber-trace-id'; /** * Propagates {@link SpanContext} through Trace Context format propagation. @@ -64,7 +64,7 @@ export class JaegerHttpTraceFormat implements HttpTextFormat { * @return {string} - returns the input string without leading zeros. **/ function removeLeadingZeros(input: string): string { - return input.replace(/^0+/, ""); + return input.replace(/^0+/, ''); } /** @@ -72,7 +72,7 @@ function removeLeadingZeros(input: string): string { * @return {SpanContext} - returns a span context represented by the serializedString. **/ function deserializeSpanContext(serializedString: string): SpanContext | null { - let headers = serializedString.split(":"); + let headers = serializedString.split(':'); if (headers.length !== 4) { return null; } From ee56b19682070ffdf87c4d127ccb0d81bc5d4fbb Mon Sep 17 00:00:00 2001 From: vladislav-kiva Date: Thu, 16 Jan 2020 17:06:34 +0300 Subject: [PATCH 06/25] feat: add jaeger http trace format (#696) --- .../context/propagation/JaegerHttpTraceFormat.ts | 14 +++----------- packages/opentelemetry-core/src/index.ts | 1 + 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts b/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts index 5f27073f53..1f6b2208eb 100644 --- a/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts +++ b/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts @@ -38,11 +38,11 @@ export class JaegerHttpTraceFormat implements HttpTextFormat { format: string, carrier: { [key: string]: unknown } ) { - const hexTraceId = removeLeadingZeros(spanContext.traceId); - const hexSpanId = removeLeadingZeros(spanContext.spanId); const flags = TraceFlags.SAMPLED; - carrier[UBER_TRACE_ID_HEADER] = `${hexTraceId}:${hexSpanId}:0:${flags}`; + carrier[ + UBER_TRACE_ID_HEADER + ] = `${spanContext.traceId}:${spanContext.spanId}:0:${flags}`; } extract( @@ -59,14 +59,6 @@ export class JaegerHttpTraceFormat implements HttpTextFormat { } } -/** - * @param {string} input - the input for which leading zeros should be removed. - * @return {string} - returns the input string without leading zeros. - **/ -function removeLeadingZeros(input: string): string { - return input.replace(/^0+/, ''); -} - /** * @param {string} serializedString - a serialized span context. * @return {SpanContext} - returns a span context represented by the serializedString. diff --git a/packages/opentelemetry-core/src/index.ts b/packages/opentelemetry-core/src/index.ts index 582101ab1e..42992559db 100644 --- a/packages/opentelemetry-core/src/index.ts +++ b/packages/opentelemetry-core/src/index.ts @@ -22,6 +22,7 @@ export * from './version'; export * from './context/propagation/B3Format'; export * from './context/propagation/BinaryTraceContext'; export * from './context/propagation/HttpTraceContext'; +export * from './context/propagation/JaegerHttpTraceFormat'; export * from './platform'; export * from './trace/globaltracer-utils'; export * from './trace/instrumentation/BasePlugin'; From 0fa26ef86a1530a979eb8a051bdba9b9fa6c7ab0 Mon Sep 17 00:00:00 2001 From: vladislav-kiva Date: Thu, 16 Jan 2020 17:20:10 +0300 Subject: [PATCH 07/25] fix: we should set sampled\unsampled via flag --- .../src/context/propagation/JaegerHttpTraceFormat.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts b/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts index 1f6b2208eb..c4c898f9a9 100644 --- a/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts +++ b/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts @@ -38,7 +38,7 @@ export class JaegerHttpTraceFormat implements HttpTextFormat { format: string, carrier: { [key: string]: unknown } ) { - const flags = TraceFlags.SAMPLED; + const flags = spanContext.traceFlags || TraceFlags.UNSAMPLED; carrier[ UBER_TRACE_ID_HEADER From b0958ee2acb95c001fc6197a777152b5f5cd4dc7 Mon Sep 17 00:00:00 2001 From: vladislav-kiva Date: Thu, 16 Jan 2020 17:41:29 +0300 Subject: [PATCH 08/25] fix: we should set sampled\unsampled via flag --- .../src/context/propagation/JaegerHttpTraceFormat.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts b/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts index c4c898f9a9..2a187127df 100644 --- a/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts +++ b/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts @@ -38,11 +38,13 @@ export class JaegerHttpTraceFormat implements HttpTextFormat { format: string, carrier: { [key: string]: unknown } ) { - const flags = spanContext.traceFlags || TraceFlags.UNSAMPLED; + const traceFlags = `0${( + spanContext.traceFlags || TraceFlags.UNSAMPLED + ).toString(16)}`; carrier[ UBER_TRACE_ID_HEADER - ] = `${spanContext.traceId}:${spanContext.spanId}:0:${flags}`; + ] = `${spanContext.traceId}:${spanContext.spanId}:0:${traceFlags}`; } extract( From aee5f4107526f69258ef3f6f993d7a3fe9910fd8 Mon Sep 17 00:00:00 2001 From: vladislav-kiva Date: Thu, 16 Jan 2020 17:44:10 +0300 Subject: [PATCH 09/25] fix: flags should be converted to hex, not decimal --- .../test/context/JaegerHttpTraceFormat.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/opentelemetry-core/test/context/JaegerHttpTraceFormat.test.ts b/packages/opentelemetry-core/test/context/JaegerHttpTraceFormat.test.ts index d7395ed0a0..dc7388c3f5 100644 --- a/packages/opentelemetry-core/test/context/JaegerHttpTraceFormat.test.ts +++ b/packages/opentelemetry-core/test/context/JaegerHttpTraceFormat.test.ts @@ -40,7 +40,7 @@ describe('JaegerHttpTraceFormat', () => { jaegerHttpTraceFormat.inject(spanContext, '', carrier); assert.deepStrictEqual( carrier[UBER_TRACE_ID_HEADER], - 'd4cda95b652f4a1592b449d5929fda1b:6e0c63257de34c92:0:1' + 'd4cda95b652f4a1592b449d5929fda1b:6e0c63257de34c92:0:01' ); }); }); @@ -48,7 +48,7 @@ describe('JaegerHttpTraceFormat', () => { describe('.extract()', () => { it('should extract context of a sampled span from carrier', () => { carrier[UBER_TRACE_ID_HEADER] = - 'd4cda95b652f4a1592b449d5929fda1b:6e0c63257de34c92:0:1'; + 'd4cda95b652f4a1592b449d5929fda1b:6e0c63257de34c92:0:01'; const extractedSpanContext = jaegerHttpTraceFormat.extract('', carrier); assert.deepStrictEqual(extractedSpanContext, { From c41944c5baa6b0b9ccd221bd0746e79c5425aa40 Mon Sep 17 00:00:00 2001 From: DotSpy Date: Thu, 16 Jan 2020 21:55:44 +0300 Subject: [PATCH 10/25] feat: create new package for propagation jaeger --- .../.npmignore | 4 + .../opentelemetry-propagation-jaeger/LICENSE | 201 ++++++++++++++++++ .../README.md | 37 ++++ .../karma.conf.js | 24 +++ .../package.json | 81 +++++++ .../propagation/JaegerHttpTraceFormat.ts | 10 +- .../context/JaegerHttpTraceFormat.test.ts | 32 +++ .../tsconfig-release.json | 7 + .../tsconfig.json | 11 + .../tslint.json | 4 + 10 files changed, 409 insertions(+), 2 deletions(-) create mode 100644 packages/opentelemetry-propagation-jaeger/.npmignore create mode 100644 packages/opentelemetry-propagation-jaeger/LICENSE create mode 100644 packages/opentelemetry-propagation-jaeger/README.md create mode 100644 packages/opentelemetry-propagation-jaeger/karma.conf.js create mode 100644 packages/opentelemetry-propagation-jaeger/package.json rename packages/{opentelemetry-core => opentelemetry-propagation-jaeger}/src/context/propagation/JaegerHttpTraceFormat.ts (90%) rename packages/{opentelemetry-core => opentelemetry-propagation-jaeger}/test/context/JaegerHttpTraceFormat.test.ts (69%) create mode 100644 packages/opentelemetry-propagation-jaeger/tsconfig-release.json create mode 100644 packages/opentelemetry-propagation-jaeger/tsconfig.json create mode 100644 packages/opentelemetry-propagation-jaeger/tslint.json diff --git a/packages/opentelemetry-propagation-jaeger/.npmignore b/packages/opentelemetry-propagation-jaeger/.npmignore new file mode 100644 index 0000000000..9505ba9450 --- /dev/null +++ b/packages/opentelemetry-propagation-jaeger/.npmignore @@ -0,0 +1,4 @@ +/bin +/coverage +/doc +/test diff --git a/packages/opentelemetry-propagation-jaeger/LICENSE b/packages/opentelemetry-propagation-jaeger/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/packages/opentelemetry-propagation-jaeger/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/opentelemetry-propagation-jaeger/README.md b/packages/opentelemetry-propagation-jaeger/README.md new file mode 100644 index 0000000000..1600973ff2 --- /dev/null +++ b/packages/opentelemetry-propagation-jaeger/README.md @@ -0,0 +1,37 @@ +# OpenTelemetry Core +[![Gitter chat][gitter-image]][gitter-url] +[![NPM Published Version][npm-img]][npm-url] +[![dependencies][dependencies-image]][dependencies-url] +[![devDependencies][devDependencies-image]][devDependencies-url] +[![Apache License][license-image]][license-image] + +OpenTelemetry propagation Jaeger provide HTTP header propagation for systems that using Jaeger HTTP header format. +Example of usage: +```javascript +const { NodeTracer } = require('@opentelemetry/node'); +const { JaegerHttpTraceFormat } = require('@opentelemetry/propagation-jaeger'); +new NodeTracer({ + httpTextFormat: new JaegerHttpTraceFormat() +}) +``` + + +## Useful links +- For more information on OpenTelemetry, visit: +- For more about OpenTelemetry JavaScript: +- For help or feedback on this project, join us on [gitter][gitter-url] + +## License + +Apache 2.0 - See [LICENSE][license-url] for more information. + +[gitter-image]: https://badges.gitter.im/open-telemetry/opentelemetry-js.svg +[gitter-url]: https://gitter.im/open-telemetry/opentelemetry-node?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge +[license-url]: https://github.com/open-telemetry/opentelemetry-js/blob/master/LICENSE +[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat +[dependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/status.svg?path=packages/opentelemetry-core +[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-core +[devDependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/dev-status.svg?path=packages/opentelemetry-core +[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-core&type=dev +[npm-url]: https://www.npmjs.com/package/@opentelemetry/core +[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fcore.svg diff --git a/packages/opentelemetry-propagation-jaeger/karma.conf.js b/packages/opentelemetry-propagation-jaeger/karma.conf.js new file mode 100644 index 0000000000..edcd9f055f --- /dev/null +++ b/packages/opentelemetry-propagation-jaeger/karma.conf.js @@ -0,0 +1,24 @@ +/*! + * Copyright 2020, OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const karmaWebpackConfig = require('../../karma.webpack'); +const karmaBaseConfig = require('../../karma.base'); + +module.exports = (config) => { + config.set(Object.assign({}, karmaBaseConfig, { + webpack: karmaWebpackConfig + })) +}; diff --git a/packages/opentelemetry-propagation-jaeger/package.json b/packages/opentelemetry-propagation-jaeger/package.json new file mode 100644 index 0000000000..da45ab8983 --- /dev/null +++ b/packages/opentelemetry-propagation-jaeger/package.json @@ -0,0 +1,81 @@ +{ + "name": "@opentelemetry/propagation-jaeger", + "version": "0.3.2", + "description": "OpenTelemetry propagation Jaeger provide HTTP header propagation for systems that using Jaeger HTTP header format", + "main": "build/src/index.js", + "browser": { + "./src/platform/index.ts": "./src/platform/browser/index.ts", + "./build/src/platform/index.js": "./build/src/platform/browser/index.js" + }, + "types": "build/src/index.d.ts", + "repository": "open-telemetry/opentelemetry-js", + "scripts": { + "test": "nyc ts-mocha -p tsconfig.json test/**/*.ts", + "test:browser": "nyc karma start --single-run", + "tdd": "yarn tdd:node", + "tdd:node": "yarn test -- --watch-extensions ts --watch", + "tdd:browser": "karma start", + "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../", + "codecov:browser": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../", + "clean": "rimraf build/*", + "check": "gts check", + "precompile": "tsc --version", + "compile": "npm run version:update && tsc -p .", + "fix": "gts fix", + "prepare": "npm run compile", + "version:update": "node ../../scripts/version-update.js", + "watch": "tsc -w" + }, + "keywords": [ + "opentelemetry", + "nodejs", + "tracing", + "profiling" + ], + "author": "OpenTelemetry Authors", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + }, + "files": [ + "build/src/**/*.js", + "build/src/**/*.d.ts", + "doc", + "LICENSE", + "README.md" + ], + "publishConfig": { + "access": "public" + }, + "devDependencies": { + "@types/mocha": "^5.2.5", + "@types/node": "^12.6.8", + "@types/semver": "^6.2.0", + "@types/sinon": "^7.0.13", + "@types/webpack-env": "1.13.9", + "codecov": "^3.6.1", + "gts": "^1.1.0", + "istanbul-instrumenter-loader": "^3.0.1", + "karma": "^4.4.1", + "karma-chrome-launcher": "^3.1.0", + "karma-coverage-istanbul-reporter": "^2.1.0", + "karma-mocha": "^1.3.0", + "karma-spec-reporter": "^0.0.32", + "karma-webpack": "^4.0.2", + "mocha": "^6.1.0", + "nyc": "^14.1.1", + "rimraf": "^3.0.0", + "sinon": "^7.5.0", + "ts-loader": "^6.0.4", + "ts-mocha": "^6.0.0", + "ts-node": "^8.6.2", + "tslint-consistent-codestyle": "^1.16.0", + "tslint-microsoft-contrib": "^6.2.0", + "typescript": "3.7.2", + "webpack": "^4.35.2" + }, + "dependencies": { + "@opentelemetry/types": "^0.3.2", + "semver": "^6.3.0" + } +} diff --git a/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts b/packages/opentelemetry-propagation-jaeger/src/context/propagation/JaegerHttpTraceFormat.ts similarity index 90% rename from packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts rename to packages/opentelemetry-propagation-jaeger/src/context/propagation/JaegerHttpTraceFormat.ts index 2a187127df..8686d60720 100644 --- a/packages/opentelemetry-core/src/context/propagation/JaegerHttpTraceFormat.ts +++ b/packages/opentelemetry-propagation-jaeger/src/context/propagation/JaegerHttpTraceFormat.ts @@ -33,6 +33,12 @@ export const UBER_TRACE_ID_HEADER = 'uber-trace-id'; * Inspired by jaeger-client-node project */ export class JaegerHttpTraceFormat implements HttpTextFormat { + private readonly _jaegerTraceHeader: string; + + constructor(customTraceHeader?: string) { + this._jaegerTraceHeader = customTraceHeader || UBER_TRACE_ID_HEADER; + } + inject( spanContext: SpanContext, format: string, @@ -43,7 +49,7 @@ export class JaegerHttpTraceFormat implements HttpTextFormat { ).toString(16)}`; carrier[ - UBER_TRACE_ID_HEADER + this._jaegerTraceHeader ] = `${spanContext.traceId}:${spanContext.spanId}:0:${traceFlags}`; } @@ -51,7 +57,7 @@ export class JaegerHttpTraceFormat implements HttpTextFormat { format: string, carrier: { [key: string]: unknown } ): SpanContext | null { - const uberTraceIdHeader = carrier[UBER_TRACE_ID_HEADER]; + const uberTraceIdHeader = carrier[this._jaegerTraceHeader]; if (!uberTraceIdHeader) return null; const uberTraceId = Array.isArray(uberTraceIdHeader) ? uberTraceIdHeader[0] diff --git a/packages/opentelemetry-core/test/context/JaegerHttpTraceFormat.test.ts b/packages/opentelemetry-propagation-jaeger/test/context/JaegerHttpTraceFormat.test.ts similarity index 69% rename from packages/opentelemetry-core/test/context/JaegerHttpTraceFormat.test.ts rename to packages/opentelemetry-propagation-jaeger/test/context/JaegerHttpTraceFormat.test.ts index dc7388c3f5..6b8fa25b90 100644 --- a/packages/opentelemetry-core/test/context/JaegerHttpTraceFormat.test.ts +++ b/packages/opentelemetry-propagation-jaeger/test/context/JaegerHttpTraceFormat.test.ts @@ -23,6 +23,8 @@ import { SpanContext, TraceFlags } from '@opentelemetry/types'; describe('JaegerHttpTraceFormat', () => { const jaegerHttpTraceFormat = new JaegerHttpTraceFormat(); + const customHeader = 'new-header'; + const customJaegerHttpTraceFormat = new JaegerHttpTraceFormat(customHeader); let carrier: { [key: string]: unknown }; beforeEach(() => { @@ -43,6 +45,20 @@ describe('JaegerHttpTraceFormat', () => { 'd4cda95b652f4a1592b449d5929fda1b:6e0c63257de34c92:0:01' ); }); + + it('should use custom header if provided', () => { + const spanContext: SpanContext = { + traceId: 'd4cda95b652f4a1592b449d5929fda1b', + spanId: '6e0c63257de34c92', + traceFlags: TraceFlags.SAMPLED, + }; + + customJaegerHttpTraceFormat.inject(spanContext, '', carrier); + assert.deepStrictEqual( + carrier[customHeader], + 'd4cda95b652f4a1592b449d5929fda1b:6e0c63257de34c92:0:01' + ); + }); }); describe('.extract()', () => { @@ -59,6 +75,22 @@ describe('JaegerHttpTraceFormat', () => { }); }); + it('should use custom header if provided', () => { + carrier[customHeader] = + 'd4cda95b652f4a1592b449d5929fda1b:6e0c63257de34c92:0:01'; + const extractedSpanContext = customJaegerHttpTraceFormat.extract( + '', + carrier + ); + + assert.deepStrictEqual(extractedSpanContext, { + spanId: '6e0c63257de34c92', + traceId: 'd4cda95b652f4a1592b449d5929fda1b', + isRemote: true, + traceFlags: TraceFlags.SAMPLED, + }); + }); + it('returns null if UBER_TRACE_ID_HEADER header is missing', () => { assert.deepStrictEqual(jaegerHttpTraceFormat.extract('', carrier), null); }); diff --git a/packages/opentelemetry-propagation-jaeger/tsconfig-release.json b/packages/opentelemetry-propagation-jaeger/tsconfig-release.json new file mode 100644 index 0000000000..ffc0f77968 --- /dev/null +++ b/packages/opentelemetry-propagation-jaeger/tsconfig-release.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "types": [] + }, + "include": ["src/**/*.ts"] +} diff --git a/packages/opentelemetry-propagation-jaeger/tsconfig.json b/packages/opentelemetry-propagation-jaeger/tsconfig.json new file mode 100644 index 0000000000..a2042cd68b --- /dev/null +++ b/packages/opentelemetry-propagation-jaeger/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../tsconfig.base", + "compilerOptions": { + "rootDir": ".", + "outDir": "build" + }, + "include": [ + "src/**/*.ts", + "test/**/*.ts" + ] +} diff --git a/packages/opentelemetry-propagation-jaeger/tslint.json b/packages/opentelemetry-propagation-jaeger/tslint.json new file mode 100644 index 0000000000..0710b135d0 --- /dev/null +++ b/packages/opentelemetry-propagation-jaeger/tslint.json @@ -0,0 +1,4 @@ +{ + "rulesDirectory": ["node_modules/tslint-microsoft-contrib"], + "extends": ["../../tslint.base.js", "./node_modules/tslint-consistent-codestyle"] +} From 6d8ebda61751cf27aa29e2b9911085b6d2e3827d Mon Sep 17 00:00:00 2001 From: Uladzislau Kiva Date: Thu, 16 Jan 2020 22:09:20 +0300 Subject: [PATCH 11/25] fix: remove unused dependencies, correct readme header, moved out jaeger from core index.ts --- packages/opentelemetry-core/src/index.ts | 1 - packages/opentelemetry-propagation-jaeger/README.md | 2 +- packages/opentelemetry-propagation-jaeger/package.json | 6 ------ 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/opentelemetry-core/src/index.ts b/packages/opentelemetry-core/src/index.ts index 42992559db..582101ab1e 100644 --- a/packages/opentelemetry-core/src/index.ts +++ b/packages/opentelemetry-core/src/index.ts @@ -22,7 +22,6 @@ export * from './version'; export * from './context/propagation/B3Format'; export * from './context/propagation/BinaryTraceContext'; export * from './context/propagation/HttpTraceContext'; -export * from './context/propagation/JaegerHttpTraceFormat'; export * from './platform'; export * from './trace/globaltracer-utils'; export * from './trace/instrumentation/BasePlugin'; diff --git a/packages/opentelemetry-propagation-jaeger/README.md b/packages/opentelemetry-propagation-jaeger/README.md index 1600973ff2..79f6ac65a4 100644 --- a/packages/opentelemetry-propagation-jaeger/README.md +++ b/packages/opentelemetry-propagation-jaeger/README.md @@ -1,4 +1,4 @@ -# OpenTelemetry Core +# OpenTelemetry Propagation Jaeger [![Gitter chat][gitter-image]][gitter-url] [![NPM Published Version][npm-img]][npm-url] [![dependencies][dependencies-image]][dependencies-url] diff --git a/packages/opentelemetry-propagation-jaeger/package.json b/packages/opentelemetry-propagation-jaeger/package.json index da45ab8983..490b3e2906 100644 --- a/packages/opentelemetry-propagation-jaeger/package.json +++ b/packages/opentelemetry-propagation-jaeger/package.json @@ -3,10 +3,6 @@ "version": "0.3.2", "description": "OpenTelemetry propagation Jaeger provide HTTP header propagation for systems that using Jaeger HTTP header format", "main": "build/src/index.js", - "browser": { - "./src/platform/index.ts": "./src/platform/browser/index.ts", - "./build/src/platform/index.js": "./build/src/platform/browser/index.js" - }, "types": "build/src/index.d.ts", "repository": "open-telemetry/opentelemetry-js", "scripts": { @@ -50,7 +46,6 @@ "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^12.6.8", - "@types/semver": "^6.2.0", "@types/sinon": "^7.0.13", "@types/webpack-env": "1.13.9", "codecov": "^3.6.1", @@ -76,6 +71,5 @@ }, "dependencies": { "@opentelemetry/types": "^0.3.2", - "semver": "^6.3.0" } } From ba8547cdac978c43c86887331830439107481e07 Mon Sep 17 00:00:00 2001 From: Uladzislau Kiva Date: Thu, 16 Jan 2020 22:10:42 +0300 Subject: [PATCH 12/25] fix: added jaeger keyword --- packages/opentelemetry-propagation-jaeger/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/opentelemetry-propagation-jaeger/package.json b/packages/opentelemetry-propagation-jaeger/package.json index 490b3e2906..e95eb74cbb 100644 --- a/packages/opentelemetry-propagation-jaeger/package.json +++ b/packages/opentelemetry-propagation-jaeger/package.json @@ -26,7 +26,8 @@ "opentelemetry", "nodejs", "tracing", - "profiling" + "profiling", + "jaeger" ], "author": "OpenTelemetry Authors", "license": "Apache-2.0", From 126f81c6116b43d273900b2fa8c2d5137913bd40 Mon Sep 17 00:00:00 2001 From: Uladzislau Kiva Date: Thu, 16 Jan 2020 22:14:26 +0300 Subject: [PATCH 13/25] fix: remove comma --- packages/opentelemetry-propagation-jaeger/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opentelemetry-propagation-jaeger/package.json b/packages/opentelemetry-propagation-jaeger/package.json index e95eb74cbb..5b00efdd29 100644 --- a/packages/opentelemetry-propagation-jaeger/package.json +++ b/packages/opentelemetry-propagation-jaeger/package.json @@ -71,6 +71,6 @@ "webpack": "^4.35.2" }, "dependencies": { - "@opentelemetry/types": "^0.3.2", + "@opentelemetry/types": "^0.3.2" } } From 49428b4bcb87bd71cca8cce0cf217c3f1b12fdf0 Mon Sep 17 00:00:00 2001 From: Uladzislau Kiva Date: Thu, 16 Jan 2020 22:18:04 +0300 Subject: [PATCH 14/25] docs: replace NodeTracer with NodeTracerRegistry --- packages/opentelemetry-propagation-jaeger/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/opentelemetry-propagation-jaeger/README.md b/packages/opentelemetry-propagation-jaeger/README.md index 79f6ac65a4..1800b0f6f4 100644 --- a/packages/opentelemetry-propagation-jaeger/README.md +++ b/packages/opentelemetry-propagation-jaeger/README.md @@ -8,11 +8,12 @@ OpenTelemetry propagation Jaeger provide HTTP header propagation for systems that using Jaeger HTTP header format. Example of usage: ```javascript -const { NodeTracer } = require('@opentelemetry/node'); +const { NodeTracerRegistry } = require('@opentelemetry/node'); const { JaegerHttpTraceFormat } = require('@opentelemetry/propagation-jaeger'); -new NodeTracer({ + +const registry = new NodeTracerRegistry({ httpTextFormat: new JaegerHttpTraceFormat() -}) +}); ``` From b94f716dc2798a0547a9ce36051a189cea1b92eb Mon Sep 17 00:00:00 2001 From: Uladzislau Kiva Date: Thu, 16 Jan 2020 22:19:22 +0300 Subject: [PATCH 15/25] fix: added missing jaeger keyword to exporter-jaeger --- packages/opentelemetry-exporter-jaeger/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/opentelemetry-exporter-jaeger/package.json b/packages/opentelemetry-exporter-jaeger/package.json index 0a024da993..6779c9a5cb 100644 --- a/packages/opentelemetry-exporter-jaeger/package.json +++ b/packages/opentelemetry-exporter-jaeger/package.json @@ -21,7 +21,8 @@ "opentelemetry", "nodejs", "tracing", - "profiling" + "profiling", + "jaeger" ], "author": "OpenTelemetry Authors", "license": "Apache-2.0", From 6ab6a8738dada04086448b6f1199106cf5f61548 Mon Sep 17 00:00:00 2001 From: Uladzislau Kiva Date: Thu, 16 Jan 2020 23:55:04 +0300 Subject: [PATCH 16/25] fix: remove test for browser --- packages/opentelemetry-propagation-jaeger/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/opentelemetry-propagation-jaeger/package.json b/packages/opentelemetry-propagation-jaeger/package.json index 5b00efdd29..ef90d2bdf1 100644 --- a/packages/opentelemetry-propagation-jaeger/package.json +++ b/packages/opentelemetry-propagation-jaeger/package.json @@ -7,7 +7,6 @@ "repository": "open-telemetry/opentelemetry-js", "scripts": { "test": "nyc ts-mocha -p tsconfig.json test/**/*.ts", - "test:browser": "nyc karma start --single-run", "tdd": "yarn tdd:node", "tdd:node": "yarn test -- --watch-extensions ts --watch", "tdd:browser": "karma start", From 21c2fed755c25fc30fb8bf3d7d1904ce46d0d613 Mon Sep 17 00:00:00 2001 From: Uladzislau Kiva Date: Fri, 17 Jan 2020 00:12:07 +0300 Subject: [PATCH 17/25] fix: remove yarn for browser --- packages/opentelemetry-propagation-jaeger/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/opentelemetry-propagation-jaeger/package.json b/packages/opentelemetry-propagation-jaeger/package.json index ef90d2bdf1..0d31c95ff7 100644 --- a/packages/opentelemetry-propagation-jaeger/package.json +++ b/packages/opentelemetry-propagation-jaeger/package.json @@ -11,7 +11,6 @@ "tdd:node": "yarn test -- --watch-extensions ts --watch", "tdd:browser": "karma start", "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../", - "codecov:browser": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../", "clean": "rimraf build/*", "check": "gts check", "precompile": "tsc --version", From 982e008897fb4828686b2b8e20ea3360741ac5c7 Mon Sep 17 00:00:00 2001 From: Uladzislau Kiva Date: Fri, 17 Jan 2020 01:02:54 +0300 Subject: [PATCH 18/25] fix: use same naming style as other packages --- .../.npmignore | 0 .../LICENSE | 0 .../README.md | 4 ++-- .../karma.conf.js | 0 .../package.json | 4 ++-- .../src/context/propagation/JaegerHttpTraceFormat.ts | 0 .../test/context/JaegerHttpTraceFormat.test.ts | 0 .../tsconfig-release.json | 0 .../tsconfig.json | 0 .../tslint.json | 0 10 files changed, 4 insertions(+), 4 deletions(-) rename packages/{opentelemetry-propagation-jaeger => opentelemetry-propagator-jaeger}/.npmignore (100%) rename packages/{opentelemetry-propagation-jaeger => opentelemetry-propagator-jaeger}/LICENSE (100%) rename packages/{opentelemetry-propagation-jaeger => opentelemetry-propagator-jaeger}/README.md (97%) rename packages/{opentelemetry-propagation-jaeger => opentelemetry-propagator-jaeger}/karma.conf.js (100%) rename packages/{opentelemetry-propagation-jaeger => opentelemetry-propagator-jaeger}/package.json (91%) rename packages/{opentelemetry-propagation-jaeger => opentelemetry-propagator-jaeger}/src/context/propagation/JaegerHttpTraceFormat.ts (100%) rename packages/{opentelemetry-propagation-jaeger => opentelemetry-propagator-jaeger}/test/context/JaegerHttpTraceFormat.test.ts (100%) rename packages/{opentelemetry-propagation-jaeger => opentelemetry-propagator-jaeger}/tsconfig-release.json (100%) rename packages/{opentelemetry-propagation-jaeger => opentelemetry-propagator-jaeger}/tsconfig.json (100%) rename packages/{opentelemetry-propagation-jaeger => opentelemetry-propagator-jaeger}/tslint.json (100%) diff --git a/packages/opentelemetry-propagation-jaeger/.npmignore b/packages/opentelemetry-propagator-jaeger/.npmignore similarity index 100% rename from packages/opentelemetry-propagation-jaeger/.npmignore rename to packages/opentelemetry-propagator-jaeger/.npmignore diff --git a/packages/opentelemetry-propagation-jaeger/LICENSE b/packages/opentelemetry-propagator-jaeger/LICENSE similarity index 100% rename from packages/opentelemetry-propagation-jaeger/LICENSE rename to packages/opentelemetry-propagator-jaeger/LICENSE diff --git a/packages/opentelemetry-propagation-jaeger/README.md b/packages/opentelemetry-propagator-jaeger/README.md similarity index 97% rename from packages/opentelemetry-propagation-jaeger/README.md rename to packages/opentelemetry-propagator-jaeger/README.md index 1800b0f6f4..fd7fa592a6 100644 --- a/packages/opentelemetry-propagation-jaeger/README.md +++ b/packages/opentelemetry-propagator-jaeger/README.md @@ -1,4 +1,4 @@ -# OpenTelemetry Propagation Jaeger +# OpenTelemetry Propagator Jaeger [![Gitter chat][gitter-image]][gitter-url] [![NPM Published Version][npm-img]][npm-url] [![dependencies][dependencies-image]][dependencies-url] @@ -9,7 +9,7 @@ OpenTelemetry propagation Jaeger provide HTTP header propagation for systems tha Example of usage: ```javascript const { NodeTracerRegistry } = require('@opentelemetry/node'); -const { JaegerHttpTraceFormat } = require('@opentelemetry/propagation-jaeger'); +const { JaegerHttpTraceFormat } = require('@opentelemetry/propagator-jaeger'); const registry = new NodeTracerRegistry({ httpTextFormat: new JaegerHttpTraceFormat() diff --git a/packages/opentelemetry-propagation-jaeger/karma.conf.js b/packages/opentelemetry-propagator-jaeger/karma.conf.js similarity index 100% rename from packages/opentelemetry-propagation-jaeger/karma.conf.js rename to packages/opentelemetry-propagator-jaeger/karma.conf.js diff --git a/packages/opentelemetry-propagation-jaeger/package.json b/packages/opentelemetry-propagator-jaeger/package.json similarity index 91% rename from packages/opentelemetry-propagation-jaeger/package.json rename to packages/opentelemetry-propagator-jaeger/package.json index 0d31c95ff7..c1f7237532 100644 --- a/packages/opentelemetry-propagation-jaeger/package.json +++ b/packages/opentelemetry-propagator-jaeger/package.json @@ -1,7 +1,7 @@ { - "name": "@opentelemetry/propagation-jaeger", + "name": "@opentelemetry/propagator-jaeger", "version": "0.3.2", - "description": "OpenTelemetry propagation Jaeger provide HTTP header propagation for systems that using Jaeger HTTP header format", + "description": "OpenTelemetry propagator Jaeger provide HTTP header propagation for systems that using Jaeger HTTP header format", "main": "build/src/index.js", "types": "build/src/index.d.ts", "repository": "open-telemetry/opentelemetry-js", diff --git a/packages/opentelemetry-propagation-jaeger/src/context/propagation/JaegerHttpTraceFormat.ts b/packages/opentelemetry-propagator-jaeger/src/context/propagation/JaegerHttpTraceFormat.ts similarity index 100% rename from packages/opentelemetry-propagation-jaeger/src/context/propagation/JaegerHttpTraceFormat.ts rename to packages/opentelemetry-propagator-jaeger/src/context/propagation/JaegerHttpTraceFormat.ts diff --git a/packages/opentelemetry-propagation-jaeger/test/context/JaegerHttpTraceFormat.test.ts b/packages/opentelemetry-propagator-jaeger/test/context/JaegerHttpTraceFormat.test.ts similarity index 100% rename from packages/opentelemetry-propagation-jaeger/test/context/JaegerHttpTraceFormat.test.ts rename to packages/opentelemetry-propagator-jaeger/test/context/JaegerHttpTraceFormat.test.ts diff --git a/packages/opentelemetry-propagation-jaeger/tsconfig-release.json b/packages/opentelemetry-propagator-jaeger/tsconfig-release.json similarity index 100% rename from packages/opentelemetry-propagation-jaeger/tsconfig-release.json rename to packages/opentelemetry-propagator-jaeger/tsconfig-release.json diff --git a/packages/opentelemetry-propagation-jaeger/tsconfig.json b/packages/opentelemetry-propagator-jaeger/tsconfig.json similarity index 100% rename from packages/opentelemetry-propagation-jaeger/tsconfig.json rename to packages/opentelemetry-propagator-jaeger/tsconfig.json diff --git a/packages/opentelemetry-propagation-jaeger/tslint.json b/packages/opentelemetry-propagator-jaeger/tslint.json similarity index 100% rename from packages/opentelemetry-propagation-jaeger/tslint.json rename to packages/opentelemetry-propagator-jaeger/tslint.json From 0d41630115bf775f7555592ad842e23739fe58b7 Mon Sep 17 00:00:00 2001 From: Uladzislau Kiva Date: Fri, 17 Jan 2020 01:35:06 +0300 Subject: [PATCH 19/25] feat: added index.ts and version.ts, revert test for browser --- .../package.json | 1 + .../src/index.ts | 17 +++++++++++++++++ .../src/version.ts | 18 ++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 packages/opentelemetry-propagator-jaeger/src/index.ts create mode 100644 packages/opentelemetry-propagator-jaeger/src/version.ts diff --git a/packages/opentelemetry-propagator-jaeger/package.json b/packages/opentelemetry-propagator-jaeger/package.json index c1f7237532..ced76d1989 100644 --- a/packages/opentelemetry-propagator-jaeger/package.json +++ b/packages/opentelemetry-propagator-jaeger/package.json @@ -7,6 +7,7 @@ "repository": "open-telemetry/opentelemetry-js", "scripts": { "test": "nyc ts-mocha -p tsconfig.json test/**/*.ts", + "test:browser": "nyc karma start --single-run", "tdd": "yarn tdd:node", "tdd:node": "yarn test -- --watch-extensions ts --watch", "tdd:browser": "karma start", diff --git a/packages/opentelemetry-propagator-jaeger/src/index.ts b/packages/opentelemetry-propagator-jaeger/src/index.ts new file mode 100644 index 0000000000..e5a078f09c --- /dev/null +++ b/packages/opentelemetry-propagator-jaeger/src/index.ts @@ -0,0 +1,17 @@ +/*! + * Copyright 2020, OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './context/propagation/JaegerHttpTraceFormat.js'; diff --git a/packages/opentelemetry-propagator-jaeger/src/version.ts b/packages/opentelemetry-propagator-jaeger/src/version.ts new file mode 100644 index 0000000000..2efbb00dcb --- /dev/null +++ b/packages/opentelemetry-propagator-jaeger/src/version.ts @@ -0,0 +1,18 @@ +/*! + * Copyright 2019, OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// this is autogenerated file, see scripts/version-update.js +export const VERSION = '0.3.2'; From 89be82a18a6b25dab360d419c8fb5e289c7fde54 Mon Sep 17 00:00:00 2001 From: vladislav-kiva Date: Fri, 17 Jan 2020 10:31:36 +0300 Subject: [PATCH 20/25] fix: tests added index-webpack.ts --- .../test/index-webpack.ts | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 packages/opentelemetry-propagator-jaeger/test/index-webpack.ts diff --git a/packages/opentelemetry-propagator-jaeger/test/index-webpack.ts b/packages/opentelemetry-propagator-jaeger/test/index-webpack.ts new file mode 100644 index 0000000000..2709346bf1 --- /dev/null +++ b/packages/opentelemetry-propagator-jaeger/test/index-webpack.ts @@ -0,0 +1,23 @@ +/*! + * Copyright 2020, OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This file is the webpack entry point for the browser Karma tests. It requires +// all modules ending in "test" from the current folder and all its subfolders. +const testsContext = require.context('.', true, /test$/); +testsContext.keys().forEach(testsContext); + +const srcContext = require.context('.', true, /src$/); +srcContext.keys().forEach(srcContext); From 5c3db8000b3082cefd368570e76616c270680fa4 Mon Sep 17 00:00:00 2001 From: vladislav-kiva Date: Fri, 17 Jan 2020 11:48:02 +0300 Subject: [PATCH 21/25] test: add test with span generated by jaeger client --- .../test/context/JaegerHttpTraceFormat.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/opentelemetry-propagator-jaeger/test/context/JaegerHttpTraceFormat.test.ts b/packages/opentelemetry-propagator-jaeger/test/context/JaegerHttpTraceFormat.test.ts index 6b8fa25b90..3026a78e72 100644 --- a/packages/opentelemetry-propagator-jaeger/test/context/JaegerHttpTraceFormat.test.ts +++ b/packages/opentelemetry-propagator-jaeger/test/context/JaegerHttpTraceFormat.test.ts @@ -75,6 +75,19 @@ describe('JaegerHttpTraceFormat', () => { }); }); + it('should extract context of a sampled span from carrier with 1 bit flag', () => { + carrier[UBER_TRACE_ID_HEADER] = + '9c41e35aeb6d1272:45fd2a9709dadcf1:a13699e3fb724f40:1'; + const extractedSpanContext = jaegerHttpTraceFormat.extract('', carrier); + + assert.deepStrictEqual(extractedSpanContext, { + spanId: '45fd2a9709dadcf1', + traceId: '9c41e35aeb6d1272', + isRemote: true, + traceFlags: TraceFlags.SAMPLED, + }); + }); + it('should use custom header if provided', () => { carrier[customHeader] = 'd4cda95b652f4a1592b449d5929fda1b:6e0c63257de34c92:0:01'; From 733016125fabcd8535f95124d654e03d2d43462f Mon Sep 17 00:00:00 2001 From: Uladzislau Kiva Date: Fri, 17 Jan 2020 23:09:03 +0300 Subject: [PATCH 22/25] fix: apply review changes --- .../opentelemetry-propagator-jaeger/README.md | 34 ++++++++++++++---- .../jaeger-tracing.png | Bin 0 -> 61523 bytes .../package.json | 2 +- .../propagation/JaegerHttpTraceFormat.ts | 28 +++++++++++---- .../src/index.ts | 2 +- 5 files changed, 50 insertions(+), 16 deletions(-) create mode 100644 packages/opentelemetry-propagator-jaeger/jaeger-tracing.png diff --git a/packages/opentelemetry-propagator-jaeger/README.md b/packages/opentelemetry-propagator-jaeger/README.md index fd7fa592a6..904ad2fff0 100644 --- a/packages/opentelemetry-propagator-jaeger/README.md +++ b/packages/opentelemetry-propagator-jaeger/README.md @@ -5,7 +5,24 @@ [![devDependencies][devDependencies-image]][devDependencies-url] [![Apache License][license-image]][license-image] -OpenTelemetry propagation Jaeger provide HTTP header propagation for systems that using Jaeger HTTP header format. +OpenTelemetry propagator-jaeger provide HTTP header propagation for systems that using Jaeger HTTP header format. + +Format: +{trace-id}:{span-id}:{parent-span-id}:{flags} + +* {trace-id} + * 64-bit or 128-bit random number in base16 format. + * Can be variable length, shorter values are 0-padded on the left. + * Value of 0 is invalid. + +* {span-id} + * 64-bit random number in base16 format. + +* {parent-span-id} + * Set to 0 because this field is deprecated. +* {flags} + * One byte bitmap, as two hex digits. + Example of usage: ```javascript const { NodeTracerRegistry } = require('@opentelemetry/node'); @@ -16,6 +33,9 @@ const registry = new NodeTracerRegistry({ }); ``` +## Trace on Jaeger UI + +![example image](jaeger-tracing.png) ## Useful links - For more information on OpenTelemetry, visit: @@ -30,9 +50,9 @@ Apache 2.0 - See [LICENSE][license-url] for more information. [gitter-url]: https://gitter.im/open-telemetry/opentelemetry-node?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge [license-url]: https://github.com/open-telemetry/opentelemetry-js/blob/master/LICENSE [license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat -[dependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/status.svg?path=packages/opentelemetry-core -[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-core -[devDependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/dev-status.svg?path=packages/opentelemetry-core -[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-core&type=dev -[npm-url]: https://www.npmjs.com/package/@opentelemetry/core -[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fcore.svg +[dependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/status.svg?path=packages/opentelemetry-propagator-jaeger +[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-propagator-jaeger +[devDependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/dev-status.svg?path=packages/opentelemetry-propagator-jaeger +[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-propagator-jaeger&type=dev +[npm-url]: https://www.npmjs.com/package/@opentelemetry/propagator-jaeger +[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fpropagator-jaeger.svg diff --git a/packages/opentelemetry-propagator-jaeger/jaeger-tracing.png b/packages/opentelemetry-propagator-jaeger/jaeger-tracing.png new file mode 100644 index 0000000000000000000000000000000000000000..0c8693a2b51f612c02414cfea96e472f5ec1eceb GIT binary patch literal 61523 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 ?Z9tFlXCaH+}q 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 Date: Fri, 17 Jan 2020 23:31:34 +0300 Subject: [PATCH 23/25] fix: move out from sub dirs --- .../src/{context/propagation => }/JaegerHttpTraceFormat.ts | 0 packages/opentelemetry-propagator-jaeger/src/index.ts | 2 +- .../test/{context => }/JaegerHttpTraceFormat.test.ts | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename packages/opentelemetry-propagator-jaeger/src/{context/propagation => }/JaegerHttpTraceFormat.ts (100%) rename packages/opentelemetry-propagator-jaeger/test/{context => }/JaegerHttpTraceFormat.test.ts (98%) diff --git a/packages/opentelemetry-propagator-jaeger/src/context/propagation/JaegerHttpTraceFormat.ts b/packages/opentelemetry-propagator-jaeger/src/JaegerHttpTraceFormat.ts similarity index 100% rename from packages/opentelemetry-propagator-jaeger/src/context/propagation/JaegerHttpTraceFormat.ts rename to packages/opentelemetry-propagator-jaeger/src/JaegerHttpTraceFormat.ts diff --git a/packages/opentelemetry-propagator-jaeger/src/index.ts b/packages/opentelemetry-propagator-jaeger/src/index.ts index d7c17b2e00..620c254f23 100644 --- a/packages/opentelemetry-propagator-jaeger/src/index.ts +++ b/packages/opentelemetry-propagator-jaeger/src/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export * from './context/propagation/JaegerHttpTraceFormat'; +export * from './JaegerHttpTraceFormat'; diff --git a/packages/opentelemetry-propagator-jaeger/test/context/JaegerHttpTraceFormat.test.ts b/packages/opentelemetry-propagator-jaeger/test/JaegerHttpTraceFormat.test.ts similarity index 98% rename from packages/opentelemetry-propagator-jaeger/test/context/JaegerHttpTraceFormat.test.ts rename to packages/opentelemetry-propagator-jaeger/test/JaegerHttpTraceFormat.test.ts index 3026a78e72..a81dc92ffa 100644 --- a/packages/opentelemetry-propagator-jaeger/test/context/JaegerHttpTraceFormat.test.ts +++ b/packages/opentelemetry-propagator-jaeger/test/JaegerHttpTraceFormat.test.ts @@ -18,7 +18,7 @@ import * as assert from 'assert'; import { JaegerHttpTraceFormat, UBER_TRACE_ID_HEADER, -} from '../../src/context/propagation/JaegerHttpTraceFormat'; +} from '../src/JaegerHttpTraceFormat'; import { SpanContext, TraceFlags } from '@opentelemetry/types'; describe('JaegerHttpTraceFormat', () => { From bda98311feabdba5ce0e8aca694ae55a122565ce Mon Sep 17 00:00:00 2001 From: Uladzislau Kiva Date: Sat, 18 Jan 2020 00:07:25 +0300 Subject: [PATCH 24/25] docs: use common language for docs --- packages/opentelemetry-propagator-jaeger/README.md | 2 +- packages/opentelemetry-propagator-jaeger/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/opentelemetry-propagator-jaeger/README.md b/packages/opentelemetry-propagator-jaeger/README.md index 904ad2fff0..5c6771c3a3 100644 --- a/packages/opentelemetry-propagator-jaeger/README.md +++ b/packages/opentelemetry-propagator-jaeger/README.md @@ -5,7 +5,7 @@ [![devDependencies][devDependencies-image]][devDependencies-url] [![Apache License][license-image]][license-image] -OpenTelemetry propagator-jaeger provide HTTP header propagation for systems that using Jaeger HTTP header format. +OpenTelemetry Jaeger propagator provides HTTP header propagation for systems that are using Jaeger HTTP header format. Format: {trace-id}:{span-id}:{parent-span-id}:{flags} diff --git a/packages/opentelemetry-propagator-jaeger/package.json b/packages/opentelemetry-propagator-jaeger/package.json index cff4c86099..8c2a8eeee8 100644 --- a/packages/opentelemetry-propagator-jaeger/package.json +++ b/packages/opentelemetry-propagator-jaeger/package.json @@ -1,7 +1,7 @@ { "name": "@opentelemetry/propagator-jaeger", "version": "0.3.2", - "description": "OpenTelemetry propagator-jaeger provide HTTP header propagation for systems that using Jaeger HTTP header format.\n", + "description": "OpenTelemetry Jaeger propagator provides HTTP header propagation for systems that are using Jaeger HTTP header format.", "main": "build/src/index.js", "types": "build/src/index.d.ts", "repository": "open-telemetry/opentelemetry-js", From e0e7b85514e61e1a5c17c6718e6d9699e9677458 Mon Sep 17 00:00:00 2001 From: Uladzislau Kiva Date: Sat, 18 Jan 2020 01:01:00 +0300 Subject: [PATCH 25/25] fix: test script fix --- packages/opentelemetry-propagator-jaeger/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opentelemetry-propagator-jaeger/package.json b/packages/opentelemetry-propagator-jaeger/package.json index 8c2a8eeee8..fd7d45f807 100644 --- a/packages/opentelemetry-propagator-jaeger/package.json +++ b/packages/opentelemetry-propagator-jaeger/package.json @@ -6,7 +6,7 @@ "types": "build/src/index.d.ts", "repository": "open-telemetry/opentelemetry-js", "scripts": { - "test": "nyc ts-mocha -p tsconfig.json test/**/*.ts", + "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.ts' --exclude 'test/index-webpack.ts'", "test:browser": "nyc karma start --single-run", "tdd": "yarn tdd:node", "tdd:node": "yarn test -- --watch-extensions ts --watch",