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

Commit a03a33b

Browse files
authored
Adds [MetricProducer], convertors to [DistributionValue] [Point] (#211)
* Adds [MetricProducer], convertors to [DistributionValue] [Point] * Adds abstract class for [MetricProducer]
1 parent 4116982 commit a03a33b

File tree

10 files changed

+462
-9
lines changed

10 files changed

+462
-9
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Copyright 2018, OpenCensus Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 the "License";
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {Metric} from './types';
18+
19+
/**
20+
* A MetricProducer producer that can be registered for exporting using
21+
* MetricProducerManager.
22+
*/
23+
export abstract class MetricProducer {
24+
/**
25+
* Gets a collection of produced Metric`s to be exported.
26+
* @returns {Metric[]} List of metrics
27+
*/
28+
abstract getMetrics(): Metric[];
29+
}

packages/opencensus-core/src/metrics/export/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,8 @@ export interface SummaryValue {
274274
*/
275275
readonly sum: number;
276276
/** Values calculated over an arbitrary time window. */
277-
readonly snapshot: Snapshot;
277+
// TODO: Change it to required when Exemplar functionality will be added.
278+
readonly snapshot?: Snapshot;
278279
}
279280

280281
/**
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* Copyright 2018, OpenCensus Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {MetricProducer} from '../metrics/export/metric-producer';
18+
import {Metric} from '../metrics/export/types';
19+
20+
import {Stats} from './stats';
21+
22+
/**
23+
* A MetricProducer producer that can be registered for exporting using
24+
* MetricProducerManager.
25+
*/
26+
export class MetricProducerForStats extends MetricProducer {
27+
private statsManager: Stats;
28+
29+
/**
30+
* @param statsManager The stats
31+
*/
32+
constructor(statsManager: Stats) {
33+
super();
34+
this.statsManager = statsManager;
35+
}
36+
37+
/**
38+
* Gets a collection of produced Metric`s to be exported.
39+
* @returns {Metric[]} List of metrics
40+
*/
41+
getMetrics(): Metric[] {
42+
return this.statsManager.getMetrics();
43+
}
44+
}

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export class MetricUtils {
2525
* Gets the corresponding metric type for the given stats type.
2626
* @param measure The measure for which to find a metric type
2727
* @param aggregation The aggregation for which to find a metric type
28+
* @returns {MetricDescriptorType} Type of metric descriptor
2829
*/
2930
private static getType(measure: Measure, aggregation: AggregationType):
3031
MetricDescriptorType {
@@ -57,6 +58,7 @@ export class MetricUtils {
5758
/**
5859
* Gets a MetricDescriptor for given view.
5960
* @param view The view for which to build a metric descriptor
61+
* @returns {MetricDescriptor}
6062
*/
6163
static viewToMetricDescriptor(view: View): MetricDescriptor {
6264
return {
@@ -69,10 +71,11 @@ export class MetricUtils {
6971
}
7072

7173
/**
72-
* Converts tag values to label values.
74+
* Converts tags to label values.
7375
* @param tags
76+
* @returns {LabelValue[]} List of label values
7477
*/
75-
static tagValuesToLabelValues(tags: Tags): LabelValue[] {
78+
static tagsToLabelValues(tags: Tags): LabelValue[] {
7679
return Object.keys(tags).map(key => {
7780
return {value: tags[key]} as LabelValue;
7881
});

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import * as defaultLogger from '../common/console-logger';
1818
import * as loggerTypes from '../common/types';
1919
import {StatsEventListener} from '../exporters/types';
20+
import {Metric} from '../metrics/export/types';
2021

2122
import {AggregationType, Measure, Measurement, MeasureType, MeasureUnit, View} from './types';
2223
import {BaseView} from './view';
@@ -123,6 +124,22 @@ export class Stats {
123124
return measurements.some(measurement => measurement.value < 0);
124125
}
125126

127+
/**
128+
* Gets a collection of produced Metric`s to be exported.
129+
* @returns {Metric[]} List of metrics
130+
*/
131+
getMetrics(): Metric[] {
132+
const metrics: Metric[] = [];
133+
134+
for (const measureName of Object.keys(this.registeredViews)) {
135+
for (const view of this.registeredViews[measureName]) {
136+
metrics.push(view.getMetric());
137+
}
138+
}
139+
140+
return metrics;
141+
}
142+
126143
/**
127144
* Updates all views with the new measurements.
128145
* @param measurements A list of measurements to record

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
* limitations under the License.
1515
*/
1616

17+
import {Metric} from '../metrics/export/types';
18+
1719
/** Tags are maps of names -> values */
1820
export interface Tags { [key: string]: string; }
1921

@@ -113,6 +115,8 @@ export interface View {
113115
getSnapshot(tags: Tags): AggregationData;
114116
/** Gets the view's tag keys */
115117
getColumns(): string[];
118+
/** Gets view`s metric */
119+
getMetric(): Metric;
116120
}
117121

118122
/**
@@ -189,7 +193,7 @@ export interface DistributionData extends AggregationMetadata {
189193
/** Bucket distribution of the histogram */
190194
buckets: Bucket[];
191195
/** Buckets count */
192-
bucketCounts: number[];
196+
bucketCounts?: number[];
193197
}
194198

195199
export type Bucket = number;

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

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616

1717
import * as defaultLogger from '../common/console-logger';
1818
import * as loggerTypes from '../common/types';
19+
import {LabelValue, Metric, MetricDescriptor, MetricDescriptorType, Point, TimeSeries, Timestamp} from '../metrics/export/types';
20+
1921
import {BucketBoundaries} from './bucket-boundaries';
22+
import {MetricUtils} from './metric-utils';
2023
import {Recorder} from './recorder';
2124
import {AggregationData, AggregationType, Measure, Measurement, Tags, View} from './types';
2225

@@ -56,6 +59,11 @@ export class BaseView implements View {
5659
readonly startTime: number;
5760
/** The bucket boundaries in a Distribution Aggregation */
5861
private bucketBoundaries: BucketBoundaries;
62+
/**
63+
* Cache a MetricDescriptor to avoid converting View to MetricDescriptor
64+
* in the future.
65+
*/
66+
private metricDescriptor: MetricDescriptor;
5967
/**
6068
* The end time for this view - represents the last time a value was recorded
6169
*/
@@ -93,6 +101,7 @@ export class BaseView implements View {
93101
this.aggregation = aggregation;
94102
this.startTime = Date.now();
95103
this.bucketBoundaries = new BucketBoundaries(bucketBoundaries);
104+
this.metricDescriptor = MetricUtils.viewToMetricDescriptor(this);
96105
}
97106

98107
/** Gets the view's tag keys */
@@ -185,9 +194,65 @@ export class BaseView implements View {
185194
}
186195
}
187196

197+
/**
198+
* Gets view`s metric
199+
* @returns {Metric}
200+
*/
201+
getMetric(): Metric {
202+
const {type} = this.metricDescriptor;
203+
let startTimestamp: Timestamp;
204+
205+
switch (type) {
206+
case MetricDescriptorType.GAUGE_INT64:
207+
case MetricDescriptorType.GAUGE_DOUBLE:
208+
startTimestamp = null;
209+
break;
210+
default:
211+
const [seconds, nanos] = process.hrtime();
212+
startTimestamp = {seconds, nanos};
213+
}
214+
215+
const timeseries: TimeSeries[] = [];
216+
217+
Object.keys(this.rows).forEach(key => {
218+
const {tags} = this.rows[key];
219+
const labelValues: LabelValue[] = MetricUtils.tagsToLabelValues(tags);
220+
const point: Point = this.toPoint(startTimestamp, this.getSnapshot(tags));
221+
timeseries.push({startTimestamp, labelValues, points: [point]});
222+
});
223+
224+
return {descriptor: this.metricDescriptor, timeseries};
225+
}
226+
227+
/**
228+
* Converts snapshot to point
229+
* @param timestamp The timestamp
230+
* @param data The aggregated data
231+
* @returns {Point}
232+
*/
233+
private toPoint(timestamp: Timestamp, data: AggregationData): Point {
234+
let value;
235+
236+
if (data.type === AggregationType.DISTRIBUTION) {
237+
// TODO: Add examplar transition
238+
const {count, sum, sumOfSquaredDeviation} = data;
239+
value = {
240+
count,
241+
sum,
242+
sumOfSquaredDeviation,
243+
bucketOptions: {explicit: {bounds: data.buckets}},
244+
buckets: data.bucketCounts
245+
};
246+
} else {
247+
value = data.value;
248+
}
249+
return {timestamp, value};
250+
}
251+
188252
/**
189253
* Returns a snapshot of an AggregationData for that tags/labels values.
190254
* @param tags The desired data's tags
255+
* @returns {AggregationData}
191256
*/
192257
getSnapshot(tags: Tags): AggregationData {
193258
return this.rows[this.encodeTags(tags)];
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/**
2+
* Copyright 2018, OpenCensus Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
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';
21+
import {MetricProducerForStats} from '../src/stats/metric-producer';
22+
23+
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+
}
50+
];
51+
const measure: Measure = {
52+
name: 'Test Measure',
53+
type: MeasureType.DOUBLE,
54+
unit: MeasureUnit.UNIT
55+
};
56+
57+
let stats: Stats;
58+
let metricProducerForStats: MetricProducerForStats;
59+
60+
beforeEach(() => {
61+
stats = new Stats();
62+
metricProducerForStats = new MetricProducerForStats(stats);
63+
});
64+
65+
describe('Metric producer', () => {
66+
const tags: Tags = {testKey1: 'testValue', testKey2: 'testValue'};
67+
const measurementValues = [1.1, 2.3, 3.2, 4.3, 5.2];
68+
const buckets = [2, 4, 6];
69+
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+
});
100+
});
101+
});

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ describe('MetricUtil', () => {
4848
it('should convert tag values to label values', () => {
4949
const tags: Tags = {test: 'test1', tag: 'test2', empty: '', fake: null};
5050
assert.deepStrictEqual(
51-
MetricUtils.tagValuesToLabelValues(tags),
51+
MetricUtils.tagsToLabelValues(tags),
5252
[{value: 'test1'}, {value: 'test2'}, {value: ''}, {value: null}]);
5353
});
5454
});

0 commit comments

Comments
 (0)