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

Commit 6b27a67

Browse files
authored
add tests, fix viewToMetricDescriptor, fix startTimestamp (#219)
1 parent 12f184a commit 6b27a67

File tree

6 files changed

+212
-81
lines changed

6 files changed

+212
-81
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,4 @@ jobs:
7777
command: npm install
7878
- run:
7979
name: Publish the module to npm.
80-
command: npm publish
80+
command: npm publish

packages/opencensus-core/src/stats/metric-utils.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,14 @@ export class MetricUtils {
6161
* @returns {MetricDescriptor}
6262
*/
6363
static viewToMetricDescriptor(view: View): MetricDescriptor {
64+
// TODO(mayurkale): add description
6465
return {
6566
name: view.name,
6667
description: view.description,
6768
unit: view.measure.unit,
6869
type: MetricUtils.getType(view.measure, view.aggregation),
69-
labelKeys: view.getColumns().map(tag => ({key: tag} as LabelKey))
70+
labelKeys: view.getColumns().map(
71+
tag => ({key: tag, description: ''} as LabelKey))
7072
};
7173
}
7274

packages/opencensus-core/src/stats/view.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,13 +202,18 @@ export class BaseView implements View {
202202
const {type} = this.metricDescriptor;
203203
let startTimestamp: Timestamp;
204204

205+
// The moment when this point was recorded.
206+
const [currentSeconds, currentNanos] = process.hrtime();
207+
const now: Timestamp = {seconds: currentSeconds, nanos: currentNanos};
208+
205209
switch (type) {
206210
case MetricDescriptorType.GAUGE_INT64:
207211
case MetricDescriptorType.GAUGE_DOUBLE:
208212
startTimestamp = null;
209213
break;
210214
default:
211215
const [seconds, nanos] = process.hrtime();
216+
// TODO (mayurkale): This should be set when create Cumulative view.
212217
startTimestamp = {seconds, nanos};
213218
}
214219

@@ -217,8 +222,13 @@ export class BaseView implements View {
217222
Object.keys(this.rows).forEach(key => {
218223
const {tags} = this.rows[key];
219224
const labelValues: LabelValue[] = MetricUtils.tagsToLabelValues(tags);
220-
const point: Point = this.toPoint(startTimestamp, this.getSnapshot(tags));
221-
timeseries.push({startTimestamp, labelValues, points: [point]});
225+
const point: Point = this.toPoint(now, this.getSnapshot(tags));
226+
227+
if (startTimestamp) {
228+
timeseries.push({startTimestamp, labelValues, points: [point]});
229+
} else {
230+
timeseries.push({labelValues, points: [point]});
231+
}
222232
});
223233

224234
return {descriptor: this.metricDescriptor, timeseries};

packages/opencensus-core/test/test-metric-producer.ts

Lines changed: 186 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -15,87 +15,202 @@
1515
*/
1616

1717
import * as assert from 'assert';
18-
19-
import {AggregationType, Measure, MeasureType, MeasureUnit, Stats, Tags, View} from '../src';
20-
import {MetricDescriptorType} from '../src/metrics/export/types';
18+
import {AggregationType, Measurement, MeasureUnit, Stats, Tags, View} from '../src';
19+
import {LabelKey, LabelValue, MetricDescriptorType, Timestamp} from '../src/metrics/export/types';
2120
import {MetricProducerForStats} from '../src/stats/metric-producer';
2221

2322
describe('Metric producer for stats', () => {
24-
interface AggregationTestCase {
25-
aggregationType: AggregationType;
26-
description: string;
27-
metricDescriptorType: MetricDescriptorType;
28-
}
29-
const aggregationTestCases: AggregationTestCase[] = [
30-
{
31-
aggregationType: AggregationType.SUM,
32-
description: 'Sum',
33-
metricDescriptorType: MetricDescriptorType.CUMULATIVE_DOUBLE
34-
},
35-
{
36-
aggregationType: AggregationType.COUNT,
37-
description: 'Count',
38-
metricDescriptorType: MetricDescriptorType.CUMULATIVE_INT64
39-
},
40-
{
41-
aggregationType: AggregationType.LAST_VALUE,
42-
description: 'Last Value',
43-
metricDescriptorType: MetricDescriptorType.GAUGE_DOUBLE
44-
},
45-
{
46-
aggregationType: AggregationType.DISTRIBUTION,
47-
description: 'Distribution',
48-
metricDescriptorType: MetricDescriptorType.CUMULATIVE_DISTRIBUTION
49-
}
23+
const {hrtime} = process;
24+
const mockedTime: Timestamp = {nanos: 1e7, seconds: 1000};
25+
26+
before(() => {
27+
process.hrtime = () => [1000, 1e7];
28+
});
29+
30+
after(() => {
31+
process.hrtime = hrtime;
32+
});
33+
34+
const stats = new Stats();
35+
const metricProducerForStats = new MetricProducerForStats(stats);
36+
37+
// constants for view name
38+
const viewName1 = 'test/view/name1';
39+
const viewName2 = 'test/view/name2';
40+
const viewName3 = 'test/view/name2';
41+
const description = 'test description';
42+
43+
const measureDouble = stats.createMeasureDouble(
44+
'opencensus.io/test/double', MeasureUnit.UNIT, 'Measure Double');
45+
const tags: Tags = {testKey1: 'testValue1', testKey2: 'testValue2'};
46+
const labelKeys: LabelKey[] = [
47+
{'key': 'testKey1', 'description': ''},
48+
{'key': 'testKey2', 'description': ''}
5049
];
51-
const measure: Measure = {
52-
name: 'Test Measure',
53-
type: MeasureType.DOUBLE,
54-
unit: MeasureUnit.UNIT
50+
const labelValues: LabelValue[] =
51+
[{'value': 'testValue1'}, {'value': 'testValue2'}];
52+
const measurement1: Measurement = {measure: measureDouble, value: 25, tags};
53+
const measurement2: Measurement = {measure: measureDouble, value: 300, tags};
54+
55+
// expected constants
56+
const expectedMetricDescriptor1 = {
57+
name: viewName1,
58+
description,
59+
labelKeys,
60+
unit: MeasureUnit.UNIT,
61+
type: MetricDescriptorType.CUMULATIVE_DOUBLE,
62+
};
63+
const expectedTimeSeries1 = [{
64+
labelValues,
65+
points: [{value: 25, timestamp: mockedTime}],
66+
startTimestamp: mockedTime
67+
}];
68+
const expectedMetricDescriptor2 = {
69+
name: viewName2,
70+
description,
71+
labelKeys,
72+
unit: MeasureUnit.UNIT,
73+
type: MetricDescriptorType.CUMULATIVE_INT64,
74+
};
75+
const expectedTimeSeries2 = [{
76+
labelValues,
77+
points: [{value: 1, timestamp: mockedTime}],
78+
startTimestamp: mockedTime
79+
}];
80+
const expectedMetricDescriptor3 = {
81+
name: viewName3,
82+
description,
83+
labelKeys,
84+
unit: MeasureUnit.UNIT,
85+
type: MetricDescriptorType.GAUGE_DOUBLE,
86+
};
87+
const expectedTimeSeries3 =
88+
[{labelValues, points: [{value: 300, timestamp: mockedTime}]}];
89+
const expectedMetricDescriptor4 = {
90+
name: viewName3,
91+
description,
92+
labelKeys,
93+
unit: MeasureUnit.UNIT,
94+
type: MetricDescriptorType.CUMULATIVE_DISTRIBUTION,
5595
};
96+
const expectedTimeSeries4 = [{
97+
labelValues,
98+
points: [{
99+
value: {
100+
'bucketOptions': {'explicit': {'bounds': [2, 4, 6]}},
101+
'buckets': [1, 2, 2, 0],
102+
'count': 5,
103+
'sum': 16.099999999999998,
104+
'sumOfSquaredDeviation': 10.427999999999997
105+
},
106+
timestamp: mockedTime
107+
}],
108+
startTimestamp: mockedTime
109+
}];
56110

57-
let stats: Stats;
58-
let metricProducerForStats: MetricProducerForStats;
111+
it('should add sum stats', () => {
112+
const view: View = stats.createView(
113+
viewName1, measureDouble, AggregationType.SUM, Object.keys(tags),
114+
description);
115+
view.recordMeasurement(measurement1);
59116

60-
beforeEach(() => {
61-
stats = new Stats();
62-
metricProducerForStats = new MetricProducerForStats(stats);
117+
const metrics = metricProducerForStats.getMetrics();
118+
119+
assert.strictEqual(metrics.length, 1);
120+
const [{
121+
descriptor: actualMetricDescriptor1,
122+
timeseries: actualTimeSeries1
123+
}] = metrics;
124+
assert.deepStrictEqual(actualMetricDescriptor1, expectedMetricDescriptor1);
125+
assert.strictEqual(actualTimeSeries1.length, 1);
126+
assert.deepStrictEqual(actualTimeSeries1, expectedTimeSeries1);
127+
});
128+
129+
it('should add count stats',
130+
() => {
131+
const view: View = stats.createView(
132+
viewName2, measureDouble, AggregationType.COUNT, Object.keys(tags),
133+
description);
134+
view.recordMeasurement(measurement1);
135+
136+
let metrics = metricProducerForStats.getMetrics();
137+
138+
assert.strictEqual(metrics.length, 2);
139+
const
140+
[{descriptor: actualMetricDescriptor1, timeseries: actualTimeSeries1},
141+
{descriptor: actualMetricDescriptor2, timeseries: actualTimeSeries2}] =
142+
metrics;
143+
assert.deepStrictEqual(
144+
actualMetricDescriptor1, expectedMetricDescriptor1);
145+
assert.strictEqual(actualTimeSeries1.length, 1);
146+
assert.deepStrictEqual(actualTimeSeries1, expectedTimeSeries1);
147+
assert.deepStrictEqual(
148+
actualMetricDescriptor2, expectedMetricDescriptor2);
149+
assert.strictEqual(actualTimeSeries2.length, 1);
150+
assert.deepStrictEqual(actualTimeSeries2, expectedTimeSeries2);
151+
152+
// update count view
153+
view.recordMeasurement(measurement2);
154+
metrics = metricProducerForStats.getMetrics();
155+
assert.deepStrictEqual(metrics[1].timeseries[0].points[0].value, 2);
156+
});
157+
158+
it('should add lastValue stats', () => {
159+
const view: View = stats.createView(
160+
viewName3, measureDouble, AggregationType.LAST_VALUE, Object.keys(tags),
161+
description);
162+
view.recordMeasurement(measurement1);
163+
view.recordMeasurement(measurement2);
164+
165+
const metrics = metricProducerForStats.getMetrics();
166+
167+
assert.strictEqual(metrics.length, 3);
168+
const
169+
[{descriptor: actualMetricDescriptor1, timeseries: actualTimeSeries1},
170+
{descriptor: actualMetricDescriptor2, timeseries: actualTimeSeries2},
171+
{descriptor: actualMetricDescriptor3, timeseries: actualTimeSeries3}] =
172+
metrics;
173+
assert.deepStrictEqual(actualMetricDescriptor1, expectedMetricDescriptor1);
174+
assert.strictEqual(actualTimeSeries1.length, 1);
175+
assert.deepStrictEqual(actualTimeSeries1, expectedTimeSeries1);
176+
assert.deepStrictEqual(actualMetricDescriptor2, expectedMetricDescriptor2);
177+
assert.strictEqual(actualTimeSeries2.length, 1);
178+
assert.deepStrictEqual(actualMetricDescriptor3, expectedMetricDescriptor3);
179+
assert.strictEqual(actualTimeSeries3.length, 1);
180+
assert.deepStrictEqual(actualTimeSeries3, expectedTimeSeries3);
63181
});
64182

65-
describe('Metric producer', () => {
66-
const tags: Tags = {testKey1: 'testValue', testKey2: 'testValue'};
183+
it('should add distribution stats', () => {
67184
const measurementValues = [1.1, 2.3, 3.2, 4.3, 5.2];
68185
const buckets = [2, 4, 6];
69186

70-
describe('getMetrics()', () => {
71-
// Detailed coverage in test-viev.ts
72-
for (const aggregation of aggregationTestCases) {
73-
it(`should return list of metrics for ${
74-
aggregation.aggregationType} aggregation`,
75-
() => {
76-
const view: View = stats.createView(
77-
'test/view/name', measure, aggregation.aggregationType,
78-
Object.keys(tags), 'test description', buckets);
79-
for (const value of measurementValues) {
80-
const measurement = {measure, tags, value};
81-
view.recordMeasurement(measurement);
82-
}
83-
84-
const metrics = metricProducerForStats.getMetrics();
85-
86-
assert.strictEqual(metrics.length, 1);
87-
const [{descriptor, timeseries}] = metrics;
88-
89-
assert.deepStrictEqual(descriptor, {
90-
name: 'test/view/name',
91-
description: 'test description',
92-
'labelKeys': [{'key': 'testKey1'}, {'key': 'testKey2'}],
93-
unit: MeasureUnit.UNIT,
94-
type: aggregation.metricDescriptorType,
95-
});
96-
assert.strictEqual(timeseries.length, 1);
97-
});
98-
}
99-
});
187+
const view: View = stats.createView(
188+
viewName3, measureDouble, AggregationType.DISTRIBUTION,
189+
Object.keys(tags), description, buckets);
190+
for (const value of measurementValues) {
191+
const measurement: Measurement = {measure: measureDouble, value, tags};
192+
view.recordMeasurement(measurement);
193+
}
194+
195+
const metrics = metricProducerForStats.getMetrics();
196+
197+
assert.strictEqual(metrics.length, 4);
198+
const
199+
[{descriptor: actualMetricDescriptor1, timeseries: actualTimeSeries1},
200+
{descriptor: actualMetricDescriptor2, timeseries: actualTimeSeries2},
201+
{descriptor: actualMetricDescriptor3, timeseries: actualTimeSeries3},
202+
{descriptor: actualMetricDescriptor4, timeseries: actualTimeSeries4}] =
203+
metrics;
204+
assert.deepStrictEqual(actualMetricDescriptor1, expectedMetricDescriptor1);
205+
assert.strictEqual(actualTimeSeries1.length, 1);
206+
assert.deepStrictEqual(actualTimeSeries1, expectedTimeSeries1);
207+
assert.deepStrictEqual(actualMetricDescriptor2, expectedMetricDescriptor2);
208+
assert.strictEqual(actualTimeSeries2.length, 1);
209+
assert.deepStrictEqual(actualMetricDescriptor3, expectedMetricDescriptor3);
210+
assert.strictEqual(actualTimeSeries3.length, 1);
211+
assert.deepStrictEqual(actualTimeSeries3, expectedTimeSeries3);
212+
assert.deepStrictEqual(actualMetricDescriptor4, expectedMetricDescriptor4);
213+
assert.strictEqual(actualTimeSeries4.length, 1);
214+
assert.deepStrictEqual(actualTimeSeries4, expectedTimeSeries4);
100215
});
101-
});
216+
});

packages/opencensus-core/test/test-metric-utils.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ describe('MetricUtil', () => {
4141
assert.strictEqual(
4242
metricDescriptor.type, MetricDescriptorType.GAUGE_DOUBLE);
4343
assert.strictEqual(metricDescriptor.description, VIEW_DESCRIPTION);
44-
assert.deepStrictEqual(
45-
metricDescriptor.labelKeys, [{key: 'testKey1'}, {key: 'testKey2'}]);
44+
assert.deepStrictEqual(metricDescriptor.labelKeys, [
45+
{key: 'testKey1', description: ''}, {key: 'testKey2', description: ''}
46+
]);
4647
});
4748

4849
it('should convert tag values to label values', () => {

packages/opencensus-core/test/test-view.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,10 @@ describe('BaseView', () => {
225225
assert.ok(descriptor);
226226
assert.deepStrictEqual(descriptor, {
227227
description: 'description test',
228-
labelKeys: [{key: 'testKey1'}, {key: 'testKey2'}],
228+
labelKeys: [
229+
{key: 'testKey1', description: ''},
230+
{key: 'testKey2', description: ''}
231+
],
229232
name: 'test/view/name',
230233
type: aggregationTestCase.metricDescriptorType,
231234
unit: '1',
@@ -237,13 +240,13 @@ describe('BaseView', () => {
237240
if (aggregationTestCase.metricDescriptorType ===
238241
MetricDescriptorType.GAUGE_INT64) {
239242
it('GAUGE_INT64 shouldnt has timeseries startTimestamp', () => {
240-
assert.strictEqual(startTimestamp, null);
243+
assert.strictEqual(startTimestamp, undefined);
241244
});
242245
} else if (
243246
aggregationTestCase.metricDescriptorType ===
244247
MetricDescriptorType.GAUGE_DOUBLE) {
245248
it('GAUGE_DOUBLE shouldnt has timeseries startTimestamp', () => {
246-
assert.strictEqual(startTimestamp, null);
249+
assert.strictEqual(startTimestamp, undefined);
247250
});
248251
} else {
249252
it('shouldnt has timeseries startTimestamp', () => {
@@ -363,7 +366,7 @@ describe('BaseView', () => {
363366
assert.ok(points);
364367
const [point] = points;
365368
const {timestamp, value} = point;
366-
assert.strictEqual(timestamp, null);
369+
assert.deepStrictEqual(timestamp, {nanos: 1e7, seconds: 1000});
367370
assert.equal(typeof value, 'number');
368371
assert.strictEqual(
369372
value, measurementValues[measurementValues.length - 1]);

0 commit comments

Comments
 (0)