jashmenn-statsd-instrument 1.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - ree
5
+ - 1.9.2
6
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+
3
+ group :test do
4
+ gem 'rake'
5
+ end
6
+
7
+ # Specify your gem's dependencies in statsd-instrument.gemspec
8
+ gemspec
9
+
10
+ gem 'SystemTimer', :platform => :mri_18, :require => ''
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Shopify
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,156 @@
1
+ # StatsD client for Ruby apps
2
+
3
+ ![Built on Travis](https://secure.travis-ci.org/Shopify/statsd-instrument.png?branch=master)
4
+
5
+ This is a ruby client for statsd (http://github.com/etsy/statsd). It provides a lightweight way to track and measure metrics in your application.
6
+
7
+ We call out to statsd by sending data over a UDP socket. UDP sockets are fast, but unreliable, there is no guarantee that your data will ever arrive at it's location. In other words, fire and forget. This is perfect for this use case because it means your code doesn't get bogged down trying to log statistics. We send data to statsd several times per request and haven't noticed a performance hit.
8
+
9
+ The fact that all of your stats data may not make it into statsd is no issue. Graphite (the graph database that statsd is built on) will only show you trends in your data. Internally it only keeps enough data to satisfy the levels of granularity we specify. As well as satisfying it's requirement as a fixed size database. We can throw as much data at it as we want it and it will do it's best to show us the trends over time and get rid of the fluff.
10
+
11
+ For Shopify, our retention periods are:
12
+
13
+ 1. 10 seconds of granularity for the last 6 hours
14
+ 2. 60 seconds of granularity for the last week
15
+ 3. 10 minutes of granularity for the last 5 years
16
+
17
+ This is the same as what Etsy uses (mentioned in the README for http://github.com/etsy/statsd).
18
+
19
+ ## Configuration
20
+
21
+ ``` ruby
22
+ StatsD.server = 'statsd.myservice.com:8125'
23
+ StatsD.logger = Rails.logger
24
+ StatsD.mode = :production
25
+ StatsD.prefix = 'my_app' # An optional prefix to be added to each stat.
26
+ StatsD.default_sample_rate = 0.1 # Sample 10% of events. By default all events are reported.
27
+ ```
28
+
29
+ If you set the mode to anything besides production then the library will print its calls to the logger, rather than sending them over the wire.
30
+
31
+ ## StatsD keys
32
+
33
+ StatsD keys look like 'admin.logins.api.success'. Each dot in the key represents a 'folder' in the graphite interface. You can include any data you want in the keys.
34
+
35
+ ## Usage
36
+
37
+ ### StatsD.measure
38
+
39
+ Lets you benchmark how long the execution of a specific method takes.
40
+
41
+ ``` ruby
42
+ # You can pass a key and a ms value
43
+ StatsD.measure('GoogleBase.insert', 2.55)
44
+
45
+ # or more commonly pass a block that calls your code
46
+ StatsD.measure('GoogleBase.insert') do
47
+ GoogleBase.insert(product)
48
+ end
49
+ ```
50
+
51
+ Rather than using this method directly it's more common to use the metaprogramming methods made available.
52
+
53
+ ``` ruby
54
+ GoogleBase.extend StatsD::Instrument
55
+ GoogleBase.statsd_measure :insert, 'GoogleBase.insert'
56
+ ```
57
+
58
+ ### StatsD.increment
59
+
60
+ Lets you increment a key in statsd to keep a count of something. If the specified key doesn't exist it will create it for you.
61
+
62
+ ``` ruby
63
+ # increments default to +1
64
+ StatsD.increment('GoogleBase.insert')
65
+ # you can also specify how much to increment the key by
66
+ StatsD.increment('GoogleBase.insert', 10)
67
+ # you can also specify a sample rate, so only 1/10 of events
68
+ # actually get to statsd. Useful for very high volume data
69
+ StatsD.increment('GoogleBase.insert', 1, 0.1)
70
+ ```
71
+
72
+ Again it's more common to use the metaprogramming methods.
73
+
74
+ ## Metaprogramming Methods
75
+
76
+ As mentioned, it's most common to use the provided metaprogramming methods. This lets you define all of your instrumentation in one file and not litter your code with instrumentation details. You should enable a class for instrumentation by extending it with the `StatsD::Instrument` class.
77
+
78
+ ``` ruby
79
+ GoogleBase.extend StatsD::Instrument
80
+ ```
81
+
82
+ Then use the methods provided below to instrument methods in your class.
83
+
84
+ ### statsd\_count
85
+
86
+ This will increment the given key even if the method doesn't finish (ie. raises).
87
+
88
+ ``` ruby
89
+ GoogleBase.statsd_count :insert, 'GoogleBase.insert'
90
+ ```
91
+
92
+ Note how I used the 'GoogleBase.insert' key above when measuring this method, and I reused here when counting the method calls. StatsD automatically separates these two kinds of stats into namespaces so there won't be a key collision here.
93
+
94
+ ### statsd\_count\_if
95
+
96
+ This will only increment the given key if the method executes successfully.
97
+
98
+ ``` ruby
99
+ GoogleBase.statsd_count_if :insert, 'GoogleBase.insert'
100
+ ```
101
+
102
+ So now, if GoogleBase#insert raises an exception or returns false (ie. result == false), we won't increment the key. If you want to define what success means for a given method you can pass a block that takes the result of the method.
103
+
104
+ ``` ruby
105
+ GoogleBase.statsd_count_if :insert, 'GoogleBase.insert' do |response|
106
+ response.code == 200
107
+ end
108
+ ```
109
+
110
+ In the above example we will only increment the key in statsd if the result of the block returns true. So the method is returning a Net::HTTP response and we're checking the status code.
111
+
112
+ ### statsd\_count\_success
113
+
114
+ Similar to statsd_count_if, except this will increment one key in the case of success and another key in the case of failure.
115
+
116
+ ``` ruby
117
+ GoogleBase.statsd_count_success :insert, 'GoogleBase.insert'
118
+ ```
119
+
120
+ So if this method fails execution (raises or returns false) we'll increment the failure key ('GoogleBase.insert.failure'), otherwise we'll increment the success key ('GoogleBase.insert.success'). Notice that we're modifying the given key before sending it to statsd.
121
+
122
+ Again you can pass a block to define what success means.
123
+
124
+ ``` ruby
125
+ GoogleBase.statsd_count_success :insert, 'GoogleBase.insert' do |response|
126
+ response.code == 200
127
+ end
128
+ ```
129
+
130
+ ### Instrumenting Class Methods
131
+
132
+ You can instrument class methods, just like instance methods, using the metaprogramming methods. You simply have to configure the instrumentation on the singleton class of the Class you want to instrument.
133
+
134
+ ```ruby
135
+ AWS::S3::Base.singleton_class.extend StatsD::Instrument
136
+ AWS::S3::Base.singleton_class.statsd_measure :request, 'S3.request'
137
+ ```
138
+
139
+ ## Reliance on DNS
140
+ Out of the box StatsD is set up to be unidirectional fire-and-forget over UDP. Configuring the StatsD host to be a non-ip will trigger a DNS lookup (ie synchronous round trip network call) for each metric sent. This can be particularly problematic in clouds that have a shared DNS infrastructure such as AWS.
141
+
142
+ ### Common Workarounds
143
+ 1. Using an IP avoids the DNS lookup but generally requires an application deploy to change.
144
+ 2. Hardcoding the DNS/IP pair in /etc/hosts allows the IP to change without redeploying your application but fails to scale as the number of servers increases.
145
+ 3. Installing caching software such as nscd that uses the DNS TTL avoids most DNS lookups but makes the exact moment of change indeterminate.
146
+
147
+ ## Compatibility
148
+
149
+ Tested on:
150
+
151
+ * Ruby 1.8.7
152
+ * Ruby Enterprise Edition 1.8.7
153
+ * Ruby 1.9.2
154
+ * Ruby 1.9.3
155
+
156
+ Ruby 1.9 compatibility is planned for the long term. Your mileage may vary with other Ruby environments.
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new('test') do |t|
5
+ t.ruby_opts << '-rubygems'
6
+ t.libs << 'lib'
7
+ t.test_files = FileList['test/*.rb']
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1 @@
1
+ require 'statsd/instrument'
@@ -0,0 +1,157 @@
1
+ require 'socket'
2
+ require 'benchmark'
3
+ require 'timeout'
4
+
5
+ class << Benchmark
6
+ def ms
7
+ 1000 * realtime { yield }
8
+ end
9
+ end
10
+
11
+
12
+ module StatsD
13
+ class << self
14
+ attr_accessor :host, :port, :mode, :logger, :enabled, :default_sample_rate,
15
+ :prefix
16
+ end
17
+ self.enabled = true
18
+ self.default_sample_rate = 1
19
+
20
+ TimeoutClass = defined?(::SystemTimer) ? ::SystemTimer : ::Timeout
21
+
22
+ # StatsD.server = 'localhost:1234'
23
+ def self.server=(conn)
24
+ self.host, port = conn.split(':')
25
+ self.port = port.to_i
26
+ end
27
+
28
+ module Instrument
29
+ def statsd_measure(method, name)
30
+ add_to_method(method, name, :measure) do |old_method, new_method, metric_name, *args|
31
+ define_method(new_method) do |*args|
32
+ StatsD.measure(metric_name) { send(old_method, *args) }
33
+ end
34
+ end
35
+ end
36
+
37
+ def statsd_count_success(method, name)
38
+ add_to_method(method, name, :count_success) do |old_method, new_method, metric_name|
39
+ define_method(new_method) do |*args|
40
+ begin
41
+ truthiness = result = send(old_method, *args)
42
+ rescue
43
+ truthiness = false
44
+ raise
45
+ else
46
+ truthiness = (yield(result) rescue false) if block_given?
47
+ result
48
+ ensure
49
+ StatsD.increment("#{metric_name}." + (truthiness == false ? 'failure' : 'success'))
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ def statsd_count_if(method, name)
56
+ add_to_method(method, name, :count_if) do |old_method, new_method, metric_name|
57
+ define_method(new_method) do |*args|
58
+ begin
59
+ truthiness = result = send(old_method, *args)
60
+ rescue
61
+ truthiness = false
62
+ raise
63
+ else
64
+ truthiness = (yield(result) rescue false) if block_given?
65
+ result
66
+ ensure
67
+ StatsD.increment(metric_name) if truthiness
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ def statsd_count(method, name)
74
+ add_to_method(method, name, :count) do |old_method, new_method, metric_name|
75
+ define_method(new_method) do |*args|
76
+ StatsD.increment(metric_name)
77
+ send(old_method, *args)
78
+ end
79
+ end
80
+ end
81
+
82
+ private
83
+ def add_to_method(method, name, action, &block)
84
+ metric_name = name
85
+
86
+ method_name_without_statsd = :"#{method}_for_#{action}_on_#{self.name}_without_#{name}"
87
+ # raw_ssl_request_for_measure_on_FedEx_without_ActiveMerchant.Shipping.#{self.class.name}.ssl_request
88
+
89
+ method_name_with_statsd = :"#{method}_for_#{action}_on_#{self.name}_with_#{name}"
90
+ # raw_ssl_request_for_measure_on_FedEx_with_ActiveMerchant.Shipping.#{self.class.name}.ssl_request
91
+
92
+ raise ArgumentError, "already instrumented #{method} for #{self.name}" if method_defined? method_name_without_statsd
93
+ raise ArgumentError, "could not find method #{method} for #{self.name}" unless method_defined?(method) || private_method_defined?(method)
94
+
95
+ alias_method method_name_without_statsd, method
96
+ yield method_name_without_statsd, method_name_with_statsd, metric_name
97
+ alias_method method, method_name_with_statsd
98
+ end
99
+ end
100
+
101
+ # glork:320|ms
102
+ def self.measure(key, milli = nil)
103
+ result = nil
104
+ ms = milli || Benchmark.ms do
105
+ result = yield
106
+ end
107
+
108
+ write(key, ms, :ms)
109
+ result
110
+ end
111
+
112
+ # gorets:1|c
113
+ def self.increment(key, delta = 1, sample_rate = default_sample_rate)
114
+ write(key, delta, :incr, sample_rate)
115
+ end
116
+
117
+ # gerbals:30|g
118
+ def self.gauge(key, amount)
119
+ write(key, amount, :gauge)
120
+ end
121
+
122
+ private
123
+
124
+ def self.socket
125
+ @socket ||= UDPSocket.new
126
+ end
127
+
128
+ def self.write(k,v,op, sample_rate = default_sample_rate)
129
+ return unless enabled
130
+ return if sample_rate < 1 && rand > sample_rate
131
+
132
+ command = "#{self.prefix + '.' if self.prefix}#{k}:#{v}"
133
+ case op
134
+ when :incr
135
+ command << '|c'
136
+ when :ms
137
+ command << '|ms'
138
+ when :gauge
139
+ command << '|g'
140
+ end
141
+
142
+ command << "|@#{sample_rate}" if sample_rate < 1
143
+
144
+ if mode.to_s == 'production'
145
+ socket_wrapper { socket.send(command, 0, host, port) }
146
+ else
147
+ logger.info "[StatsD] #{command}"
148
+ end
149
+ end
150
+
151
+ def self.socket_wrapper(options = {})
152
+ TimeoutClass.timeout(options.fetch(:timeout, 0.1)) { yield }
153
+ rescue Timeout::Error, SocketError, IOError, SystemCallError => e
154
+ logger.error e
155
+ end
156
+ end
157
+
@@ -0,0 +1,15 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "jashmenn-statsd-instrument"
3
+ s.version = '1.1.3'
4
+ s.authors = ["Jesse Storimer"]
5
+ s.email = ["jesse@shopify.com"]
6
+ s.homepage = "http://github.com/shopify/statsd-instrument"
7
+
8
+ s.summary = %q{A StatsD client for Ruby apps}
9
+ s.description = %q{A StatsD client for Ruby apps. Provides metaprogramming methods to inject StatsD instrumentation into your code.}
10
+
11
+ s.files = `git ls-files`.split("\n")
12
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
13
+
14
+ s.add_development_dependency 'mocha'
15
+ end
@@ -0,0 +1,230 @@
1
+ # Allow testing with the SystemTimer gem on 1.8
2
+ if RUBY_VERSION =~ /^1.8/
3
+ puts "Loading SystemTimer gem"
4
+ require 'system_timer'
5
+ end
6
+
7
+ require 'statsd-instrument'
8
+ require 'test/unit'
9
+ require 'mocha'
10
+ require 'logger'
11
+
12
+ StatsD.logger = Logger.new('/dev/null')
13
+
14
+ module ActiveMerchant; end
15
+ class ActiveMerchant::Base
16
+ def ssl_post(arg)
17
+ if arg
18
+ 'OK'
19
+ else
20
+ raise 'Not OK'
21
+ end
22
+ end
23
+ end
24
+
25
+ class ActiveMerchant::Gateway < ActiveMerchant::Base
26
+ def purchase(arg)
27
+ ssl_post(arg)
28
+ true
29
+ rescue
30
+ false
31
+ end
32
+
33
+ def self.sync
34
+ true
35
+ end
36
+
37
+ def self.singleton_class
38
+ class << self; self; end
39
+ end
40
+ end
41
+
42
+ class ActiveMerchant::UniqueGateway < ActiveMerchant::Base
43
+ def ssl_post(arg)
44
+ {:success => arg}
45
+ end
46
+
47
+ def purchase(arg)
48
+ ssl_post(arg)
49
+ end
50
+ end
51
+
52
+ ActiveMerchant::Base.extend StatsD::Instrument
53
+
54
+ class StatsDTest < Test::Unit::TestCase
55
+ def setup
56
+ StatsD.mode = nil
57
+ StatsD.stubs(:increment)
58
+ end
59
+
60
+ def test_statsd_count_if
61
+ ActiveMerchant::Gateway.statsd_count_if :ssl_post, 'ActiveMerchant.Gateway.if'
62
+
63
+ StatsD.expects(:increment).with(includes('if')).once
64
+ ActiveMerchant::Gateway.new.purchase(true)
65
+ ActiveMerchant::Gateway.new.purchase(false)
66
+ end
67
+
68
+ def test_statsd_count_if_with_block
69
+ ActiveMerchant::UniqueGateway.statsd_count_if :ssl_post, 'ActiveMerchant.Gateway.block' do |result|
70
+ result[:success]
71
+ end
72
+
73
+ StatsD.expects(:increment).with(includes('block')).once
74
+ ActiveMerchant::UniqueGateway.new.purchase(true)
75
+ ActiveMerchant::UniqueGateway.new.purchase(false)
76
+ end
77
+
78
+ def test_statsd_count_success
79
+ ActiveMerchant::Gateway.statsd_count_success :ssl_post, 'ActiveMerchant.Gateway'
80
+
81
+ StatsD.expects(:increment).with(includes('success'))
82
+ ActiveMerchant::Gateway.new.purchase(true)
83
+
84
+ StatsD.expects(:increment).with(includes('failure'))
85
+ ActiveMerchant::Gateway.new.purchase(false)
86
+ end
87
+
88
+ def test_statsd_count_success_with_block
89
+ ActiveMerchant::UniqueGateway.statsd_count_success :ssl_post, 'ActiveMerchant.Gateway' do |result|
90
+ result[:success]
91
+ end
92
+
93
+ StatsD.expects(:increment).with(includes('success'))
94
+ ActiveMerchant::UniqueGateway.new.purchase(true)
95
+
96
+ StatsD.expects(:increment).with(includes('failure'))
97
+ ActiveMerchant::UniqueGateway.new.purchase(false)
98
+ end
99
+
100
+ def test_statsd_count
101
+ ActiveMerchant::Gateway.statsd_count :ssl_post, 'ActiveMerchant.Gateway.ssl_post'
102
+
103
+ StatsD.expects(:increment).with(includes('ssl_post'))
104
+ ActiveMerchant::Gateway.new.purchase(true)
105
+ end
106
+
107
+ def test_statsd_measure
108
+ ActiveMerchant::UniqueGateway.statsd_measure :ssl_post, 'ActiveMerchant.Gateway.ssl_post'
109
+
110
+ StatsD.expects(:write).with('ActiveMerchant.Gateway.ssl_post', is_a(Float), :ms).returns({:success => true})
111
+ ActiveMerchant::UniqueGateway.new.purchase(true)
112
+ end
113
+
114
+ def test_instrumenting_class_method
115
+ ActiveMerchant::Gateway.singleton_class.extend StatsD::Instrument
116
+ ActiveMerchant::Gateway.singleton_class.statsd_count :sync, 'ActiveMerchant.Gateway.sync'
117
+
118
+ StatsD.expects(:increment).with(includes('sync'))
119
+ ActiveMerchant::Gateway.sync
120
+ end
121
+
122
+ def test_count_with_sampling
123
+ StatsD.unstub(:increment)
124
+ StatsD.stubs(:rand).returns(0.6)
125
+ StatsD.logger.expects(:info).never
126
+
127
+ StatsD.increment('sampling.foo.bar', 1, 0.1)
128
+ end
129
+
130
+ def test_count_with_successful_sample
131
+ StatsD.unstub(:increment)
132
+ StatsD.stubs(:rand).returns(0.01)
133
+ StatsD.logger.expects(:info).once.with do |string|
134
+ string.include?('@0.1')
135
+ end
136
+
137
+ StatsD.increment('sampling.foo.bar', 1, 0.1)
138
+ end
139
+
140
+ def test_production_mode_should_use_udp_socket
141
+ StatsD.unstub(:increment)
142
+
143
+ StatsD.mode = :production
144
+ StatsD.server = 'localhost:123'
145
+ UDPSocket.any_instance.expects(:send)
146
+
147
+ StatsD.increment('fooz')
148
+ StatsD.mode = :test
149
+ end
150
+
151
+ def test_should_not_write_when_disabled
152
+ StatsD.enabled = false
153
+ StatsD.expects(:logger).never
154
+ StatsD.increment('fooz')
155
+ StatsD.enabled = true
156
+ end
157
+
158
+ def test_statsd_mode
159
+ StatsD.unstub(:increment)
160
+ StatsD.logger.expects(:info).once
161
+ StatsD.expects(:socket_wrapper).twice
162
+ StatsD.mode = :foo
163
+ StatsD.increment('foo')
164
+ StatsD.mode = :production
165
+ StatsD.increment('foo')
166
+ StatsD.mode = 'production'
167
+ StatsD.increment('foo')
168
+ end
169
+
170
+ def test_statsd_prefix
171
+ StatsD.unstub(:increment)
172
+ StatsD.prefix = 'my_app'
173
+ StatsD.logger.expects(:info).once.with do |string|
174
+ string.include?('my_app.foo')
175
+ end
176
+ StatsD.logger.expects(:info).once.with do |string|
177
+ string.include?('food')
178
+ end
179
+ StatsD.increment('foo')
180
+ StatsD.prefix = nil
181
+ StatsD.increment('food')
182
+ end
183
+
184
+ def test_statsd_measure_with_explicit_value
185
+ StatsD.expects(:write).with('values.foobar', 42, :ms)
186
+
187
+ StatsD.measure('values.foobar', 42)
188
+ end
189
+
190
+ def test_socket_error_should_not_raise
191
+ StatsD.mode = :production
192
+ UDPSocket.any_instance.expects(:send).raises(SocketError)
193
+ StatsD.measure('values.foobar', 42)
194
+ StatsD.mode = :test
195
+ end
196
+
197
+ def test_timeout_error_should_not_raise
198
+ StatsD.mode = :production
199
+ UDPSocket.any_instance.expects(:send).raises(Timeout::Error)
200
+ StatsD.measure('values.foobar', 42)
201
+ StatsD.mode = :test
202
+ end
203
+
204
+ def test_system_call_error_should_not_raise
205
+ StatsD.mode = :production
206
+ UDPSocket.any_instance.expects(:send).raises(Errno::ETIMEDOUT)
207
+ StatsD.measure('values.foobar', 42)
208
+ StatsD.mode = :test
209
+ end
210
+
211
+ def test_io_error_should_not_raise
212
+ StatsD.mode = :production
213
+ UDPSocket.any_instance.expects(:send).raises(IOError)
214
+ StatsD.measure('values.foobar', 42)
215
+ StatsD.mode = :test
216
+ end
217
+
218
+ def test_long_request_should_timeout
219
+ StatsD.mode = :production
220
+ UDPSocket.any_instance.expects(:send).yields do
221
+ begin
222
+ Timeout.timeout(0.5) { sleep 1 }
223
+ rescue Timeout::Error
224
+ raise "Allowed long running request"
225
+ end
226
+ end
227
+ StatsD.measure('values.foobar', 42)
228
+ StatsD.mode = :test
229
+ end
230
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jashmenn-statsd-instrument
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 1
8
+ - 3
9
+ version: 1.1.3
10
+ platform: ruby
11
+ authors:
12
+ - Jesse Storimer
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2012-04-05 00:00:00 -07:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: mocha
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :development
31
+ version_requirements: *id001
32
+ description: A StatsD client for Ruby apps. Provides metaprogramming methods to inject StatsD instrumentation into your code.
33
+ email:
34
+ - jesse@shopify.com
35
+ executables: []
36
+
37
+ extensions: []
38
+
39
+ extra_rdoc_files: []
40
+
41
+ files:
42
+ - .gitignore
43
+ - .travis.yml
44
+ - Gemfile
45
+ - LICENSE
46
+ - README.md
47
+ - Rakefile
48
+ - lib/statsd-instrument.rb
49
+ - lib/statsd/instrument.rb
50
+ - statsd-instrument.gemspec
51
+ - test/statsd-instrument_test.rb
52
+ has_rdoc: true
53
+ homepage: http://github.com/shopify/statsd-instrument
54
+ licenses: []
55
+
56
+ post_install_message:
57
+ rdoc_options: []
58
+
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ segments:
66
+ - 0
67
+ version: "0"
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ requirements: []
76
+
77
+ rubyforge_project:
78
+ rubygems_version: 1.3.6
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: A StatsD client for Ruby apps
82
+ test_files:
83
+ - test/statsd-instrument_test.rb