-
Notifications
You must be signed in to change notification settings - Fork 250
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Metrics: Add Value, Point and Summary (#337)
* Add Value, Point and Summary * Fix reviews
- Loading branch information
1 parent
3abb0b6
commit 1147173
Showing
8 changed files
with
502 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# 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. | ||
|
||
|
||
class Point(object): | ||
"""A timestamped measurement of a TimeSeries. | ||
:type value: Value | ||
:param value: the Value of the Point. | ||
:type timestamp: time | ||
:param timestamp: the Timestamp when the Point was recorded. | ||
""" | ||
|
||
def __init__(self, value, timestamp): | ||
self._value = value | ||
self._timestamp = timestamp | ||
|
||
@property | ||
def value(self): | ||
"""Returns the Value""" | ||
return self._value | ||
|
||
@property | ||
def timestamp(self): | ||
"""Returns the Timestamp when this Point was recorded.""" | ||
return self._timestamp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
# 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. | ||
|
||
|
||
class Summary(object): | ||
"""Implementation of the Summary as a summary of observations. | ||
:type count: long | ||
:param count: the count of the population values. | ||
:type sum_data: float | ||
:param sum_data: the sum of the population values. | ||
:type snapshot: Snapshot | ||
:param snapshot: the values calculated over a sliding time window. | ||
""" | ||
|
||
def __init__(self, count, sum_data, snapshot): | ||
check_count_and_sum(count, sum_data) | ||
self._count = count | ||
self._sum_data = sum_data | ||
|
||
if snapshot is None: | ||
raise ValueError('snapshot must not be none') | ||
|
||
self._snapshot = snapshot | ||
|
||
@property | ||
def count(self): | ||
"""Returns the count of the population values""" | ||
return self._count | ||
|
||
@property | ||
def sum_data(self): | ||
"""Returns the sum of the population values.""" | ||
return self._sum_data | ||
|
||
@property | ||
def snapshot(self): | ||
"""Returns the values calculated over a sliding time window.""" | ||
return self._snapshot | ||
|
||
|
||
class Snapshot(object): | ||
"""Represents the summary observation of the recorded events over a | ||
sliding time window. | ||
:type count: long | ||
:param count: the number of values in the snapshot. | ||
:type sum_data: float | ||
:param sum_data: the sum of values in the snapshot. | ||
:type value_at_percentiles: ValueAtPercentile | ||
:param value_at_percentiles: a list of values at different percentiles | ||
of the distribution calculated from the current snapshot. The percentiles | ||
must be strictly increasing. | ||
""" | ||
|
||
def __init__(self, count, sum_data, value_at_percentiles=None): | ||
check_count_and_sum(count, sum_data) | ||
self._count = count | ||
self._sum_data = sum_data | ||
|
||
if value_at_percentiles is None: | ||
value_at_percentiles = [] | ||
|
||
if not isinstance(value_at_percentiles, list): | ||
raise ValueError('value_at_percentiles must be an ' | ||
'instance of list') | ||
|
||
self._value_at_percentiles = value_at_percentiles | ||
|
||
@property | ||
def count(self): | ||
"""Returns the number of values in the snapshot""" | ||
return self._count | ||
|
||
@property | ||
def sum_data(self): | ||
"""Returns the sum of values in the snapshot.""" | ||
return self._sum_data | ||
|
||
@property | ||
def value_at_percentiles(self): | ||
"""Returns a list of values at different percentiles | ||
of the distribution calculated from the current snapshot. | ||
""" | ||
return self._value_at_percentiles | ||
|
||
|
||
class ValueAtPercentile(object): | ||
"""Represents the value at a given percentile of a distribution. | ||
:type percentile: float | ||
:param percentile: the percentile in the ValueAtPercentile. | ||
:type value: float | ||
:param value: the value in the ValueAtPercentile. | ||
""" | ||
|
||
def __init__(self, percentile, value): | ||
|
||
if not 0 < percentile <= 100.0: | ||
raise ValueError("percentile must be in the interval (0.0, 100.0]") | ||
|
||
self._percentile = percentile | ||
|
||
if value < 0: | ||
raise ValueError('value must be non-negative') | ||
|
||
self._value = value | ||
|
||
@property | ||
def percentile(self): | ||
"""Returns the percentile in the ValueAtPercentile""" | ||
return self._percentile | ||
|
||
@property | ||
def value(self): | ||
"""Returns the value in the ValueAtPercentile""" | ||
return self._value | ||
|
||
|
||
def check_count_and_sum(count, sum_data): | ||
if not (count is None or count >= 0): | ||
raise ValueError('count must be non-negative') | ||
|
||
if not (sum_data is None or sum_data >= 0): | ||
raise ValueError('sum_data must be non-negative') | ||
|
||
if count == 0 and sum_data != 0: | ||
raise ValueError('sum_data must be 0 if count is 0') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# 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. | ||
|
||
|
||
class Value(object): | ||
"""The actual point value for a Point. | ||
Currently there are four types of Value: | ||
<ul> | ||
<li>double | ||
<li>long | ||
<li>Summary | ||
<li>Distribution (TODO(mayurkale): add Distribution class) | ||
</ul> | ||
Each Point contains exactly one of the four Value types. | ||
""" | ||
def __init__(self, value): | ||
self._value = value | ||
|
||
@staticmethod | ||
def double_value(value): | ||
"""Returns a double Value | ||
:type value: float | ||
:param value: value in double | ||
""" | ||
return ValueDouble(value) | ||
|
||
@staticmethod | ||
def long_value(value): | ||
"""Returns a long Value | ||
:type value: long | ||
:param value: value in long | ||
""" | ||
return ValueLong(value) | ||
|
||
@staticmethod | ||
def summary_value(value): | ||
"""Returns a summary Value | ||
:type value: Summary | ||
:param value: value in Summary | ||
""" | ||
return ValueSummary(value) | ||
|
||
@property | ||
def value(self): | ||
"""Returns the value.""" | ||
return self._value | ||
|
||
|
||
class ValueDouble(Value): | ||
"""A 64-bit double-precision floating-point number. | ||
:type value: float | ||
:param value: the value in float. | ||
""" | ||
def __init__(self, value): | ||
super(ValueDouble, self).__init__(value) | ||
|
||
|
||
class ValueLong(Value): | ||
"""A 64-bit integer. | ||
:type value: long | ||
:param value: the value in long. | ||
""" | ||
def __init__(self, value): | ||
super(ValueLong, self).__init__(value) | ||
|
||
|
||
class ValueSummary(Value): | ||
"""Represents a snapshot values calculated over an arbitrary time window. | ||
:type value: summary | ||
:param value: the value in summary. | ||
""" | ||
def __init__(self, value): | ||
super(ValueSummary, self).__init__(value) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# 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. | ||
|
||
import unittest | ||
from opencensus.metrics.export import point as point_module | ||
from opencensus.metrics.export import summary as summary_module | ||
from opencensus.metrics.export import value as value_module | ||
|
||
|
||
class TestPoint(unittest.TestCase): | ||
|
||
def setUp(self): | ||
self.double_value = value_module.Value.double_value(55.5) | ||
self.long_value = value_module.Value.long_value(9876543210) | ||
self.timestamp = '2018-10-06T17:57:57.936475Z' | ||
|
||
value_at_percentile = [summary_module.ValueAtPercentile(99.5, 10.2)] | ||
snapshot = summary_module.Snapshot(10, 87.07, value_at_percentile) | ||
self.summary = summary_module.Summary(10, 6.6, snapshot) | ||
self.summary_value = value_module.Value.summary_value(self.summary) | ||
|
||
def test_point_with_double_value(self): | ||
point = point_module.Point(self.double_value, self.timestamp) | ||
|
||
self.assertIsNotNone(point) | ||
self.assertEqual(point.timestamp, self.timestamp) | ||
|
||
self.assertIsInstance(point.value, value_module.ValueDouble) | ||
self.assertIsNotNone(point.value) | ||
self.assertEqual(point.value, self.double_value) | ||
self.assertEqual(point.value.value, 55.5) | ||
|
||
def test_point_with_long_value(self): | ||
point = point_module.Point(self.long_value, self.timestamp) | ||
|
||
self.assertIsNotNone(point) | ||
self.assertEqual(point.timestamp, self.timestamp) | ||
|
||
self.assertIsInstance(point.value, value_module.ValueLong) | ||
self.assertIsNotNone(point.value) | ||
self.assertEqual(point.value, self.long_value) | ||
self.assertEqual(point.value.value, 9876543210) | ||
|
||
def test_point_with_summary_value(self): | ||
point = point_module.Point(self.summary_value, self.timestamp) | ||
|
||
self.assertIsNotNone(point) | ||
self.assertEqual(point.timestamp, self.timestamp) | ||
|
||
self.assertIsInstance(point.value, value_module.ValueSummary) | ||
self.assertIsNotNone(point.value) | ||
self.assertEqual(point.value, self.summary_value) | ||
self.assertEqual(point.value.value, self.summary) |
Oops, something went wrong.