Skip to content
This repository was archived by the owner on Sep 17, 2025. It is now read-only.

Commit d9384fd

Browse files
authored
Add helper class for stats/metrics conversion (#355)
1 parent 781b3cb commit d9384fd

2 files changed

Lines changed: 185 additions & 0 deletions

File tree

opencensus/stats/metric_utils.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Copyright 2018, OpenCensus Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
"""
15+
Utilities to convert stats data models to metrics data models.
16+
"""
17+
18+
from opencensus.metrics import label_key
19+
from opencensus.metrics.export import metric_descriptor
20+
from opencensus.stats import aggregation as aggregation_module
21+
from opencensus.stats import measure as measure_module
22+
23+
# To check that an aggregation's reported type matches its class
24+
AGGREGATION_TYPE_MAP = {
25+
aggregation_module.Type.SUM:
26+
aggregation_module.SumAggregation,
27+
aggregation_module.Type.COUNT:
28+
aggregation_module.CountAggregation,
29+
aggregation_module.Type.DISTRIBUTION:
30+
aggregation_module.DistributionAggregation,
31+
aggregation_module.Type.LASTVALUE:
32+
aggregation_module.LastValueAggregation,
33+
}
34+
35+
36+
def get_metric_type(measure, aggregation):
37+
"""Get the corresponding metric type for the given stats type.
38+
39+
:type measure: (:class: '~opencensus.stats.measure.BaseMeasure')
40+
:param measure: the measure for which to find a metric type
41+
42+
:type aggregation: (:class:
43+
'~opencensus.stats.aggregation.BaseAggregation')
44+
:param aggregation: the aggregation for which to find a metric type
45+
"""
46+
if aggregation.aggregation_type == aggregation_module.Type.NONE:
47+
raise ValueError("aggregation type must not be NONE")
48+
assert isinstance(aggregation,
49+
AGGREGATION_TYPE_MAP[aggregation.aggregation_type])
50+
51+
if aggregation.aggregation_type == aggregation_module.Type.SUM:
52+
if isinstance(measure, measure_module.MeasureInt):
53+
return metric_descriptor.MetricDescriptorType.CUMULATIVE_INT64
54+
elif isinstance(measure, measure_module.MeasureFloat):
55+
return metric_descriptor.MetricDescriptorType.CUMULATIVE_DOUBLE
56+
else:
57+
raise ValueError
58+
elif aggregation.aggregation_type == aggregation_module.Type.COUNT:
59+
return metric_descriptor.MetricDescriptorType.CUMULATIVE_INT64
60+
elif aggregation.aggregation_type == aggregation_module.Type.DISTRIBUTION:
61+
return metric_descriptor.MetricDescriptorType.CUMULATIVE_DISTRIBUTION
62+
elif aggregation.aggregation_type == aggregation_module.Type.LASTVALUE:
63+
if isinstance(measure, measure_module.MeasureInt):
64+
return metric_descriptor.MetricDescriptorType.GAUGE_INT64
65+
elif isinstance(measure, measure_module.MeasureFloat):
66+
return metric_descriptor.MetricDescriptorType.GAUGE_DOUBLE
67+
else:
68+
raise ValueError
69+
else:
70+
raise AssertionError # pragma: NO COVER
71+
72+
73+
def view_to_metric_descriptor(view):
74+
"""Get a MetricDescriptor for given view data.
75+
76+
:type view: (:class: '~opencensus.stats.view.View')
77+
:param view: the view data to for which to build a metric descriptor
78+
"""
79+
return metric_descriptor.MetricDescriptor(
80+
view.name, view.description, view.measure.unit,
81+
get_metric_type(view.measure, view.aggregation),
82+
# TODO: add label key description
83+
[label_key.LabelKey(tk, "") for tk in view.columns])
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# Copyright 2018, OpenCensus Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
try:
16+
import mock
17+
except ImportError:
18+
from unittest import mock
19+
20+
import unittest
21+
22+
from opencensus.metrics.export import metric_descriptor
23+
from opencensus.stats import aggregation
24+
from opencensus.stats import measure
25+
from opencensus.stats import metric_utils
26+
from opencensus.stats import view
27+
28+
29+
class TestMetricUtils(unittest.TestCase):
30+
def test_get_metric_type(self):
31+
measure_int = mock.Mock(spec=measure.MeasureInt)
32+
measure_float = mock.Mock(spec=measure.MeasureFloat)
33+
agg_sum = mock.Mock(spec=aggregation.SumAggregation)
34+
agg_sum.aggregation_type = aggregation.Type.SUM
35+
agg_count = mock.Mock(spec=aggregation.CountAggregation)
36+
agg_count.aggregation_type = aggregation.Type.COUNT
37+
agg_dist = mock.Mock(spec=aggregation.DistributionAggregation)
38+
agg_dist.aggregation_type = aggregation.Type.DISTRIBUTION
39+
agg_lv = mock.Mock(spec=aggregation.LastValueAggregation)
40+
agg_lv.aggregation_type = aggregation.Type.LASTVALUE
41+
42+
view_to_metric_type = {
43+
(measure_int, agg_sum):
44+
metric_descriptor.MetricDescriptorType.CUMULATIVE_INT64,
45+
(measure_int, agg_count):
46+
metric_descriptor.MetricDescriptorType.CUMULATIVE_INT64,
47+
(measure_int, agg_dist):
48+
metric_descriptor.MetricDescriptorType.CUMULATIVE_DISTRIBUTION,
49+
(measure_int, agg_lv):
50+
metric_descriptor.MetricDescriptorType.GAUGE_INT64,
51+
(measure_float, agg_sum):
52+
metric_descriptor.MetricDescriptorType.CUMULATIVE_DOUBLE,
53+
(measure_float, agg_count):
54+
metric_descriptor.MetricDescriptorType.CUMULATIVE_INT64,
55+
(measure_float, agg_dist):
56+
metric_descriptor.MetricDescriptorType.CUMULATIVE_DISTRIBUTION,
57+
(measure_float, agg_lv):
58+
metric_descriptor.MetricDescriptorType.GAUGE_DOUBLE,
59+
}
60+
61+
for (mm, ma), metric_type in view_to_metric_type.items():
62+
self.assertEqual(metric_utils.get_metric_type(mm, ma), metric_type)
63+
64+
def test_get_metric_type_bad_aggregation(self):
65+
base_agg = mock.Mock(spec=aggregation.BaseAggregation)
66+
base_agg.aggregation_type = aggregation.Type.NONE
67+
with self.assertRaises(ValueError):
68+
metric_utils.get_metric_type(mock.Mock(), base_agg)
69+
70+
bad_agg = mock.Mock(spec=aggregation.SumAggregation)
71+
bad_agg.aggregation_type = aggregation.Type.COUNT
72+
with self.assertRaises(AssertionError):
73+
metric_utils.get_metric_type(mock.Mock(), bad_agg)
74+
75+
def test_get_metric_type_bad_measure(self):
76+
base_measure = mock.Mock(spec=measure.BaseMeasure)
77+
agg_sum = mock.Mock(spec=aggregation.SumAggregation)
78+
agg_sum.aggregation_type = aggregation.Type.SUM
79+
agg_lv = mock.Mock(spec=aggregation.LastValueAggregation)
80+
agg_lv.aggregation_type = aggregation.Type.LASTVALUE
81+
with self.assertRaises(ValueError):
82+
metric_utils.get_metric_type(base_measure, agg_sum)
83+
with self.assertRaises(ValueError):
84+
metric_utils.get_metric_type(base_measure, agg_lv)
85+
86+
def test_view_to_metric_descriptor(self):
87+
mock_measure = mock.Mock(spec=measure.MeasureFloat)
88+
mock_agg = mock.Mock(spec=aggregation.SumAggregation)
89+
mock_agg.aggregation_type = aggregation.Type.SUM
90+
test_view = view.View("name", "description", ["tk1", "tk2"],
91+
mock_measure, mock_agg)
92+
93+
md = metric_utils.view_to_metric_descriptor(test_view)
94+
self.assertTrue(isinstance(md, metric_descriptor.MetricDescriptor))
95+
self.assertEqual(md.name, test_view.name)
96+
self.assertEqual(md.description, test_view.description)
97+
self.assertEqual(md.unit, test_view.measure.unit)
98+
self.assertEqual(
99+
md.type, metric_descriptor.MetricDescriptorType.CUMULATIVE_DOUBLE)
100+
self.assertTrue(
101+
all(lk.key == col
102+
for lk, col in zip(md.label_keys, test_view.columns)))

0 commit comments

Comments
 (0)