Skip to content

Commit

Permalink
adding opentracing api compatibility test spec
Browse files Browse the repository at this point in the history
  • Loading branch information
Ashish Aggarwal authored and Ashish Aggarwal committed Aug 2, 2018
1 parent 78649af commit d5c352c
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 57 deletions.
3 changes: 3 additions & 0 deletions examples/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ const clientChildSpan = tracer.startSpan('downstream-service-call', {
clientChildSpan.setTag(opentracing.Tags.ERROR, true);
clientChildSpan.setTag(opentracing.Tags.HTTP_STATUS_CODE, 503);
clientChildSpan.addTags({'child-custom-tag-1': 1, 'child-custom-tag-2': 'someval'});
clientChildSpan.log({
eventCode: 1001
});

serverSpan.setTag(opentracing.Tags.ERROR, true);
serverSpan.setTag('my-custom-tag', 10.5);
Expand Down
8 changes: 4 additions & 4 deletions src/dispatchers/remote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ export default class RemoteDispatcher implements Dispatcher {
_logger: any;

constructor(agentHost: string, agentPort: number, logger = new NullLogger()) {
logger.info(`Initializing the remote dispatcher, connecting at ${agentHost}:${agentPort}`);
agentHost = agentHost || 'haystack-agent';
agentPort = agentPort || 35000;
logger.info(`Initializing the remote dispatcher, connecting at ${agentHost}:${agentPort}`);
this._client = new services.SpanAgentClient(`${agentHost}:${agentPort}`, grpc.credentials.createInsecure());
this._logger = logger;
}
Expand Down Expand Up @@ -63,9 +63,9 @@ export default class RemoteDispatcher implements Dispatcher {
const protoSpan = new messages.Span();
protoSpan.setServicename(span.serviceName());
protoSpan.setOperationname(span.operationName());
protoSpan.setTraceid(span.context().traceId());
protoSpan.setSpanid(span.context().spanId());
protoSpan.setParentspanid(span.context().parentSpanId());
protoSpan.setTraceid(span.context().traceId);
protoSpan.setSpanid(span.context().spanId);
protoSpan.setParentspanid(span.context().parentSpanId);
protoSpan.setStarttime(span.startTime());
protoSpan.setDuration(span.duration());

Expand Down
27 changes: 27 additions & 0 deletions src/propagators/binary_propagator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2018 Expedia, Inc.
*
* 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.
*/

import {Propagator} from './propagator';
import SpanContext from '../span_context';

export default class BinaryPropagator implements Propagator {
inject(spanContext: SpanContext, carrier: any): void {
}

extract(carrier: any): SpanContext {
return null;
}
}
10 changes: 5 additions & 5 deletions src/propagators/textmap_propagator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ export default class TextMapPropagator implements Propagator {
}

inject(spanContext: SpanContext, carrier: any): void {
carrier[this._opts.traceIdKey()] = spanContext.traceId();
carrier[this._opts.spanIdKey()] = spanContext.spanId();
carrier[this._opts.parentSpanIdKey()] = spanContext.parentSpanId();
carrier[this._opts.traceIdKey()] = spanContext.traceId;
carrier[this._opts.spanIdKey()] = spanContext.spanId;
carrier[this._opts.parentSpanIdKey()] = spanContext.parentSpanId;

const baggage = spanContext.baggage();
const baggage = spanContext.baggage;
for (const key in baggage) {
if (baggage.hasOwnProperty(key)) {
carrier[`${this._opts.baggageKeyPrefix()}${key}`] = this._codex.encode(spanContext.baggage()[key]);
carrier[`${this._opts.baggageKeyPrefix()}${key}`] = this._codex.encode(spanContext.baggage[key]);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/span.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ export default class Span extends opentracing.Span {
}

protected _getBaggageItem(key: string): string | any {
return this._spanContext.baggage()[key];
return this._spanContext.baggage[key];
}

protected _context(): SpanContext {
Expand Down
48 changes: 16 additions & 32 deletions src/span_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,61 +18,45 @@ import Utils from './utils';
import * as opentracing from 'opentracing';

export default class SpanContext extends opentracing.SpanContext {
_traceId: string;
_spanId: string;
_parentSpanId: string;
_baggage: any;
traceId: string;
spanId: string;
parentSpanId: string;
baggage: any;

constructor(
traceId,
spanId,
parentSpanId,
baggage = {}) {
super();
this._traceId = traceId;
this._spanId = spanId;
this._parentSpanId = parentSpanId;
this._baggage = baggage;
}

traceId(): string {
return this._traceId;
}

spanId(): string {
return this._spanId;
}

parentSpanId(): string {
return this._parentSpanId;
}

baggage(): any {
return this._baggage;
this.traceId = traceId;
this.spanId = spanId;
this.parentSpanId = parentSpanId;
this.baggage = baggage;
}

setTraceId(traceId: string): void {
this._traceId = traceId;
this.traceId = traceId;
}

setSpanId(spanId: string): void {
this._spanId = spanId;
this.spanId = spanId;
}

setParentSpanId(parentSpanId: string): void {
this._parentSpanId = parentSpanId;
this.parentSpanId = parentSpanId;
}

addBaggageItem(key: string, value: any): SpanContext {
const newBaggage = Utils.assign(this._baggage, key, value);
const newBaggage = Utils.assign(this.baggage, key, value);
return new SpanContext(
this._traceId,
this._spanId,
this._parentSpanId,
this.traceId,
this.spanId,
this.parentSpanId,
newBaggage);
}

isValid(): boolean {
return !!(this._traceId && this._spanId);
return !!(this.traceId && this.spanId);
}
}
12 changes: 7 additions & 5 deletions src/tracer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import PropagationRegistry from './propagators/propagation_registry';
import TextMapPropagator from './propagators/textmap_propagator';
import URLCodex from './propagators/url_codex';
import StartSpanFields from './start_span_fields';
import BinaryPropagator from './propagators/binary_propagator';

export default class Tracer extends opentracing.Tracer {
_serviceName: string;
Expand All @@ -46,6 +47,7 @@ export default class Tracer extends opentracing.Tracer {
this._logger = logger;
this._registry = new PropagationRegistry();
this._registry.register(opentracing.FORMAT_TEXT_MAP, new TextMapPropagator());
this._registry.register(opentracing.FORMAT_BINARY, new BinaryPropagator());
this._registry.register(opentracing.FORMAT_HTTP_HEADERS, new TextMapPropagator(new URLCodex()));
}

Expand Down Expand Up @@ -98,13 +100,13 @@ export default class Tracer extends opentracing.Tracer {
static _createSpanContext(parent: SpanContext, callerContext: SpanContext): SpanContext {
if (!parent || !parent.isValid) {
if (callerContext) {
return new SpanContext(callerContext.traceId(), callerContext.spanId(), callerContext.parentSpanId(), callerContext.baggage());
return new SpanContext(callerContext.traceId, callerContext.spanId, callerContext.parentSpanId, callerContext.baggage);
} else {
const parentBaggage = parent && parent.baggage();
const parentBaggage = parent && parent.baggage;
return new SpanContext(Utils.randomUUID(), Utils.randomUUID(), parentBaggage);
}
} else {
return new SpanContext(parent.traceId(), Utils.randomUUID(), parent.spanId(), parent.baggage());
return new SpanContext(parent.traceId, Utils.randomUUID(), parent.spanId, parent.baggage);
}
}

Expand Down Expand Up @@ -142,7 +144,7 @@ export default class Tracer extends opentracing.Tracer {

const propagator = this._registry.propagator(format);
if (!propagator) {
throw new Error('injector for the given format is not supported');
throw new Error('injector is not supported for format=' + format);
}

propagator.inject(spanContext, carrier);
Expand All @@ -155,7 +157,7 @@ export default class Tracer extends opentracing.Tracer {

const propagator = this._registry.propagator(format);
if (!propagator) {
throw new Error('extractor for the given format is not supported');
throw new Error('extractor is not supported for format=' + format);
}

return propagator.extract(carrier);
Expand Down
28 changes: 28 additions & 0 deletions tests/api-compat.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2018 Expedia, Inc.
*
* 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.
*/

import Tracer from '../src/tracer';

describe('OpenTracing Api Compatibility Tests', () => {

describe('OpenTracing Api', () => {
it("should be compatible", () => {
const apiCompatibilityChecks = require('opentracing/lib/test/api_compatibility.js').default;
apiCompatibilityChecks(() => new Tracer('my-service'));
});
});
});

28 changes: 18 additions & 10 deletions tests/tracer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ const expectSpansInStore = (inMemSpanStore: InMemoryDispatcher, expectedCount: n
const versionTagValue = receivedSpan.tags()['version'];
expect(versionTagValue).eq('1.1');
expect(receivedSpan.serviceName()).eq(dummyServiceName);
expect(isUndefined(receivedSpan.context().traceId())).eq(false);
expect(isUndefined(receivedSpan.context().spanId())).eq(false);
expect(isUndefined(receivedSpan.context().traceId)).eq(false);
expect(isUndefined(receivedSpan.context().spanId)).eq(false);
});
};

Expand All @@ -62,7 +62,7 @@ describe('Tracer tests', () => {
expectSpansInStore(inMemSpanStore, 1);
const receivedSpan = inMemSpanStore.spans()[0];
expect(receivedSpan.operationName()).eq(dummyOperation);
expect(isUndefined(receivedSpan.context().parentSpanId())).eq(true);
expect(isUndefined(receivedSpan.context().parentSpanId)).eq(true);
});

it('should start and dispatch server and client spans', () => {
Expand All @@ -77,6 +77,9 @@ describe('Tracer tests', () => {
startClientSpanFields.childOf = serverSpan.context();
startClientSpanFields.tags = { 'span.kind': 'client' };
const clientSpan = tracer.startSpan(downstreamOperation, startClientSpanFields);
clientSpan.log({
eventCode: 100
});

expect(serverSpan.isFinished()).eq(false);
expect(inMemSpanStore.spans().length).equal(0);
Expand All @@ -85,16 +88,21 @@ describe('Tracer tests', () => {

expectSpansInStore(inMemSpanStore, 2);

expect(inMemSpanStore.spans().map(span => span.operationName())).includes(downstreamOperation);
expect(inMemSpanStore.spans().map(span => span.operationName())).includes(dummyOperation);

const receivedClientSpan = findSpan(inMemSpanStore, 'client');
const receivedServerSpan = findSpan(inMemSpanStore, 'server');

expect(receivedClientSpan.operationName()).eq(downstreamOperation);
expect(receivedServerSpan.operationName()).eq(dummyOperation);
expect(receivedClientSpan.duration() <= receivedServerSpan.duration()).eq(true);
expect(receivedClientSpan.context().parentSpanId()).eq(receivedServerSpan.context().spanId());
expect(isUndefined(receivedServerSpan.context().parentSpanId())).eq(true);
expect(receivedServerSpan.context().traceId()).eq(receivedClientSpan.context().traceId());
expect(receivedClientSpan.context().parentSpanId).eq(receivedServerSpan.context().spanId);
expect(isUndefined(receivedServerSpan.context().parentSpanId)).eq(true);
expect(receivedServerSpan.context().traceId).eq(receivedClientSpan.context().traceId);

expect(receivedClientSpan.logs().length).eq(1);
receivedClientSpan.logs().forEach(log => {
expect(log.keyValuePairs['eventCode']).eq(100);
expect(log.timestamp <= (Date.now() * 1000)).eq(true);
})
});

it('should inject the span in the carrier', () => {
Expand All @@ -111,7 +119,7 @@ describe('Tracer tests', () => {
const tracer = new Tracer(dummyServiceName, inMemSpanStore, commonTags);
const carrier = {'Trace-ID': 'a' , 'Span-ID': 'b', 'Parent-ID': 'c', 'Baggage-myKey': 'myVal'};
const spanContext = tracer.extract(opentracing.FORMAT_TEXT_MAP, carrier);
expect(JSON.stringify(spanContext)).eq('{"_traceId":"a","_spanId":"b","_parentSpanId":"c","_baggage":{"myKey":"myVal"}}');
expect(JSON.stringify(spanContext)).eq('{"traceId":"a","spanId":"b","parentSpanId":"c","baggage":{"myKey":"myVal"}}');
});
});
});

0 comments on commit d5c352c

Please sign in to comment.