-
Notifications
You must be signed in to change notification settings - Fork 250
Support int typed aggregations #696
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
3a6263d
44ce81d
5289909
6659817
1681a35
f7668cc
f89bea5
eb199aa
207f980
f98ddc1
e890189
f62746f
b27a8ee
22e8bc3
25fb25c
8f9b313
71994eb
7e0706a
7549e50
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,30 +14,14 @@ | |
|
||
import logging | ||
|
||
from opencensus.stats import bucket_boundaries | ||
from opencensus.stats import aggregation_data | ||
from opencensus.stats import measure as measure_module | ||
from opencensus.metrics.export.metric_descriptor import MetricDescriptorType | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class Type(object): | ||
""" The type of aggregation function used on a View. | ||
|
||
Attributes: | ||
NONE (int): The aggregation type of the view is 'unknown'. | ||
SUM (int): The aggregation type of the view is 'sum'. | ||
COUNT (int): The aggregation type of the view is 'count'. | ||
DISTRIBUTION (int): The aggregation type of the view is 'distribution'. | ||
LASTVALUE (int): The aggregation type of the view is 'lastvalue'. | ||
""" | ||
NONE = 0 | ||
SUM = 1 | ||
COUNT = 2 | ||
DISTRIBUTION = 3 | ||
LASTVALUE = 4 | ||
|
||
|
||
class BaseAggregation(object): | ||
"""Aggregation describes how the data collected is aggregated by type of | ||
aggregation and buckets | ||
|
@@ -51,8 +35,7 @@ class BaseAggregation(object): | |
:param aggregation_type: represents the type of this aggregation | ||
|
||
""" | ||
def __init__(self, buckets=None, aggregation_type=Type.NONE): | ||
self._aggregation_type = aggregation_type | ||
def __init__(self, buckets=None): | ||
self._buckets = buckets or [] | ||
|
||
@property | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You still have an aggregation_type property. As well remove the param comment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I ended up removing |
||
|
@@ -78,16 +61,25 @@ class SumAggregation(BaseAggregation): | |
:param aggregation_type: represents the type of this aggregation | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO, I would include a get_metric_type(measure) method in BaseAggregation with no implementation to let developers know that aggregations should implement this (there might be new kinds of aggregations) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: Fix "Sum Aggregation DESCRIBES" in comments There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
|
||
""" | ||
def __init__(self, sum=None, aggregation_type=Type.SUM): | ||
super(SumAggregation, self).__init__(aggregation_type=aggregation_type) | ||
self._sum = aggregation_data.SumAggregationDataFloat( | ||
sum_data=float(sum or 0)) | ||
self.aggregation_data = self._sum | ||
|
||
@property | ||
def sum(self): | ||
"""The sum of the current aggregation""" | ||
return self._sum | ||
def __init__(self, sum=None): | ||
super(SumAggregation, self).__init__() | ||
self._initial_sum = sum or 0 | ||
|
||
def new_aggregation_data(self, measure): | ||
value_type = MetricDescriptorType.to_type_class( | ||
self.get_metric_type(measure)) | ||
# TODO: do we need to type cast `_initial_sum`? | ||
colincadams marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return aggregation_data.SumAggregationData( | ||
value_type=value_type, sum_data=self._initial_sum) | ||
|
||
@staticmethod | ||
def get_metric_type(measure): | ||
if isinstance(measure, measure_module.MeasureInt): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't have strong opinion here, it seems a more "Pythonic" style is: if isinstance(measure, measure_module.MeasureInt):
return MetricDescriptorType.CUMULATIVE_INT64
if isinstance(measure, measure_module.MeasureFloat):
return MetricDescriptorType.CUMULATIVE_DOUBLE
raise ValueError Up to you. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch, surprised the linter didn't yell about this (or maybe it was a warning I didn't see 😁) |
||
return MetricDescriptorType.CUMULATIVE_INT64 | ||
elif isinstance(measure, measure_module.MeasureFloat): | ||
return MetricDescriptorType.CUMULATIVE_DOUBLE | ||
else: | ||
raise ValueError | ||
|
||
|
||
class CountAggregation(BaseAggregation): | ||
|
@@ -101,16 +93,16 @@ class CountAggregation(BaseAggregation): | |
:param aggregation_type: represents the type of this aggregation | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix param comments There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
|
||
""" | ||
def __init__(self, count=0, aggregation_type=Type.COUNT): | ||
super(CountAggregation, self).__init__( | ||
aggregation_type=aggregation_type) | ||
self._count = aggregation_data.CountAggregationData(count) | ||
self.aggregation_data = self._count | ||
def __init__(self, count=0): | ||
super(CountAggregation, self).__init__() | ||
self._initial_count = count | ||
|
||
@property | ||
def count(self): | ||
"""The count of the current aggregation""" | ||
return self._count | ||
def new_aggregation_data(self, measure=None): | ||
return aggregation_data.CountAggregationData(self._initial_count) | ||
|
||
@staticmethod | ||
def get_metric_type(measure): | ||
return MetricDescriptorType.CUMULATIVE_INT64 | ||
|
||
|
||
class DistributionAggregation(BaseAggregation): | ||
|
@@ -129,10 +121,7 @@ class DistributionAggregation(BaseAggregation): | |
|
||
""" | ||
|
||
def __init__(self, | ||
boundaries=None, | ||
distribution=None, | ||
aggregation_type=Type.DISTRIBUTION): | ||
def __init__(self, boundaries=None): | ||
if boundaries: | ||
if not all(boundaries[ii] < boundaries[ii + 1] | ||
for ii in range(len(boundaries) - 1)): | ||
|
@@ -147,22 +136,16 @@ def __init__(self, | |
ii) | ||
boundaries = boundaries[ii:] | ||
|
||
super(DistributionAggregation, self).__init__( | ||
buckets=boundaries, aggregation_type=aggregation_type) | ||
self._boundaries = bucket_boundaries.BucketBoundaries(boundaries) | ||
self._distribution = distribution or {} | ||
self.aggregation_data = aggregation_data.DistributionAggregationData( | ||
0, 0, 0, None, boundaries) | ||
super(DistributionAggregation, self).__init__(buckets=boundaries) | ||
self._boundaries = boundaries | ||
|
||
@property | ||
def boundaries(self): | ||
"""The boundaries of the current aggregation""" | ||
return self._boundaries | ||
def new_aggregation_data(self, measure=None): | ||
return aggregation_data.DistributionAggregationData( | ||
0, 0, 0, None, self._boundaries) | ||
|
||
@property | ||
def distribution(self): | ||
"""The distribution of the current aggregation""" | ||
return self._distribution | ||
@staticmethod | ||
def get_metric_type(measure): | ||
return MetricDescriptorType.CUMULATIVE_DISTRIBUTION | ||
|
||
|
||
class LastValueAggregation(BaseAggregation): | ||
|
@@ -176,15 +159,21 @@ class LastValueAggregation(BaseAggregation): | |
:param aggregation_type: represents the type of this aggregation | ||
|
||
""" | ||
def __init__(self, value=0, aggregation_type=Type.LASTVALUE): | ||
super(LastValueAggregation, self).__init__( | ||
aggregation_type=aggregation_type) | ||
self.aggregation_data = aggregation_data.LastValueAggregationData( | ||
value=value) | ||
self._value = value | ||
|
||
@property | ||
def value(self): | ||
"""The current recorded value | ||
""" | ||
return self._value | ||
def __init__(self, value=0): | ||
super(LastValueAggregation, self).__init__() | ||
self._initial_value = value | ||
|
||
def new_aggregation_data(self, measure): | ||
value_type = MetricDescriptorType.to_type_class( | ||
self.get_metric_type(measure)) | ||
return aggregation_data.LastValueAggregationData( | ||
value=self._initial_value, value_type=value_type) | ||
|
||
@staticmethod | ||
def get_metric_type(measure): | ||
if isinstance(measure, measure_module.MeasureInt): | ||
return MetricDescriptorType.GAUGE_INT64 | ||
elif isinstance(measure, measure_module.MeasureFloat): | ||
return MetricDescriptorType.GAUGE_DOUBLE | ||
else: | ||
raise ValueError |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,16 +52,21 @@ def to_point(self, timestamp): | |
raise NotImplementedError # pragma: NO COVER | ||
|
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Is there a reason for this class to exist? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not that I can tell, besides to show that aggregations should implement In any case it looks like you can lose the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just removed |
||
class SumAggregationDataFloat(BaseAggregationData): | ||
class SumAggregationData(BaseAggregationData): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why the decision to make There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Initially, I had this private class with
But then in We could also duplicate the classes entirely, instead of the I guess the other option is to force the user to decide and provide Int or Float, but since we can determine it that seems easier and less error prone. |
||
"""Sum Aggregation Data is the aggregated data for the Sum aggregation | ||
|
||
:type sum_data: float | ||
:type value_type: class that is either | ||
:class:`opencensus.metrics.export.value.ValueDouble` or | ||
:class:`opencensus.metrics.export.value.ValueLong` | ||
:param value_type: the type of value to be used when creating a point | ||
:type sum_data: meh | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. meh? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. loll 🤸♂ |
||
:param sum_data: represents the aggregated sum | ||
|
||
""" | ||
|
||
def __init__(self, sum_data): | ||
super(SumAggregationDataFloat, self).__init__(sum_data) | ||
def __init__(self, value_type, sum_data): | ||
super(SumAggregationData, self).__init__(sum_data) | ||
self._value_type = value_type | ||
self._sum_data = sum_data | ||
|
||
def __repr__(self): | ||
|
@@ -82,17 +87,22 @@ def sum_data(self): | |
"""The current sum data""" | ||
return self._sum_data | ||
|
||
@property | ||
def value_type(self): | ||
"""The value type to use when creating the point""" | ||
return self._value_type | ||
|
||
def to_point(self, timestamp): | ||
"""Get a Point conversion of this aggregation. | ||
|
||
:type timestamp: :class: `datetime.datetime` | ||
:param timestamp: The time to report the point as having been recorded. | ||
|
||
:rtype: :class: `opencensus.metrics.export.point.Point` | ||
:return: a :class: `opencensus.metrics.export.value.ValueDouble`-valued | ||
Point with value equal to `sum_data`. | ||
:return: a Point with value equal to `sum_data` and of type | ||
`_value_type`. | ||
""" | ||
return point.Point(value.ValueDouble(self.sum_data), timestamp) | ||
return point.Point(self._value_type(self.sum_data), timestamp) | ||
|
||
|
||
class CountAggregationData(BaseAggregationData): | ||
|
@@ -328,13 +338,18 @@ class LastValueAggregationData(BaseAggregationData): | |
""" | ||
LastValue Aggregation Data is the value of aggregated data | ||
|
||
:type value_type: class that is either | ||
:class:`opencensus.metrics.export.value.ValueDouble` or | ||
:class:`opencensus.metrics.export.value.ValueLong` | ||
:param value_type: the type of value to be used when creating a point | ||
:type value: long | ||
:param value: represents the current value | ||
|
||
""" | ||
|
||
def __init__(self, value): | ||
def __init__(self, value_type, value): | ||
super(LastValueAggregationData, self).__init__(value) | ||
self._value_type = value_type | ||
self._value = value | ||
|
||
def __repr__(self): | ||
|
@@ -355,17 +370,21 @@ def value(self): | |
"""The current value recorded""" | ||
return self._value | ||
|
||
@property | ||
def value_type(self): | ||
"""The value type to use when creating the point""" | ||
return self._value_type | ||
|
||
def to_point(self, timestamp): | ||
"""Get a Point conversion of this aggregation. | ||
|
||
:type timestamp: :class: `datetime.datetime` | ||
:param timestamp: The time to report the point as having been recorded. | ||
|
||
:rtype: :class: `opencensus.metrics.export.point.Point` | ||
:return: a :class: `opencensus.metrics.export.value.ValueDouble`-valued | ||
Point. | ||
:return: a Point with value of type `_value_type`. | ||
""" | ||
return point.Point(value.ValueDouble(self.value), timestamp) | ||
return point.Point(self._value_type(self.value), timestamp) | ||
|
||
|
||
class Exemplar(object): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While you're in here: I don't see any reason for
buckets
to be onBaseAggregation
, it looks like an odd choice from the first implementation (#149) that never got cleaned up. Sinceaggregation_type
is gone now I recommend scrapping this whole class.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, just removed the class.