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

Commit d3b2897

Browse files
authored
DistributionAggregation fixes (#375)
Fix a few existing bugs in DistributionAggregation, and lint/formatting issues in related files.
1 parent 03ad5ea commit d3b2897

6 files changed

Lines changed: 319 additions & 281 deletions

File tree

opencensus/stats/aggregation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def __init__(
133133
self._boundaries = bucket_boundaries.BucketBoundaries(boundaries)
134134
self._distribution = distribution or {}
135135
self.aggregation_data = aggregation_data.DistributionAggregationData(
136-
0, 0, 0, 0, 0, None, boundaries)
136+
0, 0, float('inf'), float('-inf'), 0, None, boundaries)
137137

138138
@property
139139
def boundaries(self):

opencensus/stats/aggregation_data.py

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
1415
from opencensus.stats import bucket_boundaries
1516

1617

@@ -21,6 +22,7 @@ class BaseAggregationData(object):
2122
:param aggregation_data: represents the aggregated value from a collection
2223
2324
"""
25+
2426
def __init__(self, aggregation_data):
2527
self._aggregation_data = aggregation_data
2628

@@ -37,6 +39,7 @@ class SumAggregationDataFloat(BaseAggregationData):
3739
:param sum_data: represents the aggregated sum
3840
3941
"""
42+
4043
def __init__(self, sum_data):
4144
super(SumAggregationDataFloat, self).__init__(sum_data)
4245
self._sum_data = sum_data
@@ -60,6 +63,7 @@ class CountAggregationData(BaseAggregationData):
6063
:param count_data: represents the aggregated count
6164
6265
"""
66+
6367
def __init__(self, count_data):
6468
super(CountAggregationData, self).__init__(count_data)
6569
self._count_data = count_data
@@ -104,6 +108,7 @@ class DistributionAggregationData(BaseAggregationData):
104108
:param bounds: the histogram distribution of the values
105109
106110
"""
111+
107112
def __init__(self,
108113
mean_data,
109114
count_data,
@@ -123,13 +128,14 @@ def __init__(self,
123128
bounds = []
124129

125130
if counts_per_bucket is None:
126-
counts_per_bucket = []
127-
bucket_size = len(bounds) + 1
128-
for i in range(bucket_size):
129-
counts_per_bucket.append(0)
131+
counts_per_bucket = [0 for ii in range(len(bounds) + 1)]
132+
elif len(counts_per_bucket) != len(bounds) + 1:
133+
raise ValueError("counts_per_bucket length does not match bounds "
134+
"length")
135+
130136
self._counts_per_bucket = counts_per_bucket
131137
self._bounds = bucket_boundaries.BucketBoundaries(
132-
boundaries=bounds).boundaries
138+
boundaries=bounds).boundaries
133139
bucket = 0
134140
for _ in self.bounds:
135141
bucket = bucket + 1
@@ -207,30 +213,24 @@ def add_sample(self, value, timestamp, attachments):
207213

208214
old_mean = self._mean_data
209215
self._mean_data = self._mean_data + (
210-
(value - self._mean_data) / self._count_data)
216+
(value - self._mean_data) / self._count_data)
211217
self._sum_of_sqd_deviations = self._sum_of_sqd_deviations + (
212-
(value - old_mean) *
213-
(value - self._mean_data))
218+
(value - old_mean) * (value - self._mean_data))
214219

215220
def increment_bucket_count(self, value):
216221
"""Increment the bucket count based on a given value from the user"""
217-
i = 0
218-
incremented = False
219-
for b in self._bounds:
220-
if value < b and not incremented:
221-
self._counts_per_bucket[i] += 1
222-
incremented = True
223-
i += 1
224-
225-
if incremented:
226-
return i
227-
228222
if len(self._bounds) == 0:
229223
self._counts_per_bucket[0] += 1
230-
return i
224+
return 0
231225

232-
self._counts_per_bucket[(len(self._bounds))-1] += 1
233-
return i
226+
for ii, bb in enumerate(self._bounds):
227+
if value < bb:
228+
self._counts_per_bucket[ii] += 1
229+
return ii
230+
else:
231+
last_bucket_index = len(self._bounds)
232+
self._counts_per_bucket[last_bucket_index] += 1
233+
return last_bucket_index
234234

235235

236236
class LastValueAggregationData(BaseAggregationData):
@@ -241,6 +241,7 @@ class LastValueAggregationData(BaseAggregationData):
241241
:param value: represents the current value
242242
243243
"""
244+
244245
def __init__(self, value):
245246
super(LastValueAggregationData, self).__init__(value)
246247
self._value = value
@@ -271,10 +272,7 @@ class Exemplar(object):
271272
:param attachments: the contextual information about the example value.
272273
"""
273274

274-
def __init__(self,
275-
value,
276-
timestamp,
277-
attachments):
275+
def __init__(self, value, timestamp, attachments):
278276
self._value = value
279277

280278
self._timestamp = timestamp

tests/unit/stats/test_aggregation.py

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,92 +12,113 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from datetime import datetime
1516
import unittest
16-
import mock
17+
1718
from opencensus.stats import aggregation as aggregation_module
1819

1920

2021
class TestBaseAggregation(unittest.TestCase):
21-
2222
def test_constructor_defaults(self):
2323
base_aggregation = aggregation_module.BaseAggregation()
2424

25-
self.assertEqual(aggregation_module.Type.NONE, base_aggregation.aggregation_type)
25+
self.assertEqual(aggregation_module.Type.NONE,
26+
base_aggregation.aggregation_type)
2627
self.assertEqual([], base_aggregation.buckets)
2728

2829
def test_constructor_explicit(self):
2930

3031
buckets = ["test"]
3132
base_aggregation = aggregation_module.BaseAggregation(buckets=buckets)
3233

33-
self.assertEqual(aggregation_module.Type.NONE, base_aggregation.aggregation_type)
34+
self.assertEqual(aggregation_module.Type.NONE,
35+
base_aggregation.aggregation_type)
3436
self.assertEqual(["test"], base_aggregation.buckets)
3537

3638

3739
class TestSumAggregation(unittest.TestCase):
38-
3940
def test_constructor_defaults(self):
4041
sum_aggregation = aggregation_module.SumAggregation()
4142

4243
self.assertEqual(0, sum_aggregation.sum.sum_data)
43-
self.assertEqual(aggregation_module.Type.SUM, sum_aggregation.aggregation_type)
44+
self.assertEqual(aggregation_module.Type.SUM,
45+
sum_aggregation.aggregation_type)
4446

4547
def test_constructor_explicit(self):
4648
sum = 1
4749

4850
sum_aggregation = aggregation_module.SumAggregation(sum=sum)
4951

5052
self.assertEqual(1, sum_aggregation.sum.sum_data)
51-
self.assertEqual(aggregation_module.Type.SUM, sum_aggregation.aggregation_type)
53+
self.assertEqual(aggregation_module.Type.SUM,
54+
sum_aggregation.aggregation_type)
5255

5356

5457
class TestCountAggregation(unittest.TestCase):
55-
5658
def test_constructor_defaults(self):
5759
count_aggregation = aggregation_module.CountAggregation()
5860

5961
self.assertEqual(0, count_aggregation.count.count_data)
60-
self.assertEqual(aggregation_module.Type.COUNT, count_aggregation.aggregation_type)
62+
self.assertEqual(aggregation_module.Type.COUNT,
63+
count_aggregation.aggregation_type)
6164

6265
def test_constructor_explicit(self):
6366
count = 4
6467

6568
count_aggregation = aggregation_module.CountAggregation(count=count)
6669

6770
self.assertEqual(4, count_aggregation.count.count_data)
68-
self.assertEqual(aggregation_module.Type.COUNT, count_aggregation.aggregation_type)
71+
self.assertEqual(aggregation_module.Type.COUNT,
72+
count_aggregation.aggregation_type)
6973

7074

7175
class TestLastValueAggregation(unittest.TestCase):
72-
7376
def test_constructor_defaults(self):
7477
last_value_aggregation = aggregation_module.LastValueAggregation()
7578

7679
self.assertEqual(0, last_value_aggregation.value)
77-
self.assertEqual(aggregation_module.Type.LASTVALUE, last_value_aggregation.aggregation_type)
80+
self.assertEqual(aggregation_module.Type.LASTVALUE,
81+
last_value_aggregation.aggregation_type)
7882

7983
def test_constructor_explicit(self):
8084
val = 16
81-
last_value_aggregation = aggregation_module.LastValueAggregation(value=val)
85+
last_value_aggregation = aggregation_module.LastValueAggregation(
86+
value=val)
8287

8388
self.assertEqual(16, last_value_aggregation.value)
84-
self.assertEqual(aggregation_module.Type.LASTVALUE, last_value_aggregation.aggregation_type)
89+
self.assertEqual(aggregation_module.Type.LASTVALUE,
90+
last_value_aggregation.aggregation_type)
8591

8692

8793
class TestDistributionAggregation(unittest.TestCase):
88-
8994
def test_constructor_defaults(self):
9095
distribution_aggregation = aggregation_module.DistributionAggregation()
9196

9297
self.assertEqual([], distribution_aggregation.boundaries.boundaries)
9398
self.assertEqual({}, distribution_aggregation.distribution)
94-
self.assertEqual(aggregation_module.Type.DISTRIBUTION, distribution_aggregation.aggregation_type)
99+
self.assertEqual(aggregation_module.Type.DISTRIBUTION,
100+
distribution_aggregation.aggregation_type)
95101

96102
def test_constructor_explicit(self):
97103
boundaries = ["test"]
98104
distribution = {1: "test"}
99-
distribution_aggregation = aggregation_module.DistributionAggregation(boundaries=boundaries, distribution=distribution)
105+
distribution_aggregation = aggregation_module.DistributionAggregation(
106+
boundaries=boundaries, distribution=distribution)
100107

101-
self.assertEqual(["test"], distribution_aggregation.boundaries.boundaries)
108+
self.assertEqual(["test"],
109+
distribution_aggregation.boundaries.boundaries)
102110
self.assertEqual({1: "test"}, distribution_aggregation.distribution)
103-
self.assertEqual(aggregation_module.Type.DISTRIBUTION, distribution_aggregation.aggregation_type)
111+
self.assertEqual(aggregation_module.Type.DISTRIBUTION,
112+
distribution_aggregation.aggregation_type)
113+
114+
def test_min_max(self):
115+
da = aggregation_module.DistributionAggregation([])
116+
117+
self.assertEqual(da.aggregation_data.min, float('inf'))
118+
self.assertEqual(da.aggregation_data.max, float('-inf'))
119+
120+
for dp in range(-10, 11):
121+
da.aggregation_data.add_sample(dp, datetime(1999, 12, 31), {})
122+
123+
self.assertEqual(da.aggregation_data.min, -10)
124+
self.assertEqual(da.aggregation_data.max, 10)

0 commit comments

Comments
 (0)