Skip to content
This repository was archived by the owner on Sep 17, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions opencensus/stats/metric_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Copyright 2018, 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.
"""
Utilities to convert stats data models to metrics data models.
"""

from opencensus.metrics import label_key
from opencensus.metrics.export import metric_descriptor
from opencensus.stats import aggregation as aggregation_module
from opencensus.stats import measure as measure_module

# To check that an aggregation's reported type matches its class
AGGREGATION_TYPE_MAP = {
aggregation_module.Type.SUM:
aggregation_module.SumAggregation,
aggregation_module.Type.COUNT:
aggregation_module.CountAggregation,
aggregation_module.Type.DISTRIBUTION:
aggregation_module.DistributionAggregation,
aggregation_module.Type.LASTVALUE:
aggregation_module.LastValueAggregation,
}


def get_metric_type(measure, aggregation):
"""Get the corresponding metric type for the given stats type.

:type measure: (:class: '~opencensus.stats.measure.BaseMeasure')
:param measure: the measure for which to find a metric type

:type aggregation: (:class:
'~opencensus.stats.aggregation.BaseAggregation')
:param aggregation: the aggregation for which to find a metric type
"""
if aggregation.aggregation_type == aggregation_module.Type.NONE:
raise ValueError("aggregation type must not be NONE")
assert isinstance(aggregation,
AGGREGATION_TYPE_MAP[aggregation.aggregation_type])

if aggregation.aggregation_type == aggregation_module.Type.SUM:
if isinstance(measure, measure_module.MeasureInt):
return metric_descriptor.MetricDescriptorType.CUMULATIVE_INT64
elif isinstance(measure, measure_module.MeasureFloat):
return metric_descriptor.MetricDescriptorType.CUMULATIVE_DOUBLE
else:
raise ValueError
elif aggregation.aggregation_type == aggregation_module.Type.COUNT:
return metric_descriptor.MetricDescriptorType.CUMULATIVE_INT64
elif aggregation.aggregation_type == aggregation_module.Type.DISTRIBUTION:
return metric_descriptor.MetricDescriptorType.CUMULATIVE_DISTRIBUTION
elif aggregation.aggregation_type == aggregation_module.Type.LASTVALUE:
if isinstance(measure, measure_module.MeasureInt):
return metric_descriptor.MetricDescriptorType.GAUGE_INT64
elif isinstance(measure, measure_module.MeasureFloat):
return metric_descriptor.MetricDescriptorType.GAUGE_DOUBLE
else:
raise ValueError
else:
raise AssertionError # pragma: NO COVER


def view_to_metric_descriptor(view):
"""Get a MetricDescriptor for given view data.

:type view: (:class: '~opencensus.stats.view.View')
:param view: the view data to for which to build a metric descriptor
"""
return metric_descriptor.MetricDescriptor(
view.name, view.description, view.measure.unit,
get_metric_type(view.measure, view.aggregation),
# TODO: add label key description
[label_key.LabelKey(tk, "") for tk in view.columns])
Comment thread
c24t marked this conversation as resolved.
102 changes: 102 additions & 0 deletions tests/unit/stats/test_metric_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Copyright 2018, 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.

try:
import mock
except ImportError:
from unittest import mock

import unittest

from opencensus.metrics.export import metric_descriptor
from opencensus.stats import aggregation
from opencensus.stats import measure
from opencensus.stats import metric_utils
from opencensus.stats import view


class TestMetricUtils(unittest.TestCase):
def test_get_metric_type(self):
measure_int = mock.Mock(spec=measure.MeasureInt)
measure_float = mock.Mock(spec=measure.MeasureFloat)
agg_sum = mock.Mock(spec=aggregation.SumAggregation)
agg_sum.aggregation_type = aggregation.Type.SUM
agg_count = mock.Mock(spec=aggregation.CountAggregation)
agg_count.aggregation_type = aggregation.Type.COUNT
agg_dist = mock.Mock(spec=aggregation.DistributionAggregation)
agg_dist.aggregation_type = aggregation.Type.DISTRIBUTION
agg_lv = mock.Mock(spec=aggregation.LastValueAggregation)
agg_lv.aggregation_type = aggregation.Type.LASTVALUE

view_to_metric_type = {
(measure_int, agg_sum):
metric_descriptor.MetricDescriptorType.CUMULATIVE_INT64,
(measure_int, agg_count):
metric_descriptor.MetricDescriptorType.CUMULATIVE_INT64,
(measure_int, agg_dist):
metric_descriptor.MetricDescriptorType.CUMULATIVE_DISTRIBUTION,
(measure_int, agg_lv):
metric_descriptor.MetricDescriptorType.GAUGE_INT64,
(measure_float, agg_sum):
metric_descriptor.MetricDescriptorType.CUMULATIVE_DOUBLE,
(measure_float, agg_count):
metric_descriptor.MetricDescriptorType.CUMULATIVE_INT64,
(measure_float, agg_dist):
metric_descriptor.MetricDescriptorType.CUMULATIVE_DISTRIBUTION,
(measure_float, agg_lv):
metric_descriptor.MetricDescriptorType.GAUGE_DOUBLE,
}

for (mm, ma), metric_type in view_to_metric_type.items():
self.assertEqual(metric_utils.get_metric_type(mm, ma), metric_type)

def test_get_metric_type_bad_aggregation(self):
base_agg = mock.Mock(spec=aggregation.BaseAggregation)
base_agg.aggregation_type = aggregation.Type.NONE
with self.assertRaises(ValueError):
metric_utils.get_metric_type(mock.Mock(), base_agg)

bad_agg = mock.Mock(spec=aggregation.SumAggregation)
bad_agg.aggregation_type = aggregation.Type.COUNT
with self.assertRaises(AssertionError):
metric_utils.get_metric_type(mock.Mock(), bad_agg)

def test_get_metric_type_bad_measure(self):
base_measure = mock.Mock(spec=measure.BaseMeasure)
agg_sum = mock.Mock(spec=aggregation.SumAggregation)
agg_sum.aggregation_type = aggregation.Type.SUM
agg_lv = mock.Mock(spec=aggregation.LastValueAggregation)
agg_lv.aggregation_type = aggregation.Type.LASTVALUE
with self.assertRaises(ValueError):
metric_utils.get_metric_type(base_measure, agg_sum)
with self.assertRaises(ValueError):
metric_utils.get_metric_type(base_measure, agg_lv)

def test_view_to_metric_descriptor(self):
mock_measure = mock.Mock(spec=measure.MeasureFloat)
mock_agg = mock.Mock(spec=aggregation.SumAggregation)
mock_agg.aggregation_type = aggregation.Type.SUM
test_view = view.View("name", "description", ["tk1", "tk2"],
mock_measure, mock_agg)

md = metric_utils.view_to_metric_descriptor(test_view)
self.assertTrue(isinstance(md, metric_descriptor.MetricDescriptor))
self.assertEqual(md.name, test_view.name)
self.assertEqual(md.description, test_view.description)
self.assertEqual(md.unit, test_view.measure.unit)
self.assertEqual(
md.type, metric_descriptor.MetricDescriptorType.CUMULATIVE_DOUBLE)
self.assertTrue(
all(lk.key == col
for lk, col in zip(md.label_keys, test_view.columns)))