Skip to content

Commit

Permalink
feat(@opentelemetry/propagator-jaeger): support custom baggage prefix
Browse files Browse the repository at this point in the history
  • Loading branch information
sschegolev committed Dec 21, 2021
1 parent 2c8601f commit 9ba00cb
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 10 deletions.
24 changes: 14 additions & 10 deletions packages/opentelemetry-propagator-jaeger/src/JaegerPropagator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ import {
TraceFlags,
} from '@opentelemetry/api';
import { isTracingSuppressed } from '@opentelemetry/core';
import { JaegerPropagatorBackwardCompatibleConfig } from './types';

export const UBER_TRACE_ID_HEADER = 'uber-trace-id';
export const UBER_BAGGAGE_HEADER_PREFIX = 'uberctx';
const UBER_BAGGAGE_HEADER_REGEX = /^uberctx-(.+)/i;

/**
* Propagates {@link SpanContext} through Trace Context format propagation.
Expand All @@ -47,12 +47,16 @@ const UBER_BAGGAGE_HEADER_REGEX = /^uberctx-(.+)/i;
*/
export class JaegerPropagator implements TextMapPropagator {
private readonly _jaegerTraceHeader: string;

/**
* @param {string} [customTraceHeader="uber-trace-id"] - HTTP header to inject\extract trace from.
**/
constructor(customTraceHeader?: string) {
this._jaegerTraceHeader = customTraceHeader || UBER_TRACE_ID_HEADER;
private readonly _jaegerBaggageHeaderPrefix: string;

constructor(config?: JaegerPropagatorBackwardCompatibleConfig) {
if (typeof config === 'string') {
this._jaegerTraceHeader = config;
this._jaegerBaggageHeaderPrefix = UBER_BAGGAGE_HEADER_PREFIX;
} else {
this._jaegerTraceHeader = config?.customTraceHeader || UBER_TRACE_ID_HEADER;
this._jaegerBaggageHeaderPrefix = config?.customBaggageHeaderPrefix || UBER_BAGGAGE_HEADER_PREFIX;
}
}

inject(context: Context, carrier: unknown, setter: TextMapSetter): void {
Expand All @@ -74,7 +78,7 @@ export class JaegerPropagator implements TextMapPropagator {
for (const [key, entry] of baggage.getAllEntries()) {
setter.set(
carrier,
`${UBER_BAGGAGE_HEADER_PREFIX}-${key}`,
`${this._jaegerBaggageHeaderPrefix}-${key}`,
encodeURIComponent(entry.value)
);
}
Expand All @@ -88,11 +92,11 @@ export class JaegerPropagator implements TextMapPropagator {
: uberTraceIdHeader;
const baggageValues = getter
.keys(carrier)
.filter(key => UBER_BAGGAGE_HEADER_REGEX.test(key))
.filter(key => key.startsWith(`${this._jaegerBaggageHeaderPrefix}-`))
.map(key => {
const value = getter.get(carrier, key);
return {
key: key.substring(UBER_BAGGAGE_HEADER_PREFIX.length + 1),
key: key.substring(this._jaegerBaggageHeaderPrefix.length + 1),
value: Array.isArray(value) ? value[0] : value,
};
});
Expand Down
26 changes: 26 additions & 0 deletions packages/opentelemetry-propagator-jaeger/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright The 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 type CustomTraceHeader = string;

export type CustomBaggageHeaderPrefix = string;

export interface JaegerPropagatorConfig {
customTraceHeader?: CustomTraceHeader,
customBaggageHeaderPrefix?: CustomBaggageHeaderPrefix,
}

export type JaegerPropagatorBackwardCompatibleConfig = CustomTraceHeader | JaegerPropagatorConfig;
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@ import {
describe('JaegerPropagator', () => {
const jaegerPropagator = new JaegerPropagator();
const customHeader = 'new-header';
const customBaggageHeaderPrefix = 'custom-baggage-header-prefix';
const customJaegerPropagator = new JaegerPropagator(customHeader);
const customJaegerPropagatorWithConfig = new JaegerPropagator({
customTraceHeader: customHeader,
customBaggageHeaderPrefix,
});
let carrier: { [key: string]: unknown };

beforeEach(() => {
Expand Down Expand Up @@ -114,6 +119,28 @@ describe('JaegerPropagator', () => {
encodeURIComponent('%id%')
);
});

it('should propagate baggage with custom prefix with url encoded values', () => {
const baggage = propagation.createBaggage({
test: {
value: '1',
},
myuser: {
value: '%id%',
},
});

customJaegerPropagatorWithConfig.inject(
propagation.setBaggage(ROOT_CONTEXT, baggage),
carrier,
defaultTextMapSetter
);
assert.strictEqual(carrier[`${customBaggageHeaderPrefix}-test`], '1');
assert.strictEqual(
carrier[`${customBaggageHeaderPrefix}-myuser`],
encodeURIComponent('%id%')
);
});
});

describe('.extract()', () => {
Expand Down Expand Up @@ -215,6 +242,21 @@ describe('JaegerPropagator', () => {
assert(secondEntry.value === '%id%');
});

it('should extract baggage with custom prefix from carrier', () => {
carrier[`${customBaggageHeaderPrefix}-test`] = 'value';
carrier[`${customBaggageHeaderPrefix}-myuser`] = '%25id%25';
const extractedBaggage = propagation.getBaggage(
customJaegerPropagatorWithConfig.extract(ROOT_CONTEXT, carrier, defaultTextMapGetter)
);

const firstEntry = extractedBaggage?.getEntry('test');
assert(typeof firstEntry !== 'undefined');
assert(firstEntry.value === 'value');
const secondEntry = extractedBaggage?.getEntry('myuser');
assert(typeof secondEntry !== 'undefined');
assert(secondEntry.value === '%id%');
});

it('should extract baggage from carrier and not override current one', () => {
carrier[`${UBER_BAGGAGE_HEADER_PREFIX}-test`] = 'value';
carrier[`${UBER_BAGGAGE_HEADER_PREFIX}-myuser`] = '%25id%25';
Expand Down Expand Up @@ -266,6 +308,9 @@ describe('JaegerPropagator', () => {
it('returns the customized header if customized', () => {
assert.deepStrictEqual(customJaegerPropagator.fields(), [customHeader]);
});
it('returns the customized header if customized with config', () => {
assert.deepStrictEqual(customJaegerPropagatorWithConfig.fields(), [customHeader]);
});
});

it('should fail gracefully on bad responses from getter', () => {
Expand Down

0 comments on commit 9ba00cb

Please sign in to comment.