hawkly
Version:
An OpenTracing compatible tracer for hawkly.io
376 lines • 32.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const opentracing = require("opentracing");
const sinon = require("sinon");
const Tracer_1 = require("./Tracer");
const ava_1 = require("ava");
// This file contains tests for the public interface
ava_1.test('Check Tracer options are set correctly', (t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const accessToken = 'testAccessToken';
const componentName = 'testComponentname';
const recordCallback = sinon.spy();
const tracer = new Tracer_1.Tracer({
accessToken,
componentName,
recordCallback,
});
t.is(tracer.accessToken, accessToken, 'accessToken does not match');
t.is(tracer.componentName, componentName, 'componentName does not match');
t.is(tracer.recordCallback, recordCallback, 'recordCallback does not match');
// Call the recordCallback
tracer.recordCallback();
t.true(recordCallback.called);
}));
ava_1.test('Check Tracer throws when constructor options are not set correctly', (t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
// Check accessToken errors
const accessTokenUndefinedError = t.throws(() => {
const tracer = new Tracer_1.Tracer({
componentName: 'help',
});
tracer.clear();
});
t.is(accessTokenUndefinedError.message, 'You need to set your accessToken for the hawkly tracer');
const accessTokenNonStringError = t.throws(() => {
const tracer = new Tracer_1.Tracer({
accessToken: 234,
componentName: 'im',
});
tracer.clear();
});
t.is(accessTokenNonStringError.message, 'The accessToken must be a string');
// Check componentName errors
const componentNameUndefinedError = t.throws(() => {
const tracer = new Tracer_1.Tracer({
accessToken: 'trapped',
});
tracer.clear();
});
t.is(componentNameUndefinedError.message, 'You need to set a componentName to identify where these traces are coming from');
const componentNameNonStringError = t.throws(() => {
const tracer = new Tracer_1.Tracer({
accessToken: 'in',
componentName: 23423,
});
tracer.clear();
});
t.is(componentNameNonStringError.message, 'The componentName must be a string');
// Check recordCallback errors
const recordCallbackNonFunctionButDefinedError = t.throws(() => {
const tracer = new Tracer_1.Tracer({
accessToken: 'a',
componentName: 'testing',
recordCallback: 'factory',
});
tracer.clear();
});
t.is(recordCallbackNonFunctionButDefinedError.message, 'recordCallback must be a function');
}));
// Havent been able to get this to work
// test('should log error if the context is not a Span or Context', async (t: any) => {
// const tracer: Tracer = new Tracer({
// accessToken: 'test',
// componentName: 'test',
// recordCallback: () => {
// //
// },
// });
// const span: any = tracer.startSpan('test2', { childOf: undefined });
// span.finish();
// // t.is(tracer.internalEvents
// console.log(tracer.internalEvents);
// // t.true(tracer.internalEvents.find((event: any) => {
// // return event.msg === 'Span reference has an invalid context'
// // && event.payload === 'parent';
// // }));
// });
ava_1.test('supports childOf with a Span object', (t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const tracer = new Tracer_1.Tracer({
accessToken: 'test',
componentName: 'test',
recordCallback: () => {
//
},
});
const parent = tracer.startSpan('test1');
const span = tracer.startSpan('test2', { childOf: parent });
span.finish();
parent.finish();
t.true(span.context().traceId === parent.context().traceId, 'traceId does not match');
t.true(span.context().parentId === parent.context().spanId, 'parentId does not match');
t.true(parent.context().referenceType === 'root');
t.true(span.context().referenceType === 'childOf');
}));
ava_1.test('supports childOf with a SpanContext object', (t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const tracer = new Tracer_1.Tracer({
accessToken: 'test',
componentName: 'test',
recordCallback: () => {
//
},
});
const parent = tracer.startSpan('test1');
const span = tracer.startSpan('test2', { childOf: parent.context() });
span.finish();
parent.finish();
t.true(span.context().traceId === parent.context().traceId, 'traceId does not match');
t.true(span.context().parentId === parent.context().spanId, 'parentId does not match');
t.true(parent.context().referenceType === 'root');
t.true(span.context().referenceType === 'childOf');
}));
ava_1.test('supports followsFrom with a Span object', (t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const tracer = new Tracer_1.Tracer({
accessToken: 'test',
componentName: 'test',
recordCallback: () => {
//
},
});
const parent = tracer.startSpan('test1');
const span = tracer.startSpan('test2', { followsFrom: parent });
span.finish();
parent.finish();
t.true(span.context().traceId === parent.context().traceId, 'traceId does not match');
t.true(span.context().parentId === parent.context().spanId, 'parentId does not match');
t.true(parent.context().referenceType === 'root');
t.true(span.context().referenceType === 'followsFrom');
}));
ava_1.test('supports followsFrom with a SpanContext object', (t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const tracer = new Tracer_1.Tracer({
accessToken: 'test',
componentName: 'test',
recordCallback: () => {
//
},
});
const parent = tracer.startSpan('test1');
const parentContext = parent.context();
parent.finish();
const span = tracer.startSpan('test2', { followsFrom: parentContext });
span.finish();
t.true(span.context().traceId === parent.context().traceId, 'traceId does not match');
t.true(span.context().parentId === parent.context().spanId, 'parentId does not match');
t.true(parent.context().referenceType === 'root');
t.true(span.context().referenceType === 'followsFrom');
}));
ava_1.test('supports startTime', (t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const tracer = new Tracer_1.Tracer({
accessToken: 'test',
componentName: 'test',
recordCallback: () => {
//
},
});
const now = Date.now() - 5000;
const span = tracer.startSpan('test2', { startTime: now });
span.finish();
t.is(span._startMs, now, 'start time does not match what was supplied');
}));
ava_1.test('should throw when startTime is not a number', (t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const error = yield t.throws(() => {
const tracer = new Tracer_1.Tracer({
accessToken: 'test',
componentName: 'test',
recordCallback: () => {
//
},
});
const span = tracer.startSpan('test2', { startTime: 'now' });
span.finish();
});
t.is(error.message, 'startTime must be a timestamp of type number');
}));
ava_1.test('supports tags', (t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
yield t.notThrows(() => {
const tracer = new Tracer_1.Tracer({
accessToken: 'test',
componentName: 'test',
recordCallback: () => {
//
},
});
// Verify that we can add tags at startSpan time.
const span = tracer.startSpan('test', {
tags: {
tag_a: 1,
tag_b: 'b',
tag_c: true,
},
});
span.finish();
});
}));
ava_1.test('should throw when tags is not an object', (t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const error = yield t.throws(() => {
const tracer = new Tracer_1.Tracer({
accessToken: 'test',
componentName: 'test',
recordCallback: () => {
//
},
});
const span = tracer.startSpan('test', {
tags: 'tags',
});
span.finish();
});
t.is(error.message, 'tags must be an object');
}));
ava_1.test('should throw when tags is an Array', (t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const error = yield t.throws(() => {
const tracer = new Tracer_1.Tracer({
accessToken: 'test',
componentName: 'test',
recordCallback: () => {
//
},
});
const span = tracer.startSpan('test', {
tags: [],
});
span.finish();
});
t.is(error.message, 'tags must be an object');
}));
ava_1.test('should handle a large number of spans gracefully', (t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
yield t.notThrows(() => {
const tracer = new Tracer_1.Tracer({
accessToken: 'test',
componentName: 'test',
recordCallback: () => {
//
},
});
// Loop through a large number of span creations.
// This syntax may loop weird, but we're avoiding i++ and a for loop
[...Array(10000)].forEach(() => {
const span = tracer.startSpan('microspan');
span.finish();
});
});
}));
ava_1.test('should handle clearing spans', (t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const tracer = new Tracer_1.Tracer({
accessToken: 'test',
componentName: 'test',
recordCallback: () => {
//
},
});
[...Array(100)].forEach(() => {
const span = tracer.startSpan('microspan');
span.finish();
});
t.true(tracer._spans.length === 100);
tracer.clear();
t.true(tracer._spans.length === 0);
}));
ava_1.test('should handle passing in the opentracing module', (t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const tracer = new Tracer_1.Tracer({
accessToken: 'test',
componentName: 'test',
opentracingModule: opentracing,
recordCallback: () => {
//
},
});
// Verify that we can add tags at startSpan time.
const span = tracer.startSpan('test');
span.finish();
t.is(tracer.opentracing, opentracing);
}));
ava_1.test('should throw when the first arg of Span.log() is not an object', (t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const error = yield t.throws(() => {
const tracer = new Tracer_1.Tracer({
accessToken: 'test',
componentName: 'test',
recordCallback: () => {
//
},
});
const span = tracer.startSpan('test', {
tags: [],
});
span.finish();
});
t.is(error.message, 'tags must be an object');
}));
ava_1.test('should be able to inject Context into a TextMap', (t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const tracer = new Tracer_1.Tracer({
accessToken: 'test',
componentName: 'test',
recordCallback: () => {
//
},
});
const carrier = {};
const span = tracer.startSpan('test');
span.finish();
tracer.inject(span, 'text_map', carrier);
t.is(carrier['ot-tracer-spanId'], span.context().spanId);
t.is(carrier['ot-tracer-parentId'], span.context().parentId);
t.is(carrier['ot-tracer-traceId'], span.context().traceId);
t.is(carrier['ot-tracer-referenceType'], span.context().referenceType);
t.is(carrier['ot-tracer-sampled'], span.context().sampled);
}));
ava_1.test('should be able to extract a Context from a TextMap', (t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const tracer = new Tracer_1.Tracer({
accessToken: 'test',
componentName: 'test',
recordCallback: () => {
//
},
});
const carrier = {};
const span = tracer.startSpan('test');
span.finish();
tracer.inject(span, 'text_map', carrier);
t.is(carrier['ot-tracer-spanId'], span.context().spanId);
t.is(carrier['ot-tracer-parentId'], span.context().parentId);
t.is(carrier['ot-tracer-traceId'], span.context().traceId);
t.is(carrier['ot-tracer-referenceType'], span.context().referenceType);
t.is(carrier['ot-tracer-sampled'], span.context().sampled);
const extractedContext = tracer.extract('text_map', carrier);
t.is(extractedContext.spanId, span.context().spanId);
t.is(extractedContext.parentId, span.context().parentId);
t.is(extractedContext.traceId, span.context().traceId);
t.is(extractedContext.referenceType, span.context().referenceType);
t.is(extractedContext.sampled, span.context().sampled);
}));
ava_1.test('should be able to inject Context into a TextMap', (t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const tracer = new Tracer_1.Tracer({
accessToken: 'test',
componentName: 'test',
recordCallback: () => {
//
},
});
const carrier = {};
const span = tracer.startSpan('test');
span.finish();
tracer.inject(span, 'text_map', carrier);
t.is(carrier['ot-tracer-spanId'], span.context().spanId);
t.is(carrier['ot-tracer-parentId'], span.context().parentId);
t.is(carrier['ot-tracer-traceId'], span.context().traceId);
t.is(carrier['ot-tracer-referenceType'], span.context().referenceType);
t.is(carrier['ot-tracer-sampled'], span.context().sampled);
}));
ava_1.test('should be able to join to a carrier', (t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const tracer = new Tracer_1.Tracer({
accessToken: 'test',
componentName: 'test',
recordCallback: () => {
//
},
});
const carrier = {};
const span = tracer.startSpan('test');
span.finish();
tracer.inject(span, 'text_map', carrier);
const childSpan = tracer.join('childSpan', carrier, 'text_map');
childSpan.finish();
t.is(childSpan.context().parentId, span.context().spanId);
t.is(childSpan.context().traceId, span.context().traceId);
t.is(childSpan.context().referenceType, 'childOf');
}));
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVHJhY2VyLnNwZWMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdHJhY2VyL1RyYWNlci5zcGVjLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDJDQUEyQztBQUMzQywrQkFBK0I7QUFFL0IscUNBQWtDO0FBQ2xDLDZCQUEyQjtBQUUzQixvREFBb0Q7QUFFcEQsVUFBSSxDQUFDLHdDQUF3QyxFQUFFLENBQU8sQ0FBTTtJQUMxRCxNQUFNLFdBQVcsR0FBVyxpQkFBaUIsQ0FBQztJQUM5QyxNQUFNLGFBQWEsR0FBVyxtQkFBbUIsQ0FBQztJQUNsRCxNQUFNLGNBQWMsR0FBUSxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUM7SUFFeEMsTUFBTSxNQUFNLEdBQVEsSUFBSSxlQUFNLENBQUM7UUFDN0IsV0FBVztRQUNYLGFBQWE7UUFDYixjQUFjO0tBQ2YsQ0FBQyxDQUFDO0lBRUgsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUFFLFdBQVcsRUFBRSw0QkFBNEIsQ0FBQyxDQUFDO0lBQ3BFLENBQUMsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLGFBQWEsRUFBRSxhQUFhLEVBQUUsOEJBQThCLENBQUMsQ0FBQztJQUMxRSxDQUFDLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxjQUFjLEVBQUUsY0FBYyxFQUFFLCtCQUErQixDQUFDLENBQUM7SUFFN0UsMEJBQTBCO0lBQzFCLE1BQU0sQ0FBQyxjQUFjLEVBQUUsQ0FBQztJQUN4QixDQUFDLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUNoQyxDQUFDLENBQUEsQ0FBQyxDQUFDO0FBRUgsVUFBSSxDQUFDLG9FQUFvRSxFQUFFLENBQU8sQ0FBTTtJQUN0RiwyQkFBMkI7SUFDM0IsTUFBTSx5QkFBeUIsR0FBUSxDQUFDLENBQUMsTUFBTSxDQUFDO1FBQzlDLE1BQU0sTUFBTSxHQUFXLElBQUksZUFBTSxDQUFDO1lBQ2hDLGFB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QztJQUNILE1BQU0sT0FBTyxHQUFRLEVBQUUsQ0FBQztJQUN4QixNQUFNLElBQUksR0FBUSxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzNDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUNkLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUV6QyxNQUFNLFNBQVMsR0FBUSxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxPQUFPLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDckUsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBRW5CLENBQUMsQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDMUQsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMxRCxDQUFDLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxhQUFhLEVBQUUsU0FBUyxDQUFDLENBQUM7QUFDckQsQ0FBQyxDQUFBLENBQUMsQ0FBQyJ9