Skip to content

Commit b523e8e

Browse files
Ashish AggarwalAshish Aggarwal
authored andcommitted
Adding propagators for textmap and http formats
1 parent ecb9bf4 commit b523e8e

6 files changed

Lines changed: 225 additions & 0 deletions

File tree

src/propagators/default_codex.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2018 Expedia, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {Codex} from './propagator';
18+
19+
export default class DefaultCodex implements Codex {
20+
constructor() { }
21+
22+
encode(value: string): string {
23+
return value;
24+
}
25+
26+
decode(value: string): string {
27+
return value;
28+
}
29+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2018 Expedia, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {Propagator} from './propagator';
18+
19+
export default class PropagationRegistry {
20+
_propagators: any;
21+
22+
constructor() {
23+
this._propagators = {};
24+
}
25+
26+
register(format: string, propagator: Propagator): void {
27+
this._propagators[format] = propagator;
28+
}
29+
30+
propagator(format): Propagator {
31+
return this._propagators[format];
32+
}
33+
}

src/propagators/propagator.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2018 Expedia, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import SpanContext from '../span_context';
18+
19+
export class PropagatorOpts {
20+
_traceIdKey: string;
21+
_spanIdKey: string;
22+
_parentSpanIdKey: string;
23+
_baggageKeyPrefix: string;
24+
25+
traceIdKey(): string {
26+
return this._traceIdKey || 'Trace-ID';
27+
}
28+
29+
spanIdKey(): string {
30+
return this._spanIdKey || 'Span-ID';
31+
}
32+
33+
parentSpanIdKey(): string {
34+
return this._parentSpanIdKey || 'Parent-ID';
35+
}
36+
37+
baggageKeyPrefix(): string {
38+
return this._baggageKeyPrefix || 'Baggage-';
39+
}
40+
}
41+
42+
export interface Propagator {
43+
inject(spanContext: SpanContext, carrier: any): void;
44+
extract(carrier: any): SpanContext;
45+
}
46+
47+
export interface Codex {
48+
encode(value: string): string;
49+
decode(value: string): string;
50+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2018 Expedia, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {Codex, Propagator, PropagatorOpts} from './propagator';
18+
import SpanContext from '../span_context';
19+
import DefaultCodex from './default_codex';
20+
21+
export default class TextMapPropagator implements Propagator {
22+
_opts: PropagatorOpts;
23+
_codex: Codex;
24+
25+
constructor(codex: Codex = new DefaultCodex(), opts: PropagatorOpts = new PropagatorOpts()) {
26+
this._opts = opts;
27+
this._codex = codex;
28+
}
29+
30+
inject(spanContext: SpanContext, carrier: any): void {
31+
carrier[this._opts.traceIdKey()] = spanContext.traceId();
32+
carrier[this._opts.spanIdKey()] = spanContext.spanId();
33+
carrier[this._opts.parentSpanIdKey()] = spanContext.parentSpanId();
34+
35+
const baggage = spanContext.baggage();
36+
for (const key in baggage) {
37+
if (baggage.hasOwnProperty(key)) {
38+
carrier[`${this._opts.baggageKeyPrefix()}${key}`] = this._codex.encode(spanContext.baggage[key]);
39+
}
40+
}
41+
}
42+
43+
extract(carrier: any): SpanContext {
44+
const baggage = {};
45+
for (const key in carrier) {
46+
if (carrier.hasOwnProperty(key) && key.indexOf(this._opts.baggageKeyPrefix()) === 0) {
47+
const keySansPrefix = key.substring(this._opts.baggageKeyPrefix().length);
48+
baggage[keySansPrefix] = this._codex.decode(carrier[key]);
49+
}
50+
}
51+
return new SpanContext(carrier[this._opts.traceIdKey()], carrier[this._opts.spanIdKey()], carrier[this._opts.parentSpanIdKey()], baggage);
52+
}
53+
}

src/propagators/url_codex.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2018 Expedia, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {Codex} from './propagator';
18+
19+
export default class URLCodex implements Codex {
20+
encode(value: string): string {
21+
return encodeURI(value);
22+
}
23+
24+
decode(value: string): string {
25+
return decodeURI(value);
26+
}
27+
}

src/tracer.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ import SpanContext from './span_context';
2323
import NoopDispatcher from './dispatchers/noop';
2424
import NullLogger from './logger';
2525
import Utils from './utils';
26+
import PropagationRegistry from './propagators/propagation_registry';
27+
import TextMapPropagator from './propagators/textmap_propagator';
28+
import URLCodex from './propagators/url_codex';
2629

2730
// startSpanFields is used for type-checking the Trace.startSpan().
2831
declare interface StartSpanFields {
@@ -38,6 +41,7 @@ export default class Tracer {
3841
_dispatcher: Dispatcher;
3942
_commonTags: any;
4043
_logger: any;
44+
_registry: PropagationRegistry;
4145

4246
constructor(serviceName: string,
4347
dispatcher = new NoopDispatcher(),
@@ -47,6 +51,9 @@ export default class Tracer {
4751
this._serviceName = serviceName;
4852
this._dispatcher = dispatcher;
4953
this._logger = logger;
54+
this._registry = new PropagationRegistry();
55+
this._registry.register(opentracing.FORMAT_TEXT_MAP, new TextMapPropagator());
56+
this._registry.register(opentracing.FORMAT_HTTP_HEADERS, new TextMapPropagator(new URLCodex()));
5057
}
5158

5259
startSpan(operationName: string, fields?: StartSpanFields): Span {
@@ -123,6 +130,32 @@ export default class Tracer {
123130
});
124131
}
125132

133+
inject(spanContext: SpanContext, format: string, carrier: any): void {
134+
if (!spanContext) {
135+
return;
136+
}
137+
138+
const propagator = this._registry._propagators(format);
139+
if (!propagator) {
140+
throw new Error('injector for the given format is not supported');
141+
}
142+
143+
propagator.inject(spanContext, carrier);
144+
}
145+
146+
extract(format: string, carrier: any): SpanContext {
147+
if (!carrier) {
148+
return;
149+
}
150+
151+
const propagator = this._registry._propagators(format);
152+
if (!propagator) {
153+
throw new Error('extracttor for the given format is not supported');
154+
}
155+
156+
return propagator.extract(carrier);
157+
}
158+
126159
static initTracer(config): Tracer {
127160
if (config.disable) {
128161
return new opentracing.Tracer();

0 commit comments

Comments
 (0)