From 7fe73e9bae74f98c270d5c629aa2add95b32ebff Mon Sep 17 00:00:00 2001 From: Peter Marton Date: Fri, 19 Jul 2019 14:00:18 -0700 Subject: [PATCH] fix(span): make child span clock relative to root span (#628) * fix(span): make child span clock relative to root span * test(span): improve comment * test(span): fix --- packages/opencensus-core/src/internal/clock.ts | 16 +++++++++++++--- packages/opencensus-core/src/trace/model/span.ts | 7 ++++++- packages/opencensus-core/test/test-span.ts | 8 ++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/packages/opencensus-core/src/internal/clock.ts b/packages/opencensus-core/src/internal/clock.ts index f73487b85..070ffca7c 100644 --- a/packages/opencensus-core/src/internal/clock.ts +++ b/packages/opencensus-core/src/internal/clock.ts @@ -27,9 +27,11 @@ export class Clock { /** The duration between start and end of the clock. */ private diff: [number, number] = [0, 0]; - /** Constructs a new SamplerImpl instance. */ - constructor() { - this.startTimeLocal = new Date(); + /** Constructs a new Clock instance. */ + constructor(startTime?: Date) { + // In some cases clocks need to be relative to other resources, passing a + // startTime makes it possible. + this.startTimeLocal = startTime || new Date(); this.hrtimeLocal = process.hrtime(); } @@ -42,6 +44,14 @@ export class Clock { this.endedLocal = true; } + /** Gets the current date from ellapsed milliseconds and start time. */ + get currentDate(): Date { + const diff = process.hrtime(this.hrtimeLocal); + const ns = diff[0] * 1e9 + diff[1]; + const ellapsed = ns / 1e6; + return new Date(this.startTime.getTime() + ellapsed); + } + /** Gets the duration of the clock. */ get duration(): number { if (!this.endedLocal) { diff --git a/packages/opencensus-core/src/trace/model/span.ts b/packages/opencensus-core/src/trace/model/span.ts index 4ee76dcc4..8423cd56a 100644 --- a/packages/opencensus-core/src/trace/model/span.ts +++ b/packages/opencensus-core/src/trace/model/span.ts @@ -316,7 +316,12 @@ export class Span implements types.Span { ); return; } - this.clock = new Clock(); + // start child span's clock from root's current time to preserve integrity. + if (this.parentSpan) { + this.clock = new Clock(this.parentSpan.clock.currentDate); + } else { + this.clock = new Clock(); + } this.startedLocal = true; this.logger.debug('starting %s %o', this.className, { traceId: this.traceId, diff --git a/packages/opencensus-core/test/test-span.ts b/packages/opencensus-core/test/test-span.ts index 74388c2f4..104307db7 100644 --- a/packages/opencensus-core/test/test-span.ts +++ b/packages/opencensus-core/test/test-span.ts @@ -47,6 +47,14 @@ describe('Span', () => { const span = new Span(tracer, rootSpan); assert.ok(span instanceof Span); }); + + it('should use relative clock for child spans', () => { + const rootSpan = new RootSpan(tracer, name, kind, traceId, parentSpanId); + rootSpan.start(); + const span = new Span(tracer, rootSpan); + span.start(); + assert.ok(rootSpan.startTime.getTime() <= span.startTime.getTime()); + }); }); /**