diff --git a/packages/opencensus-core/src/common/time-util.ts b/packages/opencensus-core/src/common/time-util.ts new file mode 100644 index 000000000..21cb9594c --- /dev/null +++ b/packages/opencensus-core/src/common/time-util.ts @@ -0,0 +1,67 @@ +/** + * Copyright 2019, OpenCensus Authors + * + * 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 {Timestamp} from '../metrics/export/types'; + +const MILLIS_PER_SECOND = 1e3; +const NANOS_PER_MILLI = 1e3 * 1e3; +const NANOS_PER_SECOND = 1e3 * 1e3 * 1e3; + +let hrtime = process.hrtime; +let hrtimeOrigin: [number, number] = [0, 0]; +let hrtimeRefSeconds = 0; +let hrtimeRefNanos = 0; + +function setHrtimeReference() { + resetHrtimeFunctionCache(); + hrtimeOrigin = hrtime(); + const refTime = Date.now(); + hrtimeRefSeconds = Math.floor(refTime / MILLIS_PER_SECOND); + hrtimeRefNanos = (refTime % MILLIS_PER_SECOND) * NANOS_PER_MILLI; +} + +/** + * This is used to enable tests to mock process.hrtime while still allow us to + * cache it. + */ +function resetHrtimeFunctionCache() { + hrtime = process.hrtime; +} + +/** + * Gets the current timestamp with seconds and nanoseconds. + * + * @returns {Timestamp} The Timestamp. + */ +export function getTimestampWithProcessHRTime(): Timestamp { + const [offsetSecs, offsetNanos] = hrtime(hrtimeOrigin); + + // determine drift in seconds and nanoseconds + const seconds = hrtimeRefSeconds + offsetSecs; + const nanos = hrtimeRefNanos + offsetNanos; + + if (nanos >= NANOS_PER_SECOND) { + return {seconds: seconds + 1, nanos: nanos % NANOS_PER_SECOND}; + } + return {seconds, nanos}; +} + +setHrtimeReference(); + +export const TEST_ONLY = { + setHrtimeReference, + resetHrtimeFunctionCache +}; diff --git a/packages/opencensus-core/src/metrics/gauges/derived-gauge.ts b/packages/opencensus-core/src/metrics/gauges/derived-gauge.ts index bd98b03e9..ed270f9e0 100644 --- a/packages/opencensus-core/src/metrics/gauges/derived-gauge.ts +++ b/packages/opencensus-core/src/metrics/gauges/derived-gauge.ts @@ -14,8 +14,9 @@ * limitations under the License. */ +import {getTimestampWithProcessHRTime} from '../../common/time-util'; import {validateArrayElementsNotNull, validateNotNull} from '../../common/validations'; -import {LabelKey, LabelValue, Metric, MetricDescriptor, MetricDescriptorType, TimeSeries} from '../export/types'; +import {LabelKey, LabelValue, Metric, MetricDescriptor, MetricDescriptorType, TimeSeries, Timestamp} from '../export/types'; import * as types from '../gauges/types'; import {hashLabelValues} from '../utils'; @@ -204,16 +205,14 @@ export class DerivedGauge implements types.Meter { if (this.registeredPoints.size === 0) { return null; } - const [seconds, nanos] = process.hrtime(); + const timestamp: Timestamp = getTimestampWithProcessHRTime(); return { descriptor: this.metricDescriptor, timeseries: Array.from( this.registeredPoints, ([_, gaugeEntry]) => ({ labelValues: gaugeEntry.labelValues, - points: [ - {value: gaugeEntry.extractor(), timestamp: {seconds, nanos}} - ] + points: [{value: gaugeEntry.extractor(), timestamp}] } as TimeSeries)) }; } diff --git a/packages/opencensus-core/src/metrics/gauges/gauge.ts b/packages/opencensus-core/src/metrics/gauges/gauge.ts index 0c8794ea1..7a0131f9e 100644 --- a/packages/opencensus-core/src/metrics/gauges/gauge.ts +++ b/packages/opencensus-core/src/metrics/gauges/gauge.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import {getTimestampWithProcessHRTime} from '../../common/time-util'; import {validateArrayElementsNotNull, validateNotNull} from '../../common/validations'; import {LabelKey, LabelValue, Metric, MetricDescriptor, MetricDescriptorType, TimeSeries, Timestamp} from '../export/types'; import * as types from '../gauges/types'; @@ -129,12 +130,11 @@ export class Gauge implements types.Meter { if (this.registeredPoints.size === 0) { return null; } - const [seconds, nanos] = process.hrtime(); + const timestamp: Timestamp = getTimestampWithProcessHRTime(); return { descriptor: this.metricDescriptor, timeseries: Array.from( - this.registeredPoints, - ([_, point]) => point.getTimeSeries({seconds, nanos})) + this.registeredPoints, ([_, point]) => point.getTimeSeries(timestamp)) }; } } diff --git a/packages/opencensus-core/src/stats/view.ts b/packages/opencensus-core/src/stats/view.ts index 4720221e5..e1031561a 100644 --- a/packages/opencensus-core/src/stats/view.ts +++ b/packages/opencensus-core/src/stats/view.ts @@ -15,6 +15,7 @@ */ import * as defaultLogger from '../common/console-logger'; +import {getTimestampWithProcessHRTime} from '../common/time-util'; import * as loggerTypes from '../common/types'; import {DistributionValue, LabelValue, Metric, MetricDescriptor, MetricDescriptorType, Point, TimeSeries, Timestamp} from '../metrics/export/types'; @@ -206,8 +207,7 @@ export class BaseView implements View { let startTimestamp: Timestamp; // The moment when this point was recorded. - const [currentSeconds, currentNanos] = process.hrtime(); - const now: Timestamp = {seconds: currentSeconds, nanos: currentNanos}; + const now: Timestamp = getTimestampWithProcessHRTime(); switch (type) { case MetricDescriptorType.GAUGE_INT64: @@ -215,9 +215,8 @@ export class BaseView implements View { startTimestamp = null; break; default: - const [seconds, nanos] = process.hrtime(); // TODO (mayurkale): This should be set when create Cumulative view. - startTimestamp = {seconds, nanos}; + startTimestamp = getTimestampWithProcessHRTime(); } const timeseries: TimeSeries[] = []; diff --git a/packages/opencensus-core/test/test-derived-gauge.ts b/packages/opencensus-core/test/test-derived-gauge.ts index bffcf65d2..0f3e45cb4 100644 --- a/packages/opencensus-core/test/test-derived-gauge.ts +++ b/packages/opencensus-core/test/test-derived-gauge.ts @@ -15,7 +15,9 @@ */ import * as assert from 'assert'; -import {LabelKey, LabelValue, MetricDescriptorType} from '../src/metrics/export/types'; + +import {TEST_ONLY} from '../src/common/time-util'; +import {LabelKey, LabelValue, MetricDescriptorType, Timestamp} from '../src/metrics/export/types'; import {DerivedGauge} from '../src/metrics/gauges/derived-gauge'; const METRIC_NAME = 'metric-name'; @@ -29,8 +31,10 @@ const LABEL_VALUES_400: LabelValue[] = [{value: '400'}]; const LABEL_VALUES_EXRTA: LabelValue[] = [{value: '200'}, {value: '400'}]; describe('DerivedGauge', () => { - const oldProcessHrtime = process.hrtime; let instance: DerivedGauge; + const realHrtimeFn = process.hrtime; + const realNowFn = Date.now; + const mockedTime: Timestamp = {seconds: 1450000100, nanos: 1e7}; const expectedMetricDescriptor = { name: METRIC_NAME, description: METRIC_DESCRIPTION, @@ -42,11 +46,18 @@ describe('DerivedGauge', () => { beforeEach(() => { instance = new DerivedGauge( METRIC_NAME, METRIC_DESCRIPTION, UNIT, GAUGE_INT64, LABEL_KEYS); - process.hrtime = () => [1000, 1e7]; + + process.hrtime = () => [100, 1e7]; + Date.now = () => 1450000000000; + // Force the clock to recalibrate the time offset with the mocked time + TEST_ONLY.setHrtimeReference(); }); afterEach(() => { - process.hrtime = oldProcessHrtime; + process.hrtime = realHrtimeFn; + Date.now = realNowFn; + // Reset the hrtime reference so that it uses a real clock again. + TEST_ONLY.resetHrtimeFunctionCache(); }); describe('createTimeSeries()', () => { @@ -73,6 +84,7 @@ describe('DerivedGauge', () => { map.set('key', 'value'); instance.createTimeSeries(LABEL_VALUES_200, map); map.set('key1', 'value1'); + let metric = instance.getMetric(); assert.notEqual(metric, null); assert.deepStrictEqual(metric.descriptor, expectedMetricDescriptor); @@ -80,7 +92,11 @@ describe('DerivedGauge', () => { assert.deepStrictEqual( metric.timeseries, [{ labelValues: LABEL_VALUES_200, - points: [{value: 2, timestamp: {nanos: 1e7, seconds: 1000}}] + points: [{ + value: 2, + timestamp: + {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }] }]); // add data in collection map.set('key2', 'value2'); @@ -98,11 +114,19 @@ describe('DerivedGauge', () => { assert.deepStrictEqual(metric.timeseries, [ { labelValues: LABEL_VALUES_200, - points: [{value: 4, timestamp: {nanos: 1e7, seconds: 1000}}] + points: [{ + value: 4, + timestamp: + {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }] }, { labelValues: LABEL_VALUES_400, - points: [{value: 5, timestamp: {nanos: 1e7, seconds: 1000}}] + points: [{ + value: 5, + timestamp: + {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }] } ]); }); @@ -121,7 +145,11 @@ describe('DerivedGauge', () => { assert.deepStrictEqual( metric.timeseries, [{ labelValues: LABEL_VALUES_200, - points: [{value: 45, timestamp: {nanos: 1e7, seconds: 1000}}] + points: [{ + value: 45, + timestamp: + {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }] }]); }); it('should return a Metric (Double) - custom object', () => { @@ -147,7 +175,11 @@ describe('DerivedGauge', () => { assert.deepStrictEqual( metric.timeseries, [{ labelValues: LABEL_VALUES_200, - points: [{value: 0.7, timestamp: {nanos: 1e7, seconds: 1000}}] + points: [{ + value: 0.7, + timestamp: + {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }] }]); }); it('should throw an error when obj is null', () => { @@ -166,7 +198,11 @@ describe('DerivedGauge', () => { assert.deepStrictEqual( metric.timeseries, [{ labelValues: LABEL_VALUES_200, - points: [{value: 1, timestamp: {nanos: 1e7, seconds: 1000}}] + points: [{ + value: 1, + timestamp: + {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }] }]); // create timeseries with same labels. diff --git a/packages/opencensus-core/test/test-gauge.ts b/packages/opencensus-core/test/test-gauge.ts index 57faa5c2c..bfdecffb0 100644 --- a/packages/opencensus-core/test/test-gauge.ts +++ b/packages/opencensus-core/test/test-gauge.ts @@ -15,7 +15,9 @@ */ import * as assert from 'assert'; -import {LabelKey, LabelValue, MetricDescriptorType} from '../src/metrics/export/types'; + +import {TEST_ONLY} from '../src/common/time-util'; +import {LabelKey, LabelValue, MetricDescriptorType, Timestamp} from '../src/metrics/export/types'; import {Gauge} from '../src/metrics/gauges/gauge'; const METRIC_NAME = 'metric-name'; @@ -32,8 +34,10 @@ const UNSET_LABEL_VALUE: LabelValue = { }; describe('GAUGE_INT64', () => { - const oldProcessHrtime = process.hrtime; let instance: Gauge; + const realHrtimeFn = process.hrtime; + const realNowFn = Date.now; + const mockedTime: Timestamp = {seconds: 1450000100, nanos: 1e7}; const expectedMetricDescriptor = { name: METRIC_NAME, description: METRIC_DESCRIPTION, @@ -45,11 +49,18 @@ describe('GAUGE_INT64', () => { beforeEach(() => { instance = new Gauge( METRIC_NAME, METRIC_DESCRIPTION, UNIT, GAUGE_INT64, LABEL_KEYS); - process.hrtime = () => [1000, 1e7]; + + process.hrtime = () => [100, 1e7]; + Date.now = () => 1450000000000; + // Force the clock to recalibrate the time offset with the mocked time + TEST_ONLY.setHrtimeReference(); }); afterEach(() => { - process.hrtime = oldProcessHrtime; + process.hrtime = realHrtimeFn; + Date.now = realNowFn; + // Reset the hrtime reference so that it uses a real clock again. + TEST_ONLY.resetHrtimeFunctionCache(); }); describe('getOrCreateTimeSeries()', () => { @@ -74,6 +85,7 @@ describe('GAUGE_INT64', () => { it('should return a Metric', () => { const point = instance.getOrCreateTimeSeries(LABEL_VALUES_200); point.add(10); + let metric = instance.getMetric(); assert.notEqual(metric, null); assert.deepStrictEqual(metric.descriptor, expectedMetricDescriptor); @@ -81,8 +93,13 @@ describe('GAUGE_INT64', () => { assert.deepStrictEqual( metric.timeseries, [{ labelValues: LABEL_VALUES_200, - points: [{value: 10, timestamp: {nanos: 1e7, seconds: 1000}}] + points: [{ + value: 10, + timestamp: + {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }] }]); + // add value and create new timeseries. point.add(5); const point1 = instance.getOrCreateTimeSeries(LABEL_VALUES_400); @@ -93,11 +110,19 @@ describe('GAUGE_INT64', () => { assert.deepStrictEqual(metric.timeseries, [ { labelValues: LABEL_VALUES_200, - points: [{value: 15, timestamp: {nanos: 1e7, seconds: 1000}}] + points: [{ + value: 15, + timestamp: + {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }] }, { labelValues: LABEL_VALUES_400, - points: [{value: -8, timestamp: {nanos: 1e7, seconds: 1000}}] + points: [{ + value: -8, + timestamp: + {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }] } ]); }); @@ -111,7 +136,11 @@ describe('GAUGE_INT64', () => { assert.deepStrictEqual( metric.timeseries, [{ labelValues: LABEL_VALUES_200, - points: [{value: 10, timestamp: {nanos: 1e7, seconds: 1000}}] + points: [{ + value: 10, + timestamp: + {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }] }]); // create timeseries with same labels. const point1 = instance.getOrCreateTimeSeries(LABEL_VALUES_200); @@ -122,7 +151,11 @@ describe('GAUGE_INT64', () => { assert.deepStrictEqual( metric.timeseries, [{ labelValues: LABEL_VALUES_200, - points: [{value: 40, timestamp: {nanos: 1e7, seconds: 1000}}] + points: [{ + value: 40, + timestamp: + {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }] }]); }); }); @@ -137,7 +170,11 @@ describe('GAUGE_INT64', () => { assert.deepStrictEqual( metric.timeseries, [{ labelValues: [UNSET_LABEL_VALUE], - points: [{value: 10, timestamp: {nanos: 1e7, seconds: 1000}}] + points: [{ + value: 10, + timestamp: + {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }] }]); }); it('should return same timeseries for interchanged labels', () => { @@ -169,7 +206,11 @@ describe('GAUGE_INT64', () => { metric.timeseries, [{ labelValues: [UNSET_LABEL_VALUE, UNSET_LABEL_VALUE, UNSET_LABEL_VALUE], - points: [{value: 200, timestamp: {nanos: 1e7, seconds: 1000}}] + points: [{ + value: 200, + timestamp: + {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }] }]); }); it('should use previously created default timeseries', () => { @@ -182,7 +223,11 @@ describe('GAUGE_INT64', () => { assert.deepStrictEqual( metric.timeseries, [{ labelValues: [UNSET_LABEL_VALUE], - points: [{value: 300, timestamp: {nanos: 1e7, seconds: 1000}}] + points: [{ + value: 300, + timestamp: + {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }] }]); // get default timeseries again. const point1 = instance.getDefaultTimeSeries(); @@ -194,7 +239,11 @@ describe('GAUGE_INT64', () => { assert.deepStrictEqual( metric.timeseries, [{ labelValues: [UNSET_LABEL_VALUE], - points: [{value: 700, timestamp: {nanos: 1e7, seconds: 1000}}] + points: [{ + value: 700, + timestamp: + {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }] }]); }); }); @@ -233,8 +282,10 @@ describe('GAUGE_INT64', () => { }); describe('GAUGE_DOUBLE', () => { - const oldProcessHrtime = process.hrtime; let instance: Gauge; + const realHrtimeFn = process.hrtime; + const realNowFn = Date.now; + const mockedTime: Timestamp = {seconds: 1450000100, nanos: 1e7}; const expectedMetricDescriptor = { name: METRIC_NAME, description: METRIC_DESCRIPTION, @@ -246,11 +297,18 @@ describe('GAUGE_DOUBLE', () => { beforeEach(() => { instance = new Gauge( METRIC_NAME, METRIC_DESCRIPTION, UNIT, GAUGE_DOUBLE, LABEL_KEYS); - process.hrtime = () => [1000, 1e7]; + + process.hrtime = () => [100, 1e7]; + Date.now = () => 1450000000000; + // Force the clock to recalibrate the time offset with the mocked time + TEST_ONLY.setHrtimeReference(); }); afterEach(() => { - process.hrtime = oldProcessHrtime; + process.hrtime = realHrtimeFn; + Date.now = realNowFn; + // Reset the hrtime reference so that it uses a real clock again. + TEST_ONLY.resetHrtimeFunctionCache(); }); describe('getOrCreateTimeSeries()', () => { @@ -275,15 +333,20 @@ describe('GAUGE_DOUBLE', () => { it('should return a Metric', () => { const point = instance.getOrCreateTimeSeries(LABEL_VALUES_200); point.add(10.34); + let metric = instance.getMetric(); assert.notEqual(metric, null); assert.deepStrictEqual(metric.descriptor, expectedMetricDescriptor); assert.equal(metric.timeseries.length, 1); - assert.deepStrictEqual( - metric.timeseries, [{ - labelValues: LABEL_VALUES_200, - points: [{value: 10.34, timestamp: {nanos: 1e7, seconds: 1000}}], - }]); + assert.deepStrictEqual(metric.timeseries, [ + { + labelValues: LABEL_VALUES_200, + points: [{ + value: 10.34, + timestamp: {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }], + } + ]); // add value and create new timeseries. point.add(5.12); const point1 = instance.getOrCreateTimeSeries(LABEL_VALUES_400); @@ -293,11 +356,19 @@ describe('GAUGE_DOUBLE', () => { assert.deepStrictEqual(metric.timeseries, [ { labelValues: LABEL_VALUES_200, - points: [{value: 15.46, timestamp: {nanos: 1e7, seconds: 1000}}] + points: [{ + value: 15.46, + timestamp: + {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }] }, { labelValues: LABEL_VALUES_400, - points: [{value: -8.3, timestamp: {nanos: 1e7, seconds: 1000}}] + points: [{ + value: -8.3, + timestamp: + {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }] } ]); }); @@ -308,22 +379,30 @@ describe('GAUGE_DOUBLE', () => { assert.notEqual(metric, null); assert.deepStrictEqual(metric.descriptor, expectedMetricDescriptor); assert.equal(metric.timeseries.length, 1); - assert.deepStrictEqual( - metric.timeseries, [{ - labelValues: LABEL_VALUES_200, - points: [{value: 12.1, timestamp: {nanos: 1e7, seconds: 1000}}], - }]); + assert.deepStrictEqual(metric.timeseries, [ + { + labelValues: LABEL_VALUES_200, + points: [{ + value: 12.1, + timestamp: {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }], + } + ]); // create timeseries with same labels. const point1 = instance.getOrCreateTimeSeries(LABEL_VALUES_200); point1.add(30.18); metric = instance.getMetric(); assert.deepStrictEqual(metric.descriptor, expectedMetricDescriptor); assert.equal(metric.timeseries.length, 1); - assert.deepStrictEqual( - metric.timeseries, [{ - labelValues: LABEL_VALUES_200, - points: [{value: 42.28, timestamp: {nanos: 1e7, seconds: 1000}}], - }]); + assert.deepStrictEqual(metric.timeseries, [ + { + labelValues: LABEL_VALUES_200, + points: [{ + value: 42.28, + timestamp: {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }], + } + ]); }); }); describe('getDefaultTimeSeries()', () => { @@ -334,11 +413,15 @@ describe('GAUGE_DOUBLE', () => { assert.notEqual(metric, null); assert.deepStrictEqual(metric.descriptor, expectedMetricDescriptor); assert.equal(metric.timeseries.length, 1); - assert.deepStrictEqual( - metric.timeseries, [{ - labelValues: [UNSET_LABEL_VALUE], - points: [{value: 10.1, timestamp: {nanos: 1e7, seconds: 1000}}], - }]); + assert.deepStrictEqual(metric.timeseries, [ + { + labelValues: [UNSET_LABEL_VALUE], + points: [{ + value: 10.1, + timestamp: {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }], + } + ]); }); it('should use previously created default timeseries', () => { const point = instance.getDefaultTimeSeries(); @@ -347,11 +430,15 @@ describe('GAUGE_DOUBLE', () => { assert.notEqual(metric, null); assert.deepStrictEqual(metric.descriptor, expectedMetricDescriptor); assert.equal(metric.timeseries.length, 1); - assert.deepStrictEqual( - metric.timeseries, [{ - labelValues: [UNSET_LABEL_VALUE], - points: [{value: 300.1, timestamp: {nanos: 1e7, seconds: 1000}}], - }]); + assert.deepStrictEqual(metric.timeseries, [ + { + labelValues: [UNSET_LABEL_VALUE], + points: [{ + value: 300.1, + timestamp: {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }], + } + ]); // get default timeseries again. const point1 = instance.getDefaultTimeSeries(); point1.add(400.1); @@ -359,11 +446,15 @@ describe('GAUGE_DOUBLE', () => { assert.notEqual(metric, null); assert.deepStrictEqual(metric.descriptor, expectedMetricDescriptor); assert.equal(metric.timeseries.length, 1); - assert.deepStrictEqual( - metric.timeseries, [{ - labelValues: [UNSET_LABEL_VALUE], - points: [{value: 700.2, timestamp: {nanos: 1e7, seconds: 1000}}], - }]); + assert.deepStrictEqual(metric.timeseries, [ + { + labelValues: [UNSET_LABEL_VALUE], + points: [{ + value: 700.2, + timestamp: {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }], + } + ]); }); it('should create same labelValues as labelKeys', () => { instance = @@ -378,12 +469,16 @@ describe('GAUGE_DOUBLE', () => { assert.deepStrictEqual(metric.descriptor.labelKeys.length, 3); assert.deepStrictEqual(metric.descriptor.type, 2); assert.equal(metric.timeseries.length, 1); - assert.deepStrictEqual( - metric.timeseries, [{ - labelValues: - [UNSET_LABEL_VALUE, UNSET_LABEL_VALUE, UNSET_LABEL_VALUE], - points: [{value: 10.1, timestamp: {nanos: 1e7, seconds: 1000}}], - }]); + assert.deepStrictEqual(metric.timeseries, [ + { + labelValues: + [UNSET_LABEL_VALUE, UNSET_LABEL_VALUE, UNSET_LABEL_VALUE], + points: [{ + value: 10.1, + timestamp: {nanos: mockedTime.nanos, seconds: mockedTime.seconds} + }], + } + ]); }); }); describe('removeTimeSeries()', () => { diff --git a/packages/opencensus-core/test/test-metric-producer.ts b/packages/opencensus-core/test/test-metric-producer.ts index 0704e22ae..d5a354e35 100644 --- a/packages/opencensus-core/test/test-metric-producer.ts +++ b/packages/opencensus-core/test/test-metric-producer.ts @@ -16,21 +16,10 @@ import * as assert from 'assert'; import {AggregationType, Measurement, MeasureUnit, Stats, Tags, View} from '../src'; -import {LabelKey, LabelValue, MetricDescriptorType, Timestamp} from '../src/metrics/export/types'; +import {LabelKey, LabelValue, MetricDescriptorType} from '../src/metrics/export/types'; import {MetricProducerForStats} from '../src/stats/metric-producer'; describe('Metric producer for stats', () => { - const {hrtime} = process; - const mockedTime: Timestamp = {nanos: 1e7, seconds: 1000}; - - before(() => { - process.hrtime = () => [1000, 1e7]; - }); - - after(() => { - process.hrtime = hrtime; - }); - const stats = new Stats(); const metricProducerForStats = new MetricProducerForStats(stats); @@ -60,11 +49,6 @@ describe('Metric producer for stats', () => { unit: MeasureUnit.UNIT, type: MetricDescriptorType.CUMULATIVE_DOUBLE, }; - const expectedTimeSeries1 = [{ - labelValues, - points: [{value: 25, timestamp: mockedTime}], - startTimestamp: mockedTime - }]; const expectedMetricDescriptor2 = { name: viewName2, description, @@ -72,11 +56,6 @@ describe('Metric producer for stats', () => { unit: MeasureUnit.UNIT, type: MetricDescriptorType.CUMULATIVE_INT64, }; - const expectedTimeSeries2 = [{ - labelValues, - points: [{value: 1, timestamp: mockedTime}], - startTimestamp: mockedTime - }]; const expectedMetricDescriptor3 = { name: viewName3, description, @@ -84,8 +63,6 @@ describe('Metric producer for stats', () => { unit: MeasureUnit.UNIT, type: MetricDescriptorType.GAUGE_DOUBLE, }; - const expectedTimeSeries3 = - [{labelValues, points: [{value: 300, timestamp: mockedTime}]}]; const expectedMetricDescriptor4 = { name: viewName3, description, @@ -93,20 +70,6 @@ describe('Metric producer for stats', () => { unit: MeasureUnit.UNIT, type: MetricDescriptorType.CUMULATIVE_DISTRIBUTION, }; - const expectedTimeSeries4 = [{ - labelValues, - points: [{ - value: { - 'bucketOptions': {'explicit': {'bounds': [2, 4, 6]}}, - 'buckets': [{count: 1}, {count: 2}, {count: 2}, {count: 0}], - 'count': 5, - 'sum': 16.099999999999998, - 'sumOfSquaredDeviation': 10.427999999999997 - }, - timestamp: mockedTime - }], - startTimestamp: mockedTime - }]; it('should add sum stats', () => { const view: View = stats.createView( @@ -123,7 +86,8 @@ describe('Metric producer for stats', () => { }] = metrics; assert.deepStrictEqual(actualMetricDescriptor1, expectedMetricDescriptor1); assert.strictEqual(actualTimeSeries1.length, 1); - assert.deepStrictEqual(actualTimeSeries1, expectedTimeSeries1); + assert.deepStrictEqual(actualTimeSeries1[0].labelValues, labelValues); + assert.equal(actualTimeSeries1[0].points[0].value, 25); }); it('should add count stats', @@ -143,11 +107,13 @@ describe('Metric producer for stats', () => { assert.deepStrictEqual( actualMetricDescriptor1, expectedMetricDescriptor1); assert.strictEqual(actualTimeSeries1.length, 1); - assert.deepStrictEqual(actualTimeSeries1, expectedTimeSeries1); + assert.deepStrictEqual(actualTimeSeries1[0].labelValues, labelValues); + assert.equal(actualTimeSeries1[0].points[0].value, 25); assert.deepStrictEqual( actualMetricDescriptor2, expectedMetricDescriptor2); assert.strictEqual(actualTimeSeries2.length, 1); - assert.deepStrictEqual(actualTimeSeries2, expectedTimeSeries2); + assert.deepStrictEqual(actualTimeSeries2[0].labelValues, labelValues); + assert.equal(actualTimeSeries2[0].points[0].value, 1); // update count view view.recordMeasurement(measurement2); @@ -172,12 +138,15 @@ describe('Metric producer for stats', () => { metrics; assert.deepStrictEqual(actualMetricDescriptor1, expectedMetricDescriptor1); assert.strictEqual(actualTimeSeries1.length, 1); - assert.deepStrictEqual(actualTimeSeries1, expectedTimeSeries1); + assert.strictEqual(actualTimeSeries1.length, 1); + assert.deepStrictEqual(actualTimeSeries1[0].labelValues, labelValues); + assert.equal(actualTimeSeries1[0].points[0].value, 25); assert.deepStrictEqual(actualMetricDescriptor2, expectedMetricDescriptor2); assert.strictEqual(actualTimeSeries2.length, 1); assert.deepStrictEqual(actualMetricDescriptor3, expectedMetricDescriptor3); assert.strictEqual(actualTimeSeries3.length, 1); - assert.deepStrictEqual(actualTimeSeries3, expectedTimeSeries3); + assert.deepStrictEqual(actualTimeSeries3[0].labelValues, labelValues); + assert.equal(actualTimeSeries3[0].points[0].value, 300); }); it('should add distribution stats', () => { @@ -203,14 +172,23 @@ describe('Metric producer for stats', () => { metrics; assert.deepStrictEqual(actualMetricDescriptor1, expectedMetricDescriptor1); assert.strictEqual(actualTimeSeries1.length, 1); - assert.deepStrictEqual(actualTimeSeries1, expectedTimeSeries1); + assert.deepStrictEqual(actualTimeSeries1[0].labelValues, labelValues); + assert.equal(actualTimeSeries1[0].points[0].value, 25); assert.deepStrictEqual(actualMetricDescriptor2, expectedMetricDescriptor2); assert.strictEqual(actualTimeSeries2.length, 1); assert.deepStrictEqual(actualMetricDescriptor3, expectedMetricDescriptor3); assert.strictEqual(actualTimeSeries3.length, 1); - assert.deepStrictEqual(actualTimeSeries3, expectedTimeSeries3); + assert.deepStrictEqual(actualTimeSeries3[0].labelValues, labelValues); + assert.equal(actualTimeSeries3[0].points[0].value, 300); assert.deepStrictEqual(actualMetricDescriptor4, expectedMetricDescriptor4); assert.strictEqual(actualTimeSeries4.length, 1); - assert.deepStrictEqual(actualTimeSeries4, expectedTimeSeries4); + assert.deepStrictEqual(actualTimeSeries4[0].labelValues, labelValues); + assert.deepStrictEqual(actualTimeSeries4[0].points[0].value, { + 'bucketOptions': {'explicit': {'bounds': [2, 4, 6]}}, + 'buckets': [{count: 1}, {count: 2}, {count: 2}, {count: 0}], + 'count': 5, + 'sum': 16.099999999999998, + 'sumOfSquaredDeviation': 10.427999999999997 + }); }); }); diff --git a/packages/opencensus-core/test/test-metric-registry.ts b/packages/opencensus-core/test/test-metric-registry.ts index 8cf62757f..0e968bd9e 100644 --- a/packages/opencensus-core/test/test-metric-registry.ts +++ b/packages/opencensus-core/test/test-metric-registry.ts @@ -15,7 +15,8 @@ */ import * as assert from 'assert'; -import {LabelKey, LabelValue, MetricDescriptorType} from '../src/metrics/export/types'; +import {TEST_ONLY} from '../src/common/time-util'; +import {LabelKey, LabelValue, MetricDescriptorType, Timestamp} from '../src/metrics/export/types'; import {MetricRegistry} from '../src/metrics/metric-registry'; import {MeasureUnit} from '../src/stats/types'; @@ -27,18 +28,26 @@ const LABEL_KEYS_WITH_NULL: LabelKey[] = [{key: 'code', description: 'desc'}, null]; const LABEL_VALUES_200: LabelValue[] = [{value: '200'}]; const LABEL_VALUES_400: LabelValue[] = [{value: '400'}]; - describe('addInt64Gauge', () => { - const oldProcessHrtime = process.hrtime; let registry: MetricRegistry; + const realHrtimeFn = process.hrtime; + const realNowFn = Date.now; + const mockedTime: Timestamp = {seconds: 1450000100, nanos: 1e7}; beforeEach(() => { registry = new MetricRegistry(); - process.hrtime = () => [1000, 1e7]; + + process.hrtime = () => [100, 1e7]; + Date.now = () => 1450000000000; + // Force the clock to recalibrate the time offset with the mocked time + TEST_ONLY.setHrtimeReference(); }); afterEach(() => { - process.hrtime = oldProcessHrtime; + process.hrtime = realHrtimeFn; + Date.now = realNowFn; + // Reset the hrtime reference so that it uses a real clock again. + TEST_ONLY.resetHrtimeFunctionCache(); }); it('should throw an error when the name is null', () => { @@ -109,21 +118,32 @@ describe('addInt64Gauge', () => { const [{points}] = timeseries; const [point] = points; assert.equal(point.value, 100); - assert.deepStrictEqual(point.timestamp, {seconds: 1000, nanos: 1e7}); + assert.deepStrictEqual( + point.timestamp, + {seconds: mockedTime.seconds, nanos: mockedTime.nanos}); }); }); describe('addDoubleGauge', () => { - const oldProcessHrtime = process.hrtime; let registry: MetricRegistry; + const realHrtimeFn = process.hrtime; + const realNowFn = Date.now; + const mockedTime: Timestamp = {seconds: 1450000100, nanos: 1e7}; beforeEach(() => { registry = new MetricRegistry(); - process.hrtime = () => [1000, 1e7]; + + process.hrtime = () => [100, 1e7]; + Date.now = () => 1450000000000; + // Force the clock to recalibrate the time offset with the mocked time + TEST_ONLY.setHrtimeReference(); }); afterEach(() => { - process.hrtime = oldProcessHrtime; + process.hrtime = realHrtimeFn; + Date.now = realNowFn; + // Reset the hrtime reference so that it uses a real clock again. + TEST_ONLY.resetHrtimeFunctionCache(); }); it('should throw an error when the name is null', () => { @@ -197,7 +217,9 @@ describe('addDoubleGauge', () => { const [{points}] = timeseries; const [point] = points; assert.equal(point.value, 0.7); - assert.deepStrictEqual(point.timestamp, {seconds: 1000, nanos: 1e7}); + assert.deepStrictEqual( + point.timestamp, + {seconds: mockedTime.seconds, nanos: mockedTime.nanos}); }); it('should throw an error when the register same metric', () => { @@ -210,16 +232,25 @@ describe('addDoubleGauge', () => { }); describe('addDerivedInt64Gauge', () => { - const oldProcessHrtime = process.hrtime; let registry: MetricRegistry; + const realHrtimeFn = process.hrtime; + const realNowFn = Date.now; + const mockedTime: Timestamp = {seconds: 1450000100, nanos: 1e7}; beforeEach(() => { registry = new MetricRegistry(); - process.hrtime = () => [1000, 1e7]; + + process.hrtime = () => [100, 1e7]; + Date.now = () => 1450000000000; + // Force the clock to recalibrate the time offset with the mocked time + TEST_ONLY.setHrtimeReference(); }); afterEach(() => { - process.hrtime = oldProcessHrtime; + process.hrtime = realHrtimeFn; + Date.now = realNowFn; + // Reset the hrtime reference so that it uses a real clock again. + TEST_ONLY.resetHrtimeFunctionCache(); }); it('should throw an error when the name is null', () => { @@ -295,7 +326,9 @@ describe('addDerivedInt64Gauge', () => { const [{points}] = timeseries; const [point] = points; assert.equal(point.value, 2); - assert.deepStrictEqual(point.timestamp, {seconds: 1000, nanos: 1e7}); + assert.deepStrictEqual( + point.timestamp, + {seconds: mockedTime.seconds, nanos: mockedTime.nanos}); }); it('should throw an error when the register same metric', () => { @@ -309,16 +342,25 @@ describe('addDerivedInt64Gauge', () => { }); describe('addDerivedDoubleGauge', () => { - const oldProcessHrtime = process.hrtime; let registry: MetricRegistry; + const realHrtimeFn = process.hrtime; + const realNowFn = Date.now; + const mockedTime: Timestamp = {seconds: 1450000100, nanos: 1e7}; beforeEach(() => { registry = new MetricRegistry(); - process.hrtime = () => [1000, 1e7]; + + process.hrtime = () => [100, 1e7]; + Date.now = () => 1450000000000; + // Force the clock to recalibrate the time offset with the mocked time + TEST_ONLY.setHrtimeReference(); }); afterEach(() => { - process.hrtime = oldProcessHrtime; + process.hrtime = realHrtimeFn; + Date.now = realNowFn; + // Reset the hrtime reference so that it uses a real clock again. + TEST_ONLY.resetHrtimeFunctionCache(); }); it('should throw an error when the name is null', () => { @@ -397,7 +439,9 @@ describe('addDerivedDoubleGauge', () => { const [{points}] = timeseries; const [point] = points; assert.equal(point.value, 0.7); - assert.deepStrictEqual(point.timestamp, {seconds: 1000, nanos: 1e7}); + assert.deepStrictEqual( + point.timestamp, + {seconds: mockedTime.seconds, nanos: mockedTime.nanos}); }); it('should throw an error when the register same metric', () => { @@ -411,16 +455,25 @@ describe('addDerivedDoubleGauge', () => { }); describe('Add multiple gauges', () => { - const oldProcessHrtime = process.hrtime; let registry: MetricRegistry; + const realHrtimeFn = process.hrtime; + const realNowFn = Date.now; + const mockedTime: Timestamp = {seconds: 1450000100, nanos: 1e7}; - before(() => { + beforeEach(() => { registry = new MetricRegistry(); - process.hrtime = () => [1000, 1e7]; + + process.hrtime = () => [100, 1e7]; + Date.now = () => 1450000000000; + // Force the clock to recalibrate the time offset with the mocked time + TEST_ONLY.setHrtimeReference(); }); - after(() => { - process.hrtime = oldProcessHrtime; + afterEach(() => { + process.hrtime = realHrtimeFn; + Date.now = realNowFn; + // Reset the hrtime reference so that it uses a real clock again. + TEST_ONLY.resetHrtimeFunctionCache(); }); it('should return metrics', () => { @@ -466,11 +519,18 @@ describe('Add multiple gauges', () => { assert.strictEqual(timeseries1.length, 1); assert.strictEqual(timeseries1[0].points.length, 1); assert.equal(timeseries1[0].points[0].value, 100); + assert.equal( + timeseries1[0].points[0].timestamp.seconds, mockedTime.seconds); + assert.equal(timeseries1[0].points[0].timestamp.nanos, mockedTime.nanos); assert.strictEqual(timeseries2.length, 1); assert.strictEqual(timeseries2[0].points.length, 1); assert.equal(timeseries2[0].points[0].value, 5.5); assert.strictEqual(timeseries3.length, 1); assert.strictEqual(timeseries3[0].points.length, 1); assert.equal(timeseries3[0].points[0].value, 5); + assert.deepStrictEqual( + timeseries1[0].points[0].timestamp, timeseries2[0].points[0].timestamp); + assert.deepStrictEqual( + timeseries2[0].points[0].timestamp, timeseries3[0].points[0].timestamp); }); }); diff --git a/packages/opencensus-core/test/test-time-util.ts b/packages/opencensus-core/test/test-time-util.ts new file mode 100644 index 000000000..94f67351a --- /dev/null +++ b/packages/opencensus-core/test/test-time-util.ts @@ -0,0 +1,52 @@ +/** + * Copyright 2019, OpenCensus Authors + * + * 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 * as assert from 'assert'; +import {getTimestampWithProcessHRTime, TEST_ONLY} from '../src/common/time-util'; + +describe('getTimestampWithProcessHRTime()', () => { + const realHrtimeFn = process.hrtime; + const realNowFn = Date.now; + + afterEach(() => { + process.hrtime = realHrtimeFn; + Date.now = realNowFn; + // Reset the hrtime reference so that it uses a real clock again. + TEST_ONLY.resetHrtimeFunctionCache(); + }); + + it('should return timestamp with respect to now and process.hrtime', () => { + process.hrtime = () => [100, 1e7]; + Date.now = () => 1450000000000; + // Force the clock to recalibrate the time offset with the mocked time + TEST_ONLY.setHrtimeReference(); + + const currentTime = getTimestampWithProcessHRTime(); + + assert.deepStrictEqual(currentTime, {seconds: 1450000100, nanos: 1e7}); + }); + + it('should handle excess of nanos', () => { + process.hrtime = () => [100, 10000000012]; + Date.now = () => 1450000000000; + // Force the clock to recalibrate the time offset with the mocked time + TEST_ONLY.setHrtimeReference(); + + const currentTime = getTimestampWithProcessHRTime(); + + assert.deepStrictEqual(currentTime, {seconds: 1450000101, nanos: 12}); + }); +}); diff --git a/packages/opencensus-core/test/test-view.ts b/packages/opencensus-core/test/test-view.ts index f557f25b0..6638b5602 100644 --- a/packages/opencensus-core/test/test-view.ts +++ b/packages/opencensus-core/test/test-view.ts @@ -17,7 +17,8 @@ import * as assert from 'assert'; import {BaseView} from '../src'; -import {DistributionValue, MetricDescriptorType} from '../src/metrics/export/types'; +import {TEST_ONLY} from '../src/common/time-util'; +import {DistributionValue, MetricDescriptorType, Timestamp} from '../src/metrics/export/types'; import {AggregationType, DistributionData, Measure, Measurement, MeasureType, MeasureUnit, Tags, View} from '../src/stats/types'; /** The order of how close values must be to be considerated almost equal */ @@ -166,7 +167,7 @@ describe('BaseView', () => { 'test/view/name', measure, AggregationType.LAST_VALUE, ['testKey1', 'testKey2'], 'description test'); - it('should not record a measurement when it has wrong tag keys', () => { + it('should not record a measurement when it have wrong tag keys', () => { const measurement = {measure, tags: {testKey3: 'testValue'}, value: 10}; view.recordMeasurement(measurement); assert.ok(!view.getSnapshot(measurement.tags)); @@ -182,7 +183,7 @@ describe('BaseView', () => { assert.ok(!view.getSnapshot(measurement.tags)); }); - it('should not record a measurement when it has not enough tag keys', + it('should not record a measurement when it have not enough tag keys', () => { const measurement = { measure, @@ -195,17 +196,14 @@ describe('BaseView', () => { }); describe('getMetric()', () => { - const {hrtime} = process; - process.hrtime = () => [1000, 1e7]; + const realHrtimeFn = process.hrtime; + const realNowFn = Date.now; + const mockedTime: Timestamp = {seconds: 1450000100, nanos: 1e7}; const measurementValues = [1.1, 2.3, 3.2, 4.3, 5.2]; const buckets = [2, 4, 6]; const tags: Tags = {testKey1: 'testValue', testKey2: 'testValue'}; const tags1: Tags = {testKey1: 'testValue1', testKey2: 'testValue1'}; - after(() => { - process.hrtime = hrtime; - }); - for (const aggregationTestCase of aggregationTestCases) { const view: View = new BaseView( 'test/view/name', measure, aggregationTestCase.aggregationType, @@ -214,15 +212,26 @@ describe('BaseView', () => { const measurement = {measure, tags, value}; view.recordMeasurement(measurement); } - const {descriptor, timeseries} = view.getMetric(); - before(() => { - process.hrtime = () => [1000, 1e7]; + beforeEach(() => { + process.hrtime = () => [100, 1e7]; + Date.now = () => 1450000000000; + // Force the clock to recalibrate the time offset with the mocked time + TEST_ONLY.setHrtimeReference(); }); + afterEach(() => { + process.hrtime = realHrtimeFn; + Date.now = realNowFn; + // Reset the hrtime reference so that it uses a real clock again. + TEST_ONLY.resetHrtimeFunctionCache(); + }); + + const {descriptor, timeseries} = view.getMetric(); + describe( `Aggregation type: ${aggregationTestCase.aggregationType}`, () => { - it('should has descriptor', () => { + it('should have descriptor', () => { assert.ok(descriptor); assert.deepStrictEqual(descriptor, { description: 'description test', @@ -240,26 +249,26 @@ describe('BaseView', () => { if (aggregationTestCase.metricDescriptorType === MetricDescriptorType.GAUGE_INT64) { - it('GAUGE_INT64 shouldnt has timeseries startTimestamp', () => { + it('GAUGE_INT64 shouldnt have timeseries startTimestamp', () => { assert.strictEqual(startTimestamp, undefined); }); } else if ( aggregationTestCase.metricDescriptorType === MetricDescriptorType.GAUGE_DOUBLE) { - it('GAUGE_DOUBLE shouldnt has timeseries startTimestamp', () => { + it('GAUGE_DOUBLE shouldnt have timeseries startTimestamp', () => { assert.strictEqual(startTimestamp, undefined); }); } else { - it('shouldnt has timeseries startTimestamp', () => { + it('should have timeseries startTimestamp', () => { assert.ok(startTimestamp); assert.equal(typeof startTimestamp.nanos, 'number'); - assert.strictEqual(startTimestamp.nanos, 1e7); assert.equal(typeof startTimestamp.seconds, 'number'); - assert.strictEqual(startTimestamp.seconds, 1000); + assert.ok(startTimestamp.seconds > 0); + assert.ok(startTimestamp.nanos > 0); }); } - it('should has labelValues', () => { + it('should have labelValues', () => { assert.ok(labelValues); assert.deepStrictEqual( labelValues, [{value: 'testValue'}, {value: 'testValue'}]); @@ -286,9 +295,9 @@ describe('BaseView', () => { const {timestamp, value} = point; assert.ok(timestamp); assert.equal(typeof timestamp.nanos, 'number'); - assert.strictEqual(timestamp.nanos, 1e7); assert.equal(typeof timestamp.seconds, 'number'); - assert.strictEqual(timestamp.seconds, 1000); + assert.equal(timestamp.seconds, mockedTime.seconds); + assert.equal(timestamp.nanos, mockedTime.nanos); assert.notEqual(typeof value, 'number'); assert.deepStrictEqual((value as DistributionValue), { bucketOptions: {explicit: {bounds: buckets}}, @@ -328,9 +337,9 @@ describe('BaseView', () => { let {timestamp, value} = point; assert.ok(timestamp); assert.equal(typeof timestamp.nanos, 'number'); - assert.strictEqual(timestamp.nanos, 1e7); assert.equal(typeof timestamp.seconds, 'number'); - assert.strictEqual(timestamp.seconds, 1000); + assert.equal(timestamp.seconds, mockedTime.seconds); + assert.equal(timestamp.nanos, mockedTime.nanos); assert.notEqual(typeof value, 'number'); assert.deepStrictEqual((value as DistributionValue), { bucketOptions: {explicit: {bounds: buckets}}, @@ -347,9 +356,9 @@ describe('BaseView', () => { ({timestamp, value} = point); assert.ok(timestamp); assert.equal(typeof timestamp.nanos, 'number'); - assert.strictEqual(timestamp.nanos, 1e7); assert.equal(typeof timestamp.seconds, 'number'); - assert.strictEqual(timestamp.seconds, 1000); + assert.equal(timestamp.seconds, mockedTime.seconds); + assert.equal(timestamp.nanos, mockedTime.nanos); assert.notEqual(typeof value, 'number'); assert.deepStrictEqual((value as DistributionValue), { bucketOptions: {explicit: {bounds: buckets}}, @@ -381,9 +390,9 @@ describe('BaseView', () => { const {timestamp, value} = point; assert.ok(timestamp); assert.equal(typeof timestamp.nanos, 'number'); - assert.strictEqual(timestamp.nanos, 1e7); assert.equal(typeof timestamp.seconds, 'number'); - assert.strictEqual(timestamp.seconds, 1000); + assert.equal(timestamp.seconds, mockedTime.seconds); + assert.equal(timestamp.nanos, mockedTime.nanos); assert.equal(typeof value, 'number'); assert.strictEqual(value, 5); }); @@ -408,9 +417,9 @@ describe('BaseView', () => { const {timestamp, value} = point; assert.ok(timestamp); assert.equal(typeof timestamp.nanos, 'number'); - assert.strictEqual(timestamp.nanos, 1e7); assert.equal(typeof timestamp.seconds, 'number'); - assert.strictEqual(timestamp.seconds, 1000); + assert.equal(timestamp.seconds, mockedTime.seconds); + assert.equal(timestamp.nanos, mockedTime.nanos); assert.equal(typeof value, 'number'); assert.strictEqual(value, total); }); @@ -431,7 +440,8 @@ describe('BaseView', () => { assert.ok(points); const [point] = points; const {timestamp, value} = point; - assert.deepStrictEqual(timestamp, {nanos: 1e7, seconds: 1000}); + assert.equal(timestamp.seconds, mockedTime.seconds); + assert.equal(timestamp.nanos, mockedTime.nanos); assert.equal(typeof value, 'number'); assert.strictEqual( value, measurementValues[measurementValues.length - 1]);