Skip to content

Commit e75a74f

Browse files
authored
Expose measured duration on Timer context manager (prometheus#1166)
Assigning the .time() context manager (with ... as t) now yields a Timer whose .duration attribute holds the observed value in seconds after the block exits. This lets callers reuse the measurement (logging, further metrics) without calling default_timer() a second time. Signed-off-by: Lukáš Vokráčko <lukas@vokracko.cz>
1 parent 130a4e8 commit e75a74f

5 files changed

Lines changed: 23 additions & 2 deletions

File tree

docs/content/instrumenting/gauge.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ def process():
108108

109109
with g.time():
110110
pass
111+
112+
with g.time() as t:
113+
pass
114+
print(t.duration) # observed time in seconds.
111115
```
112116

113117
### `set_function(f)`

docs/content/instrumenting/histogram.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ def process():
8686

8787
with h.time():
8888
pass
89+
90+
with h.time() as t:
91+
pass
92+
print(t.duration) # observed time in seconds.
8993
```
9094

9195
## Labels

docs/content/instrumenting/summary.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ def process():
6868

6969
with s.time():
7070
pass
71+
72+
with s.time() as t:
73+
pass
74+
print(t.duration) # observed time in seconds.
7175
```
7276

7377
## Labels

prometheus_client/context_managers.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class Timer:
5555
def __init__(self, metric, callback_name):
5656
self._metric = metric
5757
self._callback_name = callback_name
58+
self.duration = None
5859

5960
def _new_timer(self):
6061
return self.__class__(self._metric, self._callback_name)
@@ -65,9 +66,9 @@ def __enter__(self):
6566

6667
def __exit__(self, typ, value, traceback):
6768
# Time can go backwards.
68-
duration = max(default_timer() - self._start, 0)
69+
self.duration = max(default_timer() - self._start, 0)
6970
callback = getattr(self._metric, self._callback_name)
70-
callback(duration)
71+
callback(self.duration)
7172

7273
def labels(self, *args, **kw):
7374
self._metric = self._metric.labels(*args, **kw)

tests/test_core.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,14 @@ def test_block_decorator_with_label(self):
378378
metric.labels('foo')
379379
self.assertEqual(1, value('s_with_labels_count', {'label1': 'foo'}))
380380

381+
def test_timer_duration_exposed(self):
382+
with self.summary.time() as t:
383+
time.sleep(0.01)
384+
self.assertIsNotNone(t.duration)
385+
self.assertGreater(t.duration, 0)
386+
recorded_sum = self.registry.get_sample_value('s_sum')
387+
self.assertEqual(t.duration, recorded_sum)
388+
381389
def test_timer_not_observable(self):
382390
s = Summary('test', 'help', labelnames=('label',), registry=self.registry)
383391

0 commit comments

Comments
 (0)