Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(128)

Side by Side Diff: client/third_party/infra_libs/ts_mon/common/helpers.py

Issue 2991803002: Update infra_libs to 1.1.15 / 0b44aba87c1c6538439df6d24a409870810747ab (Closed)
Patch Set: fix Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 """Helper classes that make it easier to instrument code for monitoring.""" 5 """Helper classes that make it easier to instrument code for monitoring."""
6 6
7 7
8 from infra_libs.ts_mon.common import metrics
9
10 import time
11
12
8 class ScopedIncrementCounter(object): 13 class ScopedIncrementCounter(object):
9 """Increment a counter when the wrapped code exits. 14 """Increment a counter when the wrapped code exits.
10 15
11 The counter will be given a 'status' = 'success' or 'failure' label whose 16 The counter will be given a 'status' = 'success' or 'failure' label whose
12 value will be set to depending on whether the wrapped code threw an exception. 17 value will be set to depending on whether the wrapped code threw an exception.
13 18
14 Example: 19 Example:
15 20
16 mycounter = Counter('foo/stuff_done') 21 mycounter = Counter('foo/stuff_done')
17 with ScopedIncrementCounter(mycounter): 22 with ScopedIncrementCounter(mycounter):
(...skipping 26 matching lines...) Expand all
44 self.status = None 49 self.status = None
45 return self 50 return self
46 51
47 def __exit__(self, exc_type, exc_value, traceback): 52 def __exit__(self, exc_type, exc_value, traceback):
48 if self.status is None: 53 if self.status is None:
49 if exc_type is None: 54 if exc_type is None:
50 self.status = self.success_value 55 self.status = self.success_value
51 else: 56 else:
52 self.status = self.failure_value 57 self.status = self.failure_value
53 self.counter.increment({self.label: self.status}) 58 self.counter.increment({self.label: self.status})
59
60
61 class ScopedMeasureTime(object):
62 """Report durations metric with status when the wrapped code exits.
63
64 The metric must be CumulativeDistributionMetric with a field to set status.
65 The status field will be set to 'success' or 'failure' depending on whether
66 the wrapped code threw an exception. The status field values can be customized
67 with constructor kwargs or by calling `set_status`.
68
69 A new instance of this class should be constructed each time it is used.
70
71 Example:
72
73 mymetric = CumulativeDistributionMetric(
74 'xxx/durations', 'duration of xxx op'
75 [StringField('status')],
76 bucketer=ts_mon.GeometricBucketer(10**0.04),
77 units=ts_mon.MetricsDataUnits.SECONDS)
78 with ScopedMeasureTime(mymetric):
79 DoStuff()
80
81 To set a custom label and status value:
82
83 mymetric = CumulativeDistributionMetric(
84 'xxx/durations', 'duration of xxx op'
85 [IntegerField('response_code')],
86 bucketer=ts_mon.GeometricBucketer(10**0.04),
87 units=ts_mon.MetricsDataUnits.MILLISECONDS)
88 with ScopedMeasureTime(mymetric, field='response_code') as sd:
89 sd.set_status(404) # This custom status now won't be overwritten
90 # even if exception is raised later.
91 """
92
93 _UNITS_PER_SECOND = {
94 metrics.MetricsDataUnits.SECONDS: 1e0,
95 metrics.MetricsDataUnits.MILLISECONDS: 1e3,
96 metrics.MetricsDataUnits.MICROSECONDS: 1e6,
97 metrics.MetricsDataUnits.NANOSECONDS: 1e9,
98 }
99
100 def __init__(self, metric, field='status', success_value='success',
101 failure_value='failure', time_fn=time.time):
102 assert isinstance(metric, metrics.CumulativeDistributionMetric)
103 assert sum(1 for spec in metric.field_spec if spec.name == field) == 1, (
104 'typo in field name `%s`?' % field)
105 assert metric.units in self._UNITS_PER_SECOND, (
106 'metric\'s units (%s) is not one of %s' %
107 (metric.units, self._UNITS_PER_SECOND.keys()))
108
109 self._metric = metric
110 self._field = field
111 self._units_per_second = self._UNITS_PER_SECOND[metric.units]
112 self._success_value = success_value
113 self._failure_value = failure_value
114 self._status = None
115 self._start_timestamp = None
116 self._time_fn = time_fn
117
118 def set_status(self, status):
119 assert self._start_timestamp is not None, (
120 'set_status must be called only inside with statement')
121 self._status = status
122
123 def set_failure(self):
124 return self.set_status(self._failure_value)
125
126 def __enter__(self):
127 assert self._start_timestamp is None, ('re-use of ScopedMeasureTime '
128 'instances detected')
129 self._start_timestamp = self._time_fn()
130 return self
131
132 def __exit__(self, exc_type, exc_value, traceback):
133 elapsed_seconds = self._time_fn() - self._start_timestamp
134 if self._status is None:
135 if exc_type is None:
136 self._status = self._success_value
137 else:
138 self._status = self._failure_value
139 self._metric.add(elapsed_seconds * self._units_per_second,
140 {self._field: self._status})
OLDNEW
« no previous file with comments | « client/third_party/infra_libs/ts_mon/common/errors.py ('k') | client/third_party/infra_libs/ts_mon/common/http_metrics.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698