@@ -41,7 +41,7 @@ def __init__(self, sum_data):
4141 super (SumAggregationDataFloat , self ).__init__ (sum_data )
4242 self ._sum_data = sum_data
4343
44- def add_sample (self , value ):
44+ def add_sample (self , value , timestamp = None , attachments = None ):
4545 """Allows the user to add a sample to the Sum Aggregation Data
4646 The value of the sample is then added to the current sum data
4747 """
@@ -64,7 +64,7 @@ def __init__(self, count_data):
6464 super (CountAggregationData , self ).__init__ (count_data )
6565 self ._count_data = count_data
6666
67- def add_sample (self , value ):
67+ def add_sample (self , value , timestamp = None , attachments = None ):
6868 """Adds a sample to the current Count Aggregation Data and adds 1 to
6969 the count data"""
7070 self ._count_data = self ._count_data + 1
@@ -97,6 +97,9 @@ class DistributionAggregationData(BaseAggregationData):
9797 :type counts_per_bucket: list(int)
9898 :param counts_per_bucket: the number of occurrences per bucket
9999
100+ :type exemplars: list(Exemplar)
101+ :param: exemplars: the exemplars associated with histogram buckets.
102+
100103 :type bounds: list(float)
101104 :param bounds: the histogram distribution of the values
102105
@@ -108,7 +111,8 @@ def __init__(self,
108111 max_ ,
109112 sum_of_sqd_deviations ,
110113 counts_per_bucket = None ,
111- bounds = None ):
114+ bounds = None ,
115+ exemplars = None ):
112116 super (DistributionAggregationData , self ).__init__ (mean_data )
113117 self ._mean_data = mean_data
114118 self ._count_data = count_data
@@ -126,6 +130,13 @@ def __init__(self,
126130 self ._counts_per_bucket = counts_per_bucket
127131 self ._bounds = bucket_boundaries .BucketBoundaries (
128132 boundaries = bounds ).boundaries
133+ bucket = 0
134+ for _ in self .bounds :
135+ bucket = bucket + 1
136+
137+ # If there is no histogram, do not record an exemplar
138+ self ._exemplars = \
139+ {bucket : exemplars } if len (self ._bounds ) > 0 else None
129140
130141 @property
131142 def mean_data (self ):
@@ -157,6 +168,11 @@ def counts_per_bucket(self):
157168 """The current counts per bucket for the distribution"""
158169 return self ._counts_per_bucket
159170
171+ @property
172+ def exemplars (self ):
173+ """The current counts per bucket for the distribution"""
174+ return self ._exemplars
175+
160176 @property
161177 def bounds (self ):
162178 """The current bounds for the distribution"""
@@ -174,15 +190,17 @@ def variance(self):
174190 return 0
175191 return self .sum_of_sqd_deviations / (self ._count_data - 1 )
176192
177- def add_sample (self , value ):
193+ def add_sample (self , value , timestamp , attachments ):
178194 """Adding a sample to Distribution Aggregation Data"""
179195 if value < self .min :
180196 self ._min = value
181197 if value > self .max :
182198 self ._max = value
183199 self ._count_data += 1
184- self .increment_bucket_count (value )
200+ bucket = self .increment_bucket_count (value )
185201
202+ if attachments is not None and self .exemplars is not None :
203+ self .exemplars [bucket ] = Exemplar (value , timestamp , attachments )
186204 if self .count_data == 1 :
187205 self ._mean_data = value
188206 return
@@ -196,22 +214,29 @@ def add_sample(self, value):
196214
197215 def increment_bucket_count (self , value ):
198216 """Increment the bucket count based on a given value from the user"""
199- if len (self ._bounds ) == 0 :
200- self ._counts_per_bucket [0 ] += 1
201- return
202-
203217 i = 0
218+ incremented = False
204219 for b in self ._bounds :
205- if value < b :
220+ if value < b and not incremented :
206221 self ._counts_per_bucket [i ] += 1
207- return
222+ incremented = True
208223 i += 1
209224
225+ if incremented :
226+ return i
227+
228+ if len (self ._bounds ) == 0 :
229+ self ._counts_per_bucket [0 ] += 1
230+ return i
231+
210232 self ._counts_per_bucket [(len (self ._bounds ))- 1 ] += 1
211233
234+ return i
235+
212236
213237class LastValueAggregationData (BaseAggregationData ):
214- """LastValue Aggregation Data is the value of aggregated data
238+ """
239+ LastValue Aggregation Data is the value of aggregated data
215240
216241 :type value: long
217242 :param value: represents the current value
@@ -221,15 +246,63 @@ def __init__(self, value):
221246 super (LastValueAggregationData , self ).__init__ (value )
222247 self ._value = value
223248
224- def add_sample (self , value ):
249+ def add_sample (self , value , timestamp = None , attachments = None ):
225250 """Adds a sample to the current
226- LastValue Aggregation Data and overwrite
227- the current recorded value
228- """
251+ LastValue Aggregation Data and overwrite
252+ the current recorded value"""
229253 self ._value = value
230254
231255 @property
232256 def value (self ):
233- """The current value recorded
234- """
257+ """The current value recorded"""
235258 return self ._value
259+
260+
261+ class Exemplar (object ):
262+ """ Exemplar represents an example point that may be used to annotate
263+ aggregated distribution values, associated with a histogram bucket.
264+
265+ :type value: double
266+ :param value: value of the Exemplar point.
267+
268+ :type timestamp: time
269+ :param timestamp: the time that this Exemplar's value was recorded.
270+
271+ :type attachments: dict
272+ :param attachments: the contextual information about the example value.
273+ """
274+
275+ def __init__ (self ,
276+ value ,
277+ timestamp ,
278+ attachments ):
279+ self ._value = value
280+
281+ self ._timestamp = timestamp
282+
283+ if attachments is None :
284+ raise TypeError ('attachments should not be empty' )
285+
286+ for key , value in attachments .items ():
287+ if key is None or not isinstance (key , str ):
288+ raise TypeError ('attachment key should not be '
289+ 'empty and should be a string' )
290+ if value is None or not isinstance (value , str ):
291+ raise TypeError ('attachment value should not be '
292+ 'empty and should be a string' )
293+ self ._attachments = attachments
294+
295+ @property
296+ def value (self ):
297+ """The current value of the Exemplar point"""
298+ return self ._value
299+
300+ @property
301+ def timestamp (self ):
302+ """The time that this Exemplar's value was recorded"""
303+ return self ._timestamp
304+
305+ @property
306+ def attachments (self ):
307+ """The contextual information about the example value"""
308+ return self ._attachments
0 commit comments