Skip to content
This repository has been archived by the owner on May 23, 2023. It is now read-only.

Commit

Permalink
Add mock tracer stub
Browse files Browse the repository at this point in the history
  • Loading branch information
bcronin committed Aug 23, 2016
1 parent 64f1fa0 commit 298fad7
Show file tree
Hide file tree
Showing 6 changed files with 232 additions and 5 deletions.
9 changes: 9 additions & 0 deletions src/mock_tracer/index.js
@@ -0,0 +1,9 @@
import MockTracer from './mock_tracer';
import MockSpan from './mock_span';
import MockContext from './mock_context';

export {
MockTracer,
MockSpan,
MockContext,
};
18 changes: 18 additions & 0 deletions src/mock_tracer/mock_context.js
@@ -0,0 +1,18 @@
import opentracing from '../..';

/**
* OpenTracing Context implementation designed for use in
* unit tests.
*/
export default class MockContext extends opentracing.Context {

//------------------------------------------------------------------------//
// MockContext-specific
//------------------------------------------------------------------------//

constructor(span) {
// Store a reference to the span itself since this is a mock tracer
// intended to make debugging and unit testing easier.
this._span = span;
}
}
45 changes: 45 additions & 0 deletions src/mock_tracer/mock_report.js
@@ -0,0 +1,45 @@
/* eslint-disable import/no-extraneous-dependencies */
import _ from 'underscore';

/**
* Index a collection of reported MockSpans in a way that's easy to run unit
* test assertions against.
*/
export default class MockReport {

constructor(spans) {
this.spans = spans;
this.spansByUUID = {};
this.spansByTag = {};
this.debugSpans = [];

this.unfinishedSpans = [];

_.each(spans, (span) => {
if (span._finishMs === 0) {
this.unfinishedSpans.push(span);
}

this.spansByUUID[span.uuid()] = span;
this.debugSpans.push(span.debug());

_.each(span._tags, (val, key) => {
this.spansByTag[key] = this.spansByTag[key] || {};
this.spansByTag[key][val] = this.spansByTag[key][val] || [];
this.spansByTag[key][val].push(span);
});
});
}

firstSpanWithTagValue(key, val) {
let m = this.spansByTag[key];
if (!m) {
return null;
}
let n = m[val];
if (!n) {
return null;
}
return n[0];
}
}
81 changes: 81 additions & 0 deletions src/mock_tracer/mock_span.js
@@ -0,0 +1,81 @@
/* eslint-disable import/no-extraneous-dependencies */

import opentracing from '../..';
import MockContext from './mock_context';
import _ from 'underscore';

/**
* OpenTracing Span implementation designed for use in unit tests.
*/
export default class MockSpan extends opentracing.Span {

//------------------------------------------------------------------------//
// OpenTracing implementation
//------------------------------------------------------------------------//

_context() {
return new MockContext(this);
}

_setOperationName(name) {
this._operationName = name;
}

_addTags(set) {
let keys = Object.keys(set);
for (let i = 0; i < keys.length; i++) {
let key = keys[i];
this._tags[key] = set[key];
}
}

_log(fields) {
this._logs.push(fields);
}

_finish(finishTime) {
this._finishMs = finishTime || Date.now();
}

//------------------------------------------------------------------------//
// MockSpan-specific
//------------------------------------------------------------------------//

constructor(tracer) {
this._tracer = tracer;
this._uuid = this._generateUUID();
this._startMs = Date.now();
this._finishMs = 0;
this._operationName = '';
this._tags = {};
this._logs = [];
}

uuid() {
return this._uuid;
}

_generateUUID() {
const p0 = `00000000${Math.abs((Math.random() * 0xFFFFFFFF) | 0).toString(16)}`.substr(-8);
const p1 = `00000000${Math.abs((Math.random() * 0xFFFFFFFF) | 0).toString(16)}`.substr(-8);
return `${p0}${p1}`;
}

addReference(ref) {
}

/**
* Returns a simplified object better for console.log()'ing.
*/
debug() {
let obj = {
uuid : this._uuid,
operation : this._operationName,
millis : [this._finishMs - this._startMs, this._startMs, this._finishMs],
};
if (_.size(this._tags)) {
obj.tags = this._tags;
}
return obj;
}
}
78 changes: 78 additions & 0 deletions src/mock_tracer/mock_tracer.js
@@ -0,0 +1,78 @@

// TODO: Move mock-tracer to its own NPM package once it is complete and tested.
import opentracing from '../..';

import MockSpan from './mock_span';
import MockReport from './mock_report';

/**
* OpenTracing Tracer implementation designed for use in unit tests.
*/
export default class MockTracer extends opentracing.Tracer {

//------------------------------------------------------------------------//
// OpenTracing implementation
//------------------------------------------------------------------------//

_startSpan(fields) {
// _allocSpan is given it's own method so that derived classes can
// allocate any type of object they want, but not have to duplicate
// the other common logic in startSpan().
const span = this._allocSpan(fields);

span.setOperationName(fields.operationName);
this._spans.push(span);

if (fields.references) {
for (let i = 0; i < fields.references; i++) {
span.addReference(fields.references[i]);
}
}

// Capture the stack at the time the span started
span._startStack = new Error().stack;
return span;
}

_inject(span, format, carrier) {
throw new Error('NOT YET IMPLEMENTED');
}

_extract(format, carrier) {
throw new Error('NOT YET IMPLEMENTED');
}

_flush(callback) {
this.clear();
if (callback) {
callback(null);
}
}

//------------------------------------------------------------------------//
// MockTracer-specific
//------------------------------------------------------------------------//

constructor() {
this._spans = [];
}

_allocSpan() {
return new MockSpan(this);
}

/**
* Discard any buffered data.
*/
clear() {
this._spans = [];
}

/**
* Return the buffered data in a format convenient for making unit test
* assertions.
*/
report() {
return new MockReport(this._spans);
}
}
6 changes: 1 addition & 5 deletions src/tracer.js
Expand Up @@ -134,8 +134,6 @@ export default class Tracer {
}
delete(fields.childOf);
}
spanImp = this._imp.startSpan(fields);
}

return this._startSpan(fields);
}
Expand Down Expand Up @@ -200,7 +198,6 @@ export default class Tracer {
* for a description of the carrier object.
*/
inject(spanContext, format, carrier) {

// Debug-only runtime checks on the arguments
if (process.env.NODE_ENV === 'debug') {
if (arguments.length !== 3) {
Expand Down Expand Up @@ -330,7 +327,7 @@ export default class Tracer {
// rather than the prior behavior of returning null. Otherwise the caller
// may need to add an if check in various places depending to handle the
// case where tracing is disabled / not initialized.
_extract(format, carrier)) {
_extract(format, carrier) {
return null;
}

Expand All @@ -341,5 +338,4 @@ export default class Tracer {
done(null);
}
}

}

0 comments on commit 298fad7

Please sign in to comment.