Skip to content

Commit

Permalink
Merge branch 'main' into te
Browse files Browse the repository at this point in the history
  • Loading branch information
dyladan authored May 11, 2021
2 parents 63ade70 + 5f7ec00 commit 6a9a3a9
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 49 deletions.
26 changes: 11 additions & 15 deletions examples/http/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,17 @@ function handleRequest(request, response) {
});
// Annotate our span to capture metadata about the operation
span.addEvent('invoking handleRequest');
try {
const body = [];
request.on('error', (err) => console.log(err));
request.on('data', (chunk) => body.push(chunk));
request.on('end', () => {
// deliberately sleeping to mock some action.
setTimeout(() => {
span.end();
response.end('Hello World!');
}, 2000);
});
} catch (err) {
console.error(err);
span.end();
}

const body = [];
request.on('error', (err) => console.log(err));
request.on('data', (chunk) => body.push(chunk));
request.on('end', () => {
// deliberately sleeping to mock some action.
setTimeout(() => {
span.end();
response.end('Hello World!');
}, 2000);
});
}

startServer(8080);
26 changes: 11 additions & 15 deletions examples/https/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,17 @@ function handleRequest(request, response) {
});
// Annotate our span to capture metadata about the operation
span.addEvent('invoking handleRequest');
try {
const body = [];
request.on('error', (err) => console.log(err));
request.on('data', (chunk) => body.push(chunk));
request.on('end', () => {
// deliberately sleeping to mock some action.
setTimeout(() => {
span.end();
response.end('Hello World!');
}, 2000);
});
} catch (err) {
console.log(err);
span.end();
}

const body = [];
request.on('error', (err) => console.log(err));
request.on('data', (chunk) => body.push(chunk));
request.on('end', () => {
// deliberately sleeping to mock some action.
setTimeout(() => {
span.end();
response.end('Hello World!');
}, 2000);
});
}

startServer(443);
1 change: 1 addition & 0 deletions packages/opentelemetry-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export * from './trace/sampler/AlwaysOnSampler';
export * from './trace/sampler/ParentBasedSampler';
export * from './trace/sampler/TraceIdRatioBasedSampler';
export * from './trace/TraceState';
export * from './utils/environment';
export * from './utils/sampling';
export * from './utils/url';
export * from './utils/wrap';
Expand Down
5 changes: 5 additions & 0 deletions packages/opentelemetry-propagator-jaeger/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ provider.register({
});
```

## Baggage Notes

Jeager Baggage is represented as multiple headers where the names are carrier dependent. For this reason, they are omitted from the `fields` method. This behavior should be taken into account if your application relies on the `fields` functionality. See the [specification][fields-spec-url] for more details.

## Trace on Jaeger UI

![example image](jaeger-tracing.png)
Expand All @@ -58,3 +62,4 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[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
[fields-spec-url]: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/context/api-propagators.md#fields
77 changes: 59 additions & 18 deletions packages/opentelemetry-propagator-jaeger/src/JaegerPropagator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,22 @@

import {
Context,
getBaggage,
getSpanContext,
setBaggage,
setSpanContext,
SpanContext,
TraceFlags,
TextMapGetter,
TextMapPropagator,
TextMapSetter,
isInstrumentationSuppressed,
createBaggage,
} from '@opentelemetry/api';

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 Down Expand Up @@ -55,31 +60,67 @@ export class JaegerPropagator implements TextMapPropagator {

inject(context: Context, carrier: unknown, setter: TextMapSetter) {
const spanContext = getSpanContext(context);
if (!spanContext || isInstrumentationSuppressed(context)) return;

const traceFlags = `0${(spanContext.traceFlags || TraceFlags.NONE).toString(
16
)}`;

setter.set(
carrier,
this._jaegerTraceHeader,
`${spanContext.traceId}:${spanContext.spanId}:0:${traceFlags}`
);
const baggage = getBaggage(context);
if (spanContext && isInstrumentationSuppressed(context) === false) {
const traceFlags = `0${(
spanContext.traceFlags || TraceFlags.NONE
).toString(16)}`;

setter.set(
carrier,
this._jaegerTraceHeader,
`${spanContext.traceId}:${spanContext.spanId}:0:${traceFlags}`
);
}

if (baggage) {
for (const [key, entry] of baggage.getAllEntries()) {
setter.set(
carrier,
`${UBER_BAGGAGE_HEADER_PREFIX}-${key}`,
encodeURIComponent(entry.value)
);
}
}
}

extract(context: Context, carrier: unknown, getter: TextMapGetter): Context {
const uberTraceIdHeader = getter.get(carrier, this._jaegerTraceHeader);
const uberTraceId = Array.isArray(uberTraceIdHeader)
? uberTraceIdHeader[0]
: uberTraceIdHeader;

if (typeof uberTraceId !== 'string') return context;

const spanContext = deserializeSpanContext(uberTraceId);
if (!spanContext) return context;

return setSpanContext(context, spanContext);
const baggageValues = getter
.keys(carrier)
.filter(key => UBER_BAGGAGE_HEADER_REGEX.test(key))
.map(key => {
const value = getter.get(carrier, key);
return {
key: key.substring(UBER_BAGGAGE_HEADER_PREFIX.length + 1),
value: Array.isArray(value) ? value[0] : value,
};
});

let newContext = context;
// if the trace id header is present and valid, inject it into the context
if (typeof uberTraceId === 'string') {
const spanContext = deserializeSpanContext(uberTraceId);
if (spanContext) {
newContext = setSpanContext(newContext, spanContext);
}
}
if (baggageValues.length === 0) return newContext;

// if baggage values are present, inject it into the current baggage
let currentBaggage = getBaggage(context) ?? createBaggage();
for (const baggageEntry of baggageValues) {
if (baggageEntry.value === undefined) continue;
currentBaggage = currentBaggage.setEntry(baggageEntry.key, {
value: decodeURIComponent(baggageEntry.value),
});
}
newContext = setBaggage(newContext, currentBaggage);

return newContext;
}

fields(): string[] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@
*/

import {
createBaggage,
defaultTextMapGetter,
defaultTextMapSetter,
getBaggage,
getSpanContext,
ROOT_CONTEXT,
setBaggage,
setSpanContext,
SpanContext,
suppressInstrumentation,
Expand All @@ -29,6 +32,7 @@ import * as assert from 'assert';
import {
JaegerPropagator,
UBER_TRACE_ID_HEADER,
UBER_BAGGAGE_HEADER_PREFIX,
} from '../src/JaegerPropagator';

describe('JaegerPropagator', () => {
Expand Down Expand Up @@ -92,6 +96,28 @@ describe('JaegerPropagator', () => {
);
assert.strictEqual(carrier[UBER_TRACE_ID_HEADER], undefined);
});

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

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

describe('.extract()', () => {
Expand Down Expand Up @@ -177,6 +203,64 @@ describe('JaegerPropagator', () => {
undefined
);
});

it('should extract baggage from carrier', () => {
carrier[`${UBER_BAGGAGE_HEADER_PREFIX}-test`] = 'value';
carrier[`${UBER_BAGGAGE_HEADER_PREFIX}-myuser`] = '%25id%25';
const extractedBaggage = getBaggage(
jaegerPropagator.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';
const extractedBaggage = getBaggage(
jaegerPropagator.extract(
setBaggage(ROOT_CONTEXT, createBaggage({ one: { value: 'two' } })),
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%');
const alreadyExistingEntry = extractedBaggage?.getEntry('one');
assert(typeof alreadyExistingEntry !== 'undefined');
assert(alreadyExistingEntry.value === 'two');
});

it('should handle invalid baggage from carrier (undefined)', () => {
carrier[`${UBER_BAGGAGE_HEADER_PREFIX}-test`] = undefined;
const extractedBaggage = getBaggage(
jaegerPropagator.extract(ROOT_CONTEXT, carrier, defaultTextMapGetter)
);

const firstEntry = extractedBaggage?.getEntry('test');
assert(typeof firstEntry === 'undefined');
});

it('should handle invalid baggage from carrier (array)', () => {
carrier[`${UBER_BAGGAGE_HEADER_PREFIX}-test`] = ['one', 'two'];
const extractedBaggage = getBaggage(
jaegerPropagator.extract(ROOT_CONTEXT, carrier, defaultTextMapGetter)
);

const firstEntry = extractedBaggage?.getEntry('test');
assert(typeof firstEntry !== 'undefined');
assert(firstEntry.value === 'one');
});
});

describe('.fields()', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/opentelemetry-tracing/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ import {
getEnv,
TracesSamplerValues,
ParentBasedSampler,
ENVIRONMENT,
TraceIdRatioBasedSampler,
} from '@opentelemetry/core';
import { ENVIRONMENT } from '@opentelemetry/core/src/utils/environment';

const env = getEnv();
const FALLBACK_OTEL_TRACES_SAMPLER = TracesSamplerValues.AlwaysOn;
Expand Down

0 comments on commit 6a9a3a9

Please sign in to comment.