OLD | NEW |
1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import collections | 5 import collections |
6 import logging | 6 import logging |
7 import operator | 7 import operator |
8 import threading | 8 import threading |
9 import time | 9 import time |
10 | 10 |
11 from infra_libs.ts_mon.common import errors | 11 from infra_libs.ts_mon.common import errors |
12 | 12 |
13 | 13 |
14 """A light-weight representation of a set or an incr. | 14 """A light-weight representation of a set or an incr. |
15 | 15 |
16 Args: | 16 Args: |
17 name: The metric name. | 17 name: The metric name. |
18 fields: The normalized field tuple. | 18 fields: The normalized field tuple. |
19 mod_type: Either 'set' or 'incr'. Other values will raise | 19 mod_type: Either 'set' or 'incr'. Other values will raise |
20 UnknownModificationTypeError when it's used. | 20 UnknownModificationTypeError when it's used. |
21 args: (value, enforce_ge) for 'set' or (delta, modify_fn) for 'incr'. | 21 args: (value, enforce_ge) for 'set' or (delta, modify_fn) for 'incr'. |
22 """ # pylint: disable=pointless-string-statement | 22 """ # pylint: disable=pointless-string-statement |
23 Modification = collections.namedtuple( | 23 Modification = collections.namedtuple( |
24 'Modification', ['name', 'fields', 'mod_type', 'args']) | 24 'Modification', ['name', 'fields', 'mod_type', 'args']) |
25 | 25 |
26 | 26 |
27 def combine_modifications(old, new): | |
28 """Combines two modifications into one. | |
29 | |
30 The returned modification will be the result as if the second modification had | |
31 been applied after the first. | |
32 """ | |
33 | |
34 if old is None or new.mod_type == 'set': | |
35 # A 'set' will override any previous value. | |
36 return new | |
37 elif new.mod_type == 'incr': | |
38 # For two 'incr's sum their delta args, for an 'incr' on top of a 'set' add | |
39 # the delta to the set value. | |
40 return Modification( | |
41 old.name, old.fields, old.mod_type, | |
42 (old.args[0] + new.args[0], old.args[1])) | |
43 else: | |
44 raise errors.UnknownModificationTypeError(new.mod_type) | |
45 | |
46 | |
47 class MetricStore(object): | 27 class MetricStore(object): |
48 """A place to store values for each metric. | 28 """A place to store values for each metric. |
49 | 29 |
50 Several methods take "a normalized field tuple". This is a tuple of | 30 Several methods take "a normalized field tuple". This is a tuple of |
51 (key, value) tuples sorted by key. (The reason this is given as a tuple | 31 (key, value) tuples sorted by key. (The reason this is given as a tuple |
52 instead of a dict is because tuples are hashable and can be used as dict keys, | 32 instead of a dict is because tuples are hashable and can be used as dict keys, |
53 dicts can not). | 33 dicts can not). |
54 | 34 |
55 The MetricStore is also responsible for keeping the start_time of each metric. | 35 The MetricStore is also responsible for keeping the start_time of each metric. |
56 This is what goes into the start_timestamp_us field in the MetricsData proto | 36 This is what goes into the start_timestamp_us field in the MetricsData proto |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 | 184 |
205 def reset_for_unittest(self, name=None): | 185 def reset_for_unittest(self, name=None): |
206 if name is not None: | 186 if name is not None: |
207 self._reset(name) | 187 self._reset(name) |
208 else: | 188 else: |
209 for name in self._values.keys(): | 189 for name in self._values.keys(): |
210 self._reset(name) | 190 self._reset(name) |
211 | 191 |
212 def _reset(self, name): | 192 def _reset(self, name): |
213 self._values[name] = (self._start_time(name), {}) | 193 self._values[name] = (self._start_time(name), {}) |
OLD | NEW |