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

Commit a7e7573

Browse files
authored
Fix bug in updating aggregation map. (#253)
* Fix bug in updating aggregation map. * Update unit tests. * Use tag_value_aggregation_data_map instead of tag_value_aggregation_map.
1 parent dc1ac01 commit a7e7573

3 files changed

Lines changed: 102 additions & 67 deletions

File tree

examples/stats/helloworld/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ def main():
6161
# Get aggregated stats and print it to console.
6262
view_data = view_manager.get_view(VIDEO_SIZE_VIEW_NAME)
6363
pprint(vars(view_data))
64-
for k, v in view_data._tag_value_aggregation_map.items():
64+
for k, v in view_data._tag_value_aggregation_data_map.items():
65+
pprint(k)
6566
pprint(vars(v))
66-
pprint(vars(v.aggregation_data))
6767

6868

6969
if __name__ == '__main__':

opencensus/stats/view_data.py

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# limitations under the License.
1414

1515
from datetime import datetime
16-
import logging
16+
import copy
1717

1818

1919
class ViewData(object):
@@ -36,8 +36,7 @@ def __init__(self,
3636
self._view = view
3737
self._start_time = start_time
3838
self._end_time = end_time
39-
self._tag_value_aggregation_map = {}
40-
self._tag_map = {}
39+
self._tag_value_aggregation_data_map = {}
4140

4241
@property
4342
def view(self):
@@ -55,13 +54,9 @@ def end_time(self):
5554
return self._end_time
5655

5756
@property
58-
def tag_value_aggregation_map(self):
57+
def tag_value_aggregation_data_map(self):
5958
"""the current tag value aggregation map in the view data"""
60-
return self._tag_value_aggregation_map
61-
62-
@property
63-
def tag_map(self):
64-
return self._tag_map
59+
return self._tag_value_aggregation_data_map
6560

6661
def start(self):
6762
"""sets the start time for the view data"""
@@ -71,19 +66,6 @@ def end(self):
7166
"""sets the end time for the view data"""
7267
self._end_time = datetime.utcnow().isoformat() + 'Z'
7368

74-
def get_tag_map(self, context):
75-
"""function to return the tag map based on the context"""
76-
if self.tag_map is not None:
77-
if context.map.items() <= self.tag_map.items():
78-
return self.tag_map
79-
else:
80-
tags = self.tag_map
81-
for tag_key, tag_value in context.map.items():
82-
tags[tag_key] = tag_value
83-
return tags
84-
else: # pragma: NO COVER
85-
logging.warning("Tag Map cannot be none")
86-
8769
def get_tag_values(self, tags, columns):
8870
"""function to get the tag values from tags and columns"""
8971
tag_values = []
@@ -99,11 +81,10 @@ def get_tag_values(self, tags, columns):
9981

10082
def record(self, context, value, timestamp):
10183
"""records the view data against context"""
102-
tag_values = self.get_tag_values(tags=self.get_tag_map(context),
84+
tag_values = self.get_tag_values(tags=context.map,
10385
columns=self.view.columns)
10486
tuple_vals = tuple(tag_values)
105-
for val in tuple_vals:
106-
if val not in self.tag_value_aggregation_map:
107-
self.tag_value_aggregation_map[val] = self.view.aggregation
108-
self.tag_value_aggregation_map.get(
109-
val).aggregation_data.add_sample(value)
87+
if tuple_vals not in self.tag_value_aggregation_data_map:
88+
self.tag_value_aggregation_data_map[tuple_vals] = copy.deepcopy(
89+
self.view.aggregation.aggregation_data)
90+
self.tag_value_aggregation_data_map.get(tuple_vals).add_sample(value)

tests/unit/stats/test_view_data.py

Lines changed: 91 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
import unittest
1616
import mock
1717
from datetime import datetime
18+
from opencensus.stats import aggregation as aggregation_module
19+
from opencensus.stats import view as view_module
1820
from opencensus.stats import view_data as view_data_module
1921

2022

@@ -29,7 +31,7 @@ def test_constructor(self):
2931
self.assertEqual(view, view_data.view)
3032
self.assertEqual(start_time, view_data.start_time)
3133
self.assertEqual(end_time, view_data.end_time)
32-
self.assertEqual({}, view_data.tag_value_aggregation_map)
34+
self.assertEqual({}, view_data.tag_value_aggregation_data_map)
3335

3436
def test_start(self):
3537
view = mock.Mock()
@@ -53,29 +55,6 @@ def test_end(self):
5355

5456
self.assertIsNotNone(view_data.end_time)
5557

56-
def test_get_tag_map(self):
57-
view = mock.Mock()
58-
start_time = datetime.utcnow()
59-
end_time = datetime.utcnow()
60-
view_data = view_data_module.ViewData(view=view,
61-
start_time=start_time,
62-
end_time=end_time)
63-
test_context_1 = mock.Mock()
64-
test_context_1.map = {'key1': 'val1'}
65-
context_map_1 = view_data.get_tag_map(context=test_context_1)
66-
self.assertEqual(test_context_1.map, view_data.tag_map)
67-
self.assertEqual(test_context_1.map, context_map_1)
68-
69-
test_context_2 = mock.Mock()
70-
test_context_2.map = {'key1': 'val2'}
71-
context_map_2 = view_data.get_tag_map(context=test_context_2)
72-
self.assertEqual(test_context_2.map, context_map_2)
73-
74-
test_context_3 = mock.Mock()
75-
test_context_3.map = {}
76-
context_map_3 = view_data.get_tag_map(context=test_context_3)
77-
self.assertEqual(test_context_2.map, context_map_3)
78-
7958
def test_get_tag_values(self):
8059
view = mock.Mock()
8160
start_time = datetime.utcnow()
@@ -108,26 +87,101 @@ def test_record(self):
10887
context.map = {'key1': 'val1', 'key2': 'val2'}
10988
time = datetime.utcnow().isoformat() + 'Z'
11089
value = 1
111-
self.assertEqual({}, view_data.tag_value_aggregation_map)
90+
self.assertEqual({}, view_data.tag_value_aggregation_data_map)
11291

11392
view_data.record(context=context, value=value, timestamp=time)
11493
tag_values = view_data.get_tag_values(
115-
tags=view_data.get_tag_map(context=context), columns=view.columns)
94+
tags=context.map, columns=view.columns)
11695
tuple_vals = tuple(tag_values)
11796
self.assertEqual(['val1'], tag_values)
118-
self.assertIsNotNone(view_data.tag_value_aggregation_map)
97+
self.assertIsNotNone(view_data.tag_value_aggregation_data_map)
11998

120-
self.assertTrue('val1' in view_data.tag_value_aggregation_map)
121-
self.assertTrue('val1' in tag_values)
122-
self.assertIsNotNone(view_data.tag_value_aggregation_map['val1'])
123-
self.assertIsNotNone(view_data.tag_value_aggregation_map.get(
124-
'val1').add(value))
99+
self.assertTrue(tuple_vals in view_data.tag_value_aggregation_data_map)
100+
self.assertIsNotNone(view_data.tag_value_aggregation_data_map[tuple_vals])
101+
self.assertIsNotNone(view_data.tag_value_aggregation_data_map.get(
102+
tuple_vals).add(value))
125103

126104
view_data.record(context=context, value=value, timestamp=time)
127105
tag_values.append('val2')
128-
self.assertFalse('val2' in view_data.tag_value_aggregation_map)
129-
view_data.tag_value_aggregation_map['val2'] = view.aggregation
130-
self.assertEqual(view_data.tag_value_aggregation_map.get('val2'),
106+
tuple_vals_2 = tuple(['val2'])
107+
self.assertFalse(tuple_vals_2 in view_data.tag_value_aggregation_data_map)
108+
view_data.tag_value_aggregation_data_map[tuple_vals_2] = view.aggregation
109+
self.assertEqual(view_data.tag_value_aggregation_data_map.get(tuple_vals_2),
131110
view_data.view.aggregation)
132-
self.assertIsNotNone(view_data.tag_value_aggregation_map.get(
133-
'val2').add(value))
111+
self.assertIsNotNone(view_data.tag_value_aggregation_data_map.get(
112+
tuple_vals_2).add(value))
113+
114+
115+
def test_record_with_multi_keys(self):
116+
measure = mock.Mock()
117+
sum_aggregation = aggregation_module.SumAggregation()
118+
view = view_module.View(
119+
"test_view", "description", ['key1', 'key2'], measure, sum_aggregation)
120+
start_time = datetime.utcnow()
121+
end_time = datetime.utcnow()
122+
view_data = view_data_module.ViewData(view=view,
123+
start_time=start_time,
124+
end_time=end_time)
125+
126+
context = mock.Mock()
127+
context.map = {'key1': 'val1', 'key2': 'val2'}
128+
time = datetime.utcnow().isoformat() + 'Z'
129+
value = 1
130+
self.assertEqual({}, view_data.tag_value_aggregation_data_map)
131+
132+
view_data.record(context=context, value=value, timestamp=time)
133+
tag_values = view_data.get_tag_values(
134+
tags=context.map, columns=view.columns)
135+
tuple_vals = tuple(tag_values)
136+
self.assertEqual(['val1', 'val2'], tag_values)
137+
self.assertIsNotNone(view_data.tag_value_aggregation_data_map)
138+
self.assertTrue(tuple_vals in view_data.tag_value_aggregation_data_map)
139+
self.assertIsNotNone(view_data.tag_value_aggregation_data_map[tuple_vals])
140+
sum_data = view_data.tag_value_aggregation_data_map.get(tuple_vals)
141+
self.assertEqual(1, sum_data.sum_data)
142+
143+
context_2 = mock.Mock()
144+
context_2.map = {'key1': 'val3', 'key2': 'val2'}
145+
time_2 = datetime.utcnow().isoformat() + 'Z'
146+
value_2 = 2
147+
view_data.record(context=context_2, value=value_2, timestamp=time_2)
148+
tag_values_2 = view_data.get_tag_values(
149+
tags=context_2.map, columns=view.columns)
150+
tuple_vals_2 = tuple(tag_values_2)
151+
self.assertEqual(['val3', 'val2'], tag_values_2)
152+
self.assertTrue(tuple_vals_2 in view_data.tag_value_aggregation_data_map)
153+
sum_data_2 = view_data.tag_value_aggregation_data_map.get(tuple_vals_2)
154+
self.assertEqual(2, sum_data_2.sum_data)
155+
156+
time_3 = datetime.utcnow().isoformat() + 'Z'
157+
value_3 = 3
158+
# Use the same context {'key1': 'val1', 'key2': 'val2'}.
159+
# Record to entry [(val1, val2), sum=1].
160+
view_data.record(context=context, value=value_3, timestamp=time_3)
161+
self.assertEqual(4, sum_data.sum_data)
162+
# The other entry should remain unchanged.
163+
self.assertEqual(2, sum_data_2.sum_data)
164+
165+
def test_record_with_missing_key_in_context(self):
166+
measure = mock.Mock()
167+
sum_aggregation = aggregation_module.SumAggregation()
168+
view = view_module.View(
169+
"test_view", "description", ['key1', 'key2'], measure, sum_aggregation)
170+
start_time = datetime.utcnow()
171+
end_time = datetime.utcnow()
172+
view_data = view_data_module.ViewData(view=view,
173+
start_time=start_time,
174+
end_time=end_time)
175+
176+
context = mock.Mock()
177+
context.map = {'key1': 'val1', 'key3': 'val3'} # key2 is not in the context.
178+
time = datetime.utcnow().isoformat() + 'Z'
179+
value = 4
180+
view_data.record(context=context, value=value, timestamp=time)
181+
tag_values = view_data.get_tag_values(
182+
tags=context.map, columns=view.columns)
183+
tuple_vals = tuple(tag_values)
184+
self.assertEqual(['val1', None], tag_values)
185+
self.assertTrue(tuple_vals in view_data.tag_value_aggregation_data_map)
186+
sum_data = view_data.tag_value_aggregation_data_map.get(tuple_vals)
187+
self.assertEqual(4, sum_data.sum_data)

0 commit comments

Comments
 (0)