Merge lp:~caravone/txstatsd/statsd-timings-consistency into lp:txstatsd

Proposed by Curtis Caravone
Status: Superseded
Proposed branch: lp:~caravone/txstatsd/statsd-timings-consistency
Merge into: lp:txstatsd
Diff against target: 107 lines (+50/-6)
2 files modified
txstatsd/metrics/metrics.py (+15/-3)
txstatsd/tests/test_metrics.py (+35/-3)
To merge this branch: bzr merge lp:~caravone/txstatsd/statsd-timings-consistency
Reviewer Review Type Date Requested Status
Sidnei da Silva Approve
Review via email: mp+83459@code.launchpad.net

This proposal has been superseded by a proposal from 2011-11-28.

Commit message

Changed timing() method to clearly take durations in seconds and emit durations to txstatsd server in milliseconds
Add option for automatic calculation of timing duration

Description of the change

Updated Nov. 28, 2011:

Made sure ExtendedMetrics and IMetrics had the updated timing() logic as well. Added unit tests for ExtendedMetrics.

Changed timing() method to clearly take durations in seconds and emit durations to txstatsd server in milliseconds
Add option for automatic calculation of timing duration

To post a comment you must log in.
Revision history for this message
Sidnei da Silva (sidnei) wrote :

Looks good. Thanks!

One thing I noticed is that we're storing instance-level attributes here and in other metrics. Which means that we can't safely use them from different threads. We need to make sure that we use a per-thread metrics object in client code, or maybe handle the thread-safety here so the client code doesn't have to bother.

review: Approve
Revision history for this message
Curtis Caravone (caravone) wrote :

For the timer code I added, it would probably make sense to use a
thread-bound variable, since timing an activity generally makes the most
sense in the context of a thread. I'll take a look at the other uses of
instance-level attributes used and see what would appear to make the
most sense.

Curtis

On 11/26/11 7:34 AM, Sidnei da Silva wrote:
> Review: Approve
>
> Looks good. Thanks!
>
> One thing I noticed is that we're storing instance-level attributes here and in other metrics. Which means that we can't safely use them from different threads. We need to make sure that we use a per-thread metrics object in client code, or maybe handle the thread-safety here so the client code doesn't have to bother.

56. By Curtis Caravone

Formatting: Removed spaces around '=' in default function arguments

Unmerged revisions

56. By Curtis Caravone

Formatting: Removed spaces around '=' in default function arguments

55. By Curtis Caravone

Added automatic timer support for ExtendedMetrics
Added unit tests for ExtendedMetrics

54. By Curtis Caravone

Fixed timing call in ExtendedMetrics and IMetrics to match Metrics

53. By Curtis Caravone

[r=sidnei] Changed timing() method to clearly take durations in seconds and emit durations to txstatsd server in milliseconds
Add option for automatic calculation of timing duration

52. By Sidnei da Silva

- Someone forgot to lint this.

51. By Lucio Torre

[r=sidnei,theiw] Add pluggable metric kind support to txstatsd.

50. By Ian Wilkinson

[r=sidnei] Resolve the host when instantiating the Twisted client.

49. By Sidnei da Silva

Delay importing the reactor such that other applications get a chance to pick their choice of reactor. [trivial]

48. By Lucio Torre

[r=sidnei] add probabilistic distinct counter

47. By Sidnei da Silva

Delay importing process module and reactor [trivial]

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'txstatsd/metrics/metrics.py'
2--- txstatsd/metrics/metrics.py 2011-11-18 19:45:18 +0000
3+++ txstatsd/metrics/metrics.py 2011-11-26 00:06:23 +0000
4@@ -1,4 +1,5 @@
5
6+import time
7 from txstatsd.metrics.gaugemetric import GaugeMetric
8 from txstatsd.metrics.metermetric import MeterMetric
9 from txstatsd.metrics.distinctmetric import DistinctMetric
10@@ -29,6 +30,7 @@
11 self.connection = connection
12 self.namespace = namespace
13 self._metrics = {}
14+ self.last_time = 0
15
16 def report(self, name, value, metric_type, sample_rate=1):
17 """Report a generic metric.
18@@ -84,15 +86,25 @@
19 self._metrics[name] = metric
20 self._metrics[name].send("%s|c" % -value)
21
22- def timing(self, name, duration, sample_rate=1):
23- """Report this sample performed in duration ms."""
24+ def reset_timing(self):
25+ """Resets the duration timer for the next call to timing()"""
26+ self.last_time = time.time()
27+
28+ def timing(self, name, duration = None, sample_rate=1):
29+ """Report that this sample performed in duration seconds.
30+ Default duration is the actual elapsed time since
31+ the last call to this method or reset_timing()"""
32+ if duration is None:
33+ current_time = time.time()
34+ duration = current_time - self.last_time
35+ self.last_time = current_time
36 name = self.fully_qualify_name(name)
37 if not name in self._metrics:
38 metric = Metric(self.connection,
39 name,
40 sample_rate)
41 self._metrics[name] = metric
42- self._metrics[name].send("%s|ms" % duration)
43+ self._metrics[name].send("%s|ms" % (duration * 1000))
44
45 def distinct(self, name, item):
46 name = self.fully_qualify_name(name)
47
48=== modified file 'txstatsd/tests/test_metrics.py'
49--- txstatsd/tests/test_metrics.py 2011-11-18 19:42:56 +0000
50+++ txstatsd/tests/test_metrics.py 2011-11-26 00:06:23 +0000
51@@ -1,7 +1,8 @@
52 """Tests for the Metrics convenience class."""
53
54+import re
55+import time
56 from unittest import TestCase
57-
58 from txstatsd.metrics.metrics import Metrics
59
60
61@@ -49,9 +50,39 @@
62
63 def test_timing(self):
64 """Test the timing operation."""
65- self.metrics.timing('timing', 101123)
66+ self.metrics.timing('timing', 101.1234)
67 self.assertEqual(self.connection.data,
68- 'txstatsd.tests.timing:101123|ms')
69+ 'txstatsd.tests.timing:101123.4|ms')
70+
71+ def test_timing_automatic(self):
72+ """Test the automatic timing operation with explicit reset"""
73+ start_time = time.time()
74+
75+ self.metrics.reset_timing()
76+ time.sleep(.1)
77+ self.metrics.timing('timing')
78+
79+ elapsed = time.time() - start_time
80+
81+ label, val, units = re.split(":|\|", self.connection.data)
82+ self.assertEqual(label, 'txstatsd.tests.timing')
83+ self.assertEqual(units, 'ms')
84+ self.assertTrue(100 <= float(val) <= elapsed * 1000)
85+
86+ def test_timing_automatic_implicit_reset(self):
87+ """Test the automatic timing operation with implicit reset"""
88+ start_time = time.time()
89+
90+ self.metrics.timing('something_else')
91+ time.sleep(.1)
92+ self.metrics.timing('timing')
93+
94+ elapsed = time.time() - start_time
95+
96+ label, val, units = re.split(":|\|", self.connection.data)
97+ self.assertEqual(label, 'txstatsd.tests.timing')
98+ self.assertEqual(units, 'ms')
99+ self.assertTrue(100 <= float(val) <= elapsed * 1000)
100
101 def test_generic(self):
102 """Test the GenericMetric class."""
103@@ -70,3 +101,4 @@
104 self.metrics.gauge('gauge', 413)
105 self.assertEqual(self.connection.data,
106 'gauge:413|g')
107+

Subscribers

People subscribed via source and target branches