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

Commit

Permalink
Consolidating Span and RootSpan to allow Spans to recursively have ch…
Browse files Browse the repository at this point in the history
…ildren. (#78)
  • Loading branch information
crdgonzalezca authored and draffensperger committed May 16, 2019
1 parent beb6d8e commit 64081eb
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 118 deletions.
6 changes: 3 additions & 3 deletions packages/opencensus-web-core/src/exporters/noop_exporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
import * as webTypes from '@opencensus/web-types';

export class NoopExporter implements webTypes.Exporter {
publish(roots: webTypes.RootSpan[]): Promise<number | string | void> {
publish(roots: webTypes.Span[]): Promise<number | string | void> {
return Promise.resolve();
}

onStartSpan(root: webTypes.RootSpan) {}
onStartSpan(root: webTypes.Span) {}

onEndSpan(root: webTypes.RootSpan) {}
onEndSpan(root: webTypes.Span) {}
}
43 changes: 1 addition & 42 deletions packages/opencensus-web-core/src/trace/model/root-span.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,7 @@ import { randomTraceId } from '../../common/id-util';
import { Span } from './span';

/** Simple mock root span for use in use tests. */
export class RootSpan extends Span implements webTypes.RootSpan {
/** A list of child spans. */
spans: Span[] = [];

/** A number of children. */
private numberOfChildrenLocal: number;

export class RootSpan extends Span {
constructor(
/** Trace associated with this root span. */
private readonly tracer: webTypes.Tracer,
Expand All @@ -47,41 +41,6 @@ export class RootSpan extends Span implements webTypes.RootSpan {
} else {
this.traceId = randomTraceId();
}

this.numberOfChildrenLocal = 0;
}

/** Gets the number of child span created for this span. */
get numberOfChildren(): number {
return this.numberOfChildrenLocal;
}

/**
* Starts a new child span in the root span.
* @param nameOrOptions Span name string or SpanOptions object.
* @param kind Span kind if not using options object.
* @param parentSpanId Span parent ID.
*/
startChildSpan(
nameOrOptions?: string | webTypes.SpanOptions,
kind?: webTypes.SpanKind
): Span {
this.numberOfChildrenLocal++;
const child = new Span();
child.traceId = this.traceId;
child.traceState = this.traceState;

const spanName =
typeof nameOrOptions === 'object' ? nameOrOptions.name : nameOrOptions;
const spanKind =
typeof nameOrOptions === 'object' ? nameOrOptions.kind : kind;
if (spanName) child.name = spanName;
if (spanKind) child.kind = spanKind;

child.start();
child.parentSpanId = this.id;
this.spans.push(child);
return child;
}

start() {
Expand Down
53 changes: 52 additions & 1 deletion packages/opencensus-web-core/src/trace/model/span.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ export class Span implements webTypes.Span {
constructor(
/** The ID of this span. Defaults to a random span ID. */
public id = randomSpanId()
) {}
) {
this.numberOfChildrenLocal = 0;
}

/** If the parent span is in another process. */
remoteParent = false;
Expand Down Expand Up @@ -77,6 +79,12 @@ export class Span implements webTypes.Span {
/** Start time of the span as measured by the browser performance clock. */
startPerfTime = 0;

/** A list of child spans. */
spans: Span[] = [];

/** A number of children. */
private numberOfChildrenLocal: number;

/**
* Number of dropped attributes. This is always zero because OpenCensus web
* does not implement attribute dropping (but may be done by agent on export).
Expand Down Expand Up @@ -113,6 +121,11 @@ export class Span implements webTypes.Span {
/** End time of the span as measured by the browser performance clock. */
endPerfTime = 0;

/** Gets the number of child span created for this span. */
get numberOfChildren(): number {
return this.numberOfChildrenLocal;
}

/** End time of the span as a Date. */
get endTime(): Date {
return getDateForPerfTime(this.endPerfTime);
Expand All @@ -138,6 +151,44 @@ export class Span implements webTypes.Span {
};
}

/** Recursively gets the descendant spans. */
allDescendants(): webTypes.Span[] {
return this.spans.reduce((acc: webTypes.Span[], cur) => {
acc.push(cur);
const desc = cur.allDescendants();
acc = acc.concat(desc);
return acc;
}, []);
}

/**
* Starts a new child span.
* @param nameOrOptions Span name string or SpanOptions object.
* @param kind Span kind if not using options object.
* @param parentSpanId Span parent ID.
*/
startChildSpan(
nameOrOptions?: string | webTypes.SpanOptions,
kind?: webTypes.SpanKind
): Span {
this.numberOfChildrenLocal++;
const child = new Span();
child.traceId = this.traceId;
child.traceState = this.traceState;

const spanName =
typeof nameOrOptions === 'object' ? nameOrOptions.name : nameOrOptions;
const spanKind =
typeof nameOrOptions === 'object' ? nameOrOptions.kind : kind;
if (spanName) child.name = spanName;
if (spanKind) child.kind = spanKind;

child.start();
child.parentSpanId = this.id;
this.spans.push(child);
return child;
}

/**
* Adds an attribute to the span.
* @param key Describes the value added.
Expand Down
11 changes: 4 additions & 7 deletions packages/opencensus-web-core/src/trace/model/tracer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const NO_HEADERS_PROPAGATION = new NoHeadersPropagation();
/** Tracer manages the current root span and trace header propagation. */
export class Tracer implements webTypes.Tracer {
/** Get and set the currentRootSpan of the tracer. */
currentRootSpan: RootSpan = new RootSpan(this);
currentRootSpan: Span = new RootSpan(this);

/**
* A sampler used to make trace sample decisions. In the case of
Expand Down Expand Up @@ -80,24 +80,21 @@ export class Tracer implements webTypes.Tracer {
* @param fn Callback function
* @returns The callback return
*/
startRootSpan<T>(
options: webTypes.TraceOptions,
fn: (root: RootSpan) => T
): T {
startRootSpan<T>(options: webTypes.TraceOptions, fn: (root: Span) => T): T {
this.currentRootSpan = new RootSpan(this, options);
this.currentRootSpan.start();
return fn(this.currentRootSpan);
}

/** Notifies listeners of the span start. */
onStartSpan(root: webTypes.RootSpan) {
onStartSpan(root: webTypes.Span) {
for (const listener of this.eventListeners) {
listener.onStartSpan(root);
}
}

/** Notifies listeners of the span end. */
onEndSpan(root: webTypes.RootSpan) {
onEndSpan(root: webTypes.Span) {
for (const listener of this.eventListeners) {
listener.onEndSpan(root);
}
Expand Down
70 changes: 27 additions & 43 deletions packages/opencensus-web-core/test/test-root-span.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import { SpanKind, SpanOptions } from '@opencensus/web-types';
import { SpanKind } from '@opencensus/web-types';
import { RootSpan } from '../src/trace/model/root-span';
import { Tracer } from '../src/trace/model/tracer';

Expand Down Expand Up @@ -51,40 +51,6 @@ describe('RootSpan', () => {
});
});

describe('startChildSpan', () => {
it('appends to spans list based on root id and state', () => {
root.traceId = '00000000000000000000000000000001';
root.traceState = 'a=b';

const childSpan = root.startChildSpan('child1', SpanKind.CLIENT);

expect(childSpan.traceId).toBe('00000000000000000000000000000001');
expect(childSpan.traceState).toBe('a=b');
expect(childSpan.name).toBe('child1');
expect(childSpan.kind).toBe(SpanKind.CLIENT);
expect(childSpan.parentSpanId).toBe(root.id);
expect(root.spans).toEqual([childSpan]);
});

it('allows specifying SpanOptions object with name and kind', () => {
root.traceId = '00000000000000000000000000000001';
root.traceState = 'a=b';

const spanOptions: SpanOptions = {
name: 'child1',
kind: SpanKind.CLIENT,
};
const childSpan = root.startChildSpan(spanOptions);

expect(childSpan.traceId).toBe('00000000000000000000000000000001');
expect(childSpan.traceState).toBe('a=b');
expect(childSpan.name).toBe('child1');
expect(childSpan.kind).toBe(SpanKind.CLIENT);
expect(childSpan.parentSpanId).toBe(root.id);
expect(root.spans).toEqual([childSpan]);
});
});

describe('start', () => {
it('sets start time and calls onStartSpan for tracer', () => {
spyOn(tracer, 'onStartSpan');
Expand Down Expand Up @@ -121,18 +87,36 @@ describe('RootSpan', () => {
});
});

describe('get numberOfChildren()', () => {
it('should get numberOfChildren from rootspan instance', () => {
root = new RootSpan(tracer);
describe('nested spans', () => {
it('should get nested spans from rootspan instance', () => {
root.start();
expect(root.numberOfChildren).toBe(0);
root.startChildSpan('spanName', SpanKind.UNSPECIFIED);
const child1 = root.startChildSpan('child1', SpanKind.UNSPECIFIED);
expect(root.numberOfChildren).toBe(1);
expect(child1.numberOfChildren).toBe(0);
const child2 = root.startChildSpan('child2', SpanKind.UNSPECIFIED);
expect(root.numberOfChildren).toBe(2);
const grandchild1 = child1.startChildSpan({
name: 'grandchild1',
kind: SpanKind.UNSPECIFIED,
});
expect(root.numberOfChildren).toBe(2);
expect(child1.numberOfChildren).toBe(1);
expect(child2.numberOfChildren).toBe(0);
expect(grandchild1.numberOfChildren).toBe(0);

expect(child1).toBe(root.spans[0]);
expect(child2).toBe(root.spans[1]);
expect(grandchild1.parentSpanId).toBe(child1.id);

expect(child1.spans.length).toBe(1);
expect(grandchild1).toBe(child1.spans[0]);

expect(child2.spans.length).toBe(0);
expect(child2.spans.length).toBe(0);
expect(grandchild1.spans.length).toBe(0);

for (let i = 0; i < 10; i++) {
root.startChildSpan('spanName' + i, SpanKind.UNSPECIFIED);
}
expect(root.numberOfChildren).toBe(11);
expect(root.allDescendants().length).toBe(3);
});
});
});
55 changes: 54 additions & 1 deletion packages/opencensus-web-core/test/test-span.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@
* limitations under the License.
*/

import { LinkType, MessageEventType } from '@opencensus/web-types';
import {
LinkType,
MessageEventType,
SpanKind,
SpanOptions,
} from '@opencensus/web-types';
import { Span } from '../src/trace/model/span';
import { mockGetterOrValue, restoreGetterOrValue } from './util';

Expand Down Expand Up @@ -181,4 +186,52 @@ describe('Span', () => {
]);
});
});

describe('get numberOfChildren()', () => {
it('should get numberOfChildren from span instance', () => {
span.start();
expect(span.numberOfChildren).toBe(0);
span.startChildSpan('spanName', SpanKind.UNSPECIFIED);
expect(span.numberOfChildren).toBe(1);

for (let i = 0; i < 10; i++) {
span.startChildSpan('spanName' + i, SpanKind.UNSPECIFIED);
}
expect(span.numberOfChildren).toBe(11);
});
});

describe('startChildSpan', () => {
it('appends to spans list based on root id and state', () => {
span.traceId = '00000000000000000000000000000001';
span.traceState = 'a=b';

const childSpan = span.startChildSpan('child1', SpanKind.CLIENT);

expect(childSpan.traceId).toBe('00000000000000000000000000000001');
expect(childSpan.traceState).toBe('a=b');
expect(childSpan.name).toBe('child1');
expect(childSpan.kind).toBe(SpanKind.CLIENT);
expect(childSpan.parentSpanId).toBe(span.id);
expect(span.spans).toEqual([childSpan]);
});

it('allows specifying SpanOptions object with name and kind', () => {
span.traceId = '00000000000000000000000000000001';
span.traceState = 'a=b';

const spanOptions: SpanOptions = {
name: 'child1',
kind: SpanKind.CLIENT,
};
const childSpan = span.startChildSpan(spanOptions);

expect(childSpan.traceId).toBe('00000000000000000000000000000001');
expect(childSpan.traceState).toBe('a=b');
expect(childSpan.name).toBe('child1');
expect(childSpan.kind).toBe(SpanKind.CLIENT);
expect(childSpan.parentSpanId).toBe(span.id);
expect(span.spans).toEqual([childSpan]);
});
});
});
2 changes: 1 addition & 1 deletion packages/opencensus-web-types/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"scripts": {
"build": "npm run compile",
"clean": "rimraf build/*",
"copytypes": "node scripts/copy-types.js 'v0.0.11' && npm run fix",
"copytypes": "node scripts/copy-types.js 'abd41dbc0f2f5836980ae9d79048a81d58a9956f' && npm run fix",
"check": "gts check",
"compile": "tsc -p .",
"fix": "gts fix",
Expand Down
2 changes: 1 addition & 1 deletion packages/opencensus-web-types/src/exporters/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export interface Exporter extends modelTypes.SpanEventListener {
* Sends a list of root spans to the service.
* @param rootSpans A list of root spans to publish.
*/
publish(rootSpans: modelTypes.RootSpan[]): Promise<number | string | void>;
publish(rootSpans: modelTypes.Span[]): Promise<number | string | void>;
}

/**
Expand Down

0 comments on commit 64081eb

Please sign in to comment.