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

Proposed by Curtis Caravone
Status: Merged
Approved by: Curtis Caravone
Approved revision: 56
Merged at revision: 54
Proposed branch: lp:~caravone/txstatsd/statsd-timings-consistency
Merge into: lp:txstatsd
Diff against target: 100 lines (+32/-9)
5 files modified
txstatsd/metrics/extendedmetrics.py (+4/-2)
txstatsd/metrics/imetrics.py (+2/-2)
txstatsd/metrics/metrics.py (+9/-4)
txstatsd/metrics/timermetric.py (+1/-1)
txstatsd/tests/test_metrics.py (+16/-0)
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+83645@code.launchpad.net

This proposal supersedes a proposal from 2011-11-26.

Commit message

Added timing consistency (always take seconds but emit milliseconds) to ExtendedMetrics.
Added automatic timing option to ExtendedMetrics and signature of IMetrics timing methods.

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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

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.

Revision history for this message
Sidnei da Silva (sidnei) wrote :

Please use no spaces around the equals sign on function arguments.

Other than that looks good. Once you fix that, please set a commit message in this MP and flip the status to Approved.

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

One thing I wasn't sure about was the expected behavior of the increment/decrement calls. As you can see from the unit tests, the basic Metrics object emits deltas for each increment/decrements, while the ExtendedMetrics version keeps a cumulative delta and emits that. Not sure if it's a bug or just a subtlety of the API.

56. By Curtis Caravone

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'txstatsd/metrics/extendedmetrics.py'
--- txstatsd/metrics/extendedmetrics.py 2011-09-14 12:01:10 +0000
+++ txstatsd/metrics/extendedmetrics.py 2011-11-28 17:18:41 +0000
@@ -39,8 +39,10 @@
39 self._metrics[name] = metric39 self._metrics[name] = metric
40 self._metrics[name].decrement(value)40 self._metrics[name].decrement(value)
4141
42 def timing(self, name, duration, sample_rate=1):42 def timing(self, name, duration=None, sample_rate=1):
43 """Report this sample performed in duration ms."""43 """Report this sample performed in duration seconds."""
44 if duration is None:
45 duration = self.calculate_duration()
44 name = self.fully_qualify_name(name)46 name = self.fully_qualify_name(name)
45 if not name in self._metrics:47 if not name in self._metrics:
46 metric = TimerMetric(self.connection,48 metric = TimerMetric(self.connection,
4749
=== modified file 'txstatsd/metrics/imetrics.py'
--- txstatsd/metrics/imetrics.py 2011-09-09 15:49:55 +0000
+++ txstatsd/metrics/imetrics.py 2011-11-28 17:18:41 +0000
@@ -14,5 +14,5 @@
14 def decrement(name, value=1, sample_rate=1):14 def decrement(name, value=1, sample_rate=1):
15 """Decrement counter C{name} by C{count}."""15 """Decrement counter C{name} by C{count}."""
1616
17 def timing(name, duration, sample_rate=1):17 def timing(name, duration=None, sample_rate=1):
18 """Report that C{name} took C{duration} milliseconds."""18 """Report that C{name} took C{duration} seconds."""
1919
=== modified file 'txstatsd/metrics/metrics.py'
--- txstatsd/metrics/metrics.py 2011-11-25 23:56:31 +0000
+++ txstatsd/metrics/metrics.py 2011-11-28 17:18:41 +0000
@@ -90,14 +90,19 @@
90 """Resets the duration timer for the next call to timing()"""90 """Resets the duration timer for the next call to timing()"""
91 self.last_time = time.time()91 self.last_time = time.time()
9292
93 def timing(self, name, duration = None, sample_rate=1):93 def calculate_duration(self):
94 """Resets the duration timer and returns the elapsed duration"""
95 current_time = time.time()
96 duration = current_time - self.last_time
97 self.last_time = current_time
98 return duration
99
100 def timing(self, name, duration=None, sample_rate=1):
94 """Report that this sample performed in duration seconds.101 """Report that this sample performed in duration seconds.
95 Default duration is the actual elapsed time since102 Default duration is the actual elapsed time since
96 the last call to this method or reset_timing()"""103 the last call to this method or reset_timing()"""
97 if duration is None:104 if duration is None:
98 current_time = time.time()105 duration = self.calculate_duration()
99 duration = current_time - self.last_time
100 self.last_time = current_time
101 name = self.fully_qualify_name(name)106 name = self.fully_qualify_name(name)
102 if not name in self._metrics:107 if not name in self._metrics:
103 metric = Metric(self.connection,108 metric = Metric(self.connection,
104109
=== modified file 'txstatsd/metrics/timermetric.py'
--- txstatsd/metrics/timermetric.py 2011-09-14 12:01:10 +0000
+++ txstatsd/metrics/timermetric.py 2011-11-28 17:18:41 +0000
@@ -30,7 +30,7 @@
3030
31 def mark(self, duration):31 def mark(self, duration):
32 """Report this sample performed in duration (measured in seconds)."""32 """Report this sample performed in duration (measured in seconds)."""
33 self.send("%s|ms" % duration)33 self.send("%s|ms" % (duration * 1000))
3434
3535
36class TimerMetricReporter(object):36class TimerMetricReporter(object):
3737
=== modified file 'txstatsd/tests/test_metrics.py'
--- txstatsd/tests/test_metrics.py 2011-11-25 23:56:31 +0000
+++ txstatsd/tests/test_metrics.py 2011-11-28 17:18:41 +0000
@@ -3,6 +3,7 @@
3import re3import re
4import time4import time
5from unittest import TestCase5from unittest import TestCase
6from txstatsd.metrics.extendedmetrics import ExtendedMetrics
6from txstatsd.metrics.metrics import Metrics7from txstatsd.metrics.metrics import Metrics
78
89
@@ -102,3 +103,18 @@
102 self.assertEqual(self.connection.data,103 self.assertEqual(self.connection.data,
103 'gauge:413|g')104 'gauge:413|g')
104105
106
107class TestExtendedMetrics(TestMetrics):
108 def setUp(self):
109 super(TestExtendedMetrics, self).setUp()
110 self.metrics = ExtendedMetrics(self.connection, 'txstatsd.tests')
111
112 def test_counter(self):
113 """Test the increment and decrement operations."""
114 self.metrics.increment('counter', 18)
115 self.assertEqual(self.connection.data,
116 'txstatsd.tests.counter:18|c')
117 self.metrics.decrement('counter', 9)
118 self.assertEqual(self.connection.data,
119 'txstatsd.tests.counter:9|c')
120

Subscribers

People subscribed via source and target branches