lookout-statsd 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c46d6d96b1086ab6165a4254009cfdd9e3dc7dfa
4
- data.tar.gz: a3d8a60d8abbc04a730e281edf58015d638eb587
3
+ metadata.gz: 09edd7854e30fe524a21a82dd325487e96c83a3b
4
+ data.tar.gz: f7d047db68333414a84ec0bbdce59f0fcde041b1
5
5
  SHA512:
6
- metadata.gz: aad201320598de48a5002b876d0738981784e7acb82216b37e30b1f796aa5886f535fa6935b0de71ba89d7ca3dae7014f125752e8ea90f73fc23ff1cea551e51
7
- data.tar.gz: 5050801e669c08aa9a12d2d6ac5da237eef48996f5af5edcb1b2799060dc40812a1f1f44d26cac613437cb16f81eddc790826af6186dc0ab4b5df4ba81be1f8d
6
+ metadata.gz: 53190cf6ac482c34bde75b18f727f1b74904a5ef1bb837c3299e487bea532d164114a9625c5185254379c6a97ef8fec794d83e3fab89e0a10d4068e87909f0bd
7
+ data.tar.gz: 36d9ce3ed7906da7d80226d9978a03873fe9502744eb234a3a73adbfe81af75ba159694c174566d5b75e3264014161ebbe13d08428dcf9aa1749a7441668bf5a
data/.travis.yml ADDED
@@ -0,0 +1,14 @@
1
+ language: ruby
2
+ rvm:
3
+ - jruby
4
+ - 2.1
5
+ - 1.9.3
6
+ deploy:
7
+ provider: rubygems
8
+ api_key: 701b3f137a894afa3dca9390da8b3afe
9
+ gem: lookout-statsd
10
+ on:
11
+ repo: lookout/statsd
12
+ install:
13
+ - gem install bundler
14
+ - bundle install --jobs=3 --retry=3
data/README.md CHANGED
@@ -11,7 +11,7 @@ In your client code:
11
11
 
12
12
  require 'rubygems'
13
13
  require 'statsd'
14
- STATSD = Statsd::Client.new('localhost',8125)
14
+ STATSD = Statsd::Client.new(:host => 'localhost', :port => 8125)
15
15
 
16
16
  STATSD.increment('some_counter') # basic incrementing
17
17
  STATSD.increment('system.nested_counter', 0.1) # incrementing with sampling (10%)
@@ -22,6 +22,27 @@ In your client code:
22
22
  STATSD.timing('some_job_time', 20) # reporting job that took 20ms
23
23
  STATSD.timing('some_job_time', 20, 0.05) # reporting job that took 20ms with sampling (5% sampling)
24
24
 
25
+ There is an option for reduced DNS lookups, you can specify an additional
26
+ constructor option `:resolve_always` and set it to `false`. By default, the
27
+ client will always resolve the address unless `host` is set to 'localhost' or
28
+ '127.0.0.1'.
29
+
30
+ require 'rubygems'
31
+ require 'statsd'
32
+
33
+ STATSD = Statsd::Client.new(:host => 'specialstats.host.example',
34
+ :port => '8125',
35
+ :resolve_always => false)
36
+
37
+ STATSD.increment('some_counter') # basic incrementing
38
+
39
+ #### Note about thread-safety
40
+
41
+ Since class variables and instance variables are not thread-safe on
42
+ initialization, there is a potential for multiple UDP sockets being opened upon
43
+ if you are using a truly multithreaded ruby, i.e. JRuby. Make sure to take that
44
+ in to account when initializing this library.
45
+
25
46
  Guts
26
47
  ----
27
48
 
data/lib/statsd.rb CHANGED
@@ -15,12 +15,17 @@ module Statsd
15
15
  end
16
16
 
17
17
  class Client
18
- attr_accessor :host, :port, :prefix
18
+ attr_accessor :host, :port, :prefix, :resolve_always, :batch_size
19
19
 
20
20
  def initialize(opts={})
21
21
  @host = opts[:host] || 'localhost'
22
22
  @port = opts[:port] || 8125
23
+ @batch_size = opts[:batch_size] || 10
23
24
  @prefix = opts[:prefix]
25
+ # set resolve_always to true unless localhost or specified
26
+ @resolve_always = opts.fetch(:resolve_always, !is_localhost?)
27
+ @socket = UDPSocket.new
28
+ @send_data = send_method
24
29
  end
25
30
 
26
31
  def host_ip_addr
@@ -77,6 +82,22 @@ module Statsd
77
82
  })
78
83
  end
79
84
 
85
+ # Creates and yields a Batch that can be used to batch instrument reports into
86
+ # larger packets. Batches are sent either when the packet is "full" (defined
87
+ # by batch_size), or when the block completes, whichever is the sooner.
88
+ #
89
+ # Good artists copy https://github.com/reinh/statsd/blob/master/lib/statsd.rb#L410
90
+ #
91
+ # @yield [Batch] a statsd subclass that collects and batches instruments
92
+ # @example Batch two instument operations:
93
+ # $statsd.batch do |batch|
94
+ # batch.increment 'sys.requests'
95
+ # batch.gauge('user.count', User.count)
96
+ # end
97
+ def batch(&block)
98
+ Batch.new(self).easy(&block)
99
+ end
100
+
80
101
  private
81
102
 
82
103
  def send_stats(data, sample_rate = 1)
@@ -98,17 +119,105 @@ module Statsd
98
119
  raise "host and port must be set" unless host && port
99
120
 
100
121
  begin
101
- sock = UDPSocket.new
102
122
  data.each do |d|
103
- sock.send(d, 0, host, port)
123
+ @send_data[d]
104
124
  end
105
125
  rescue # silent but deadly
106
- ensure
107
- sock.close
108
126
  end
109
127
  true
110
128
  end
111
129
 
130
+ def socket_connect!
131
+ @socket.connect(@host, @port)
132
+ end
133
+
134
+ # Curries the send based on if we need to lookup dns every time we send
135
+ def send_method
136
+ if resolve_always
137
+ lambda {|data| @socket.send(data, 0, @host, @port)}
138
+ else
139
+ socket_connect!
140
+ lambda {|data| @socket.send(data, 0)}
141
+ end
142
+ end
143
+
144
+ def is_localhost?
145
+ @host == 'localhost' || @host == '127.0.0.1'
146
+ end
147
+ end
148
+
149
+ # Some more unabashed borrowing: https://github.com/reinh/statsd/blob/master/lib/statsd.rb#L410
150
+ # The big difference between this implementation and reinh's is that we don't support namespaces,
151
+ # and we have a bunch of hacks for introducing prefixes to the namespaces we're acting against.
152
+ # = Batch: A batching statsd proxy
153
+ #
154
+ # @example Batch a set of instruments using Batch and manual flush:
155
+ # $statsd = Statsd.new 'localhost', 8125
156
+ # batch = Statsd::Batch.new($statsd)
157
+ # batch.increment 'garets'
158
+ # batch.timing 'glork', 320
159
+ # batch.gauge 'bork', 100
160
+ # batch.flush
161
+ #
162
+ # Batch is a subclass of Statsd, but with a constructor that proxies to a
163
+ # normal Statsd instance. It has it's own batch_size parameters
164
+ # (that inherit defaults from the supplied Statsd instance). It is recommended
165
+ # that some care is taken if setting very large batch sizes. If the batch size
166
+ # exceeds the allowed packet size for UDP on your network, communication
167
+ # troubles may occur and data will be lost.
168
+ class Batch < Statsd::Client
169
+
170
+ extend Forwardable
171
+ def_delegators :@statsd,
172
+ :host, :host=,
173
+ :port, :port=,
174
+ :prefix,
175
+ :postfix,
176
+ :delimiter, :delimiter=
177
+
178
+ attr_accessor :batch_size
179
+
180
+ # @param [Statsd] requires a configured Statsd instance
181
+ def initialize(statsd)
182
+ @statsd = statsd
183
+ @batch_size = statsd.batch_size
184
+ @backlog = []
185
+ @send_data = send_method
186
+ end
187
+
188
+ # @yields [Batch] yields itself
189
+ #
190
+ # A convenience method to ensure that data is not lost in the event of an
191
+ # exception being thrown. Batches will be transmitted on the parent socket
192
+ # as soon as the batch is full, and when the block finishes.
193
+ def easy
194
+ yield self
195
+ ensure
196
+ flush
197
+ end
198
+
199
+ def flush
200
+ unless @backlog.empty?
201
+ @statsd.send_data @backlog.join("\n")
202
+ @backlog.clear
203
+ end
204
+ end
205
+
206
+ def send_batch_data(message)
207
+ @backlog << message
208
+ if @backlog.size >= @batch_size
209
+ flush
210
+ end
211
+ end
212
+
213
+ def send_method
214
+ lambda { |data|
215
+ @backlog << data
216
+ if @backlog.size >= @batch_size
217
+ flush
218
+ end
219
+ }
220
+ end
112
221
  end
113
222
 
114
223
  module Rails
data/spec/statsd_spec.rb CHANGED
@@ -55,6 +55,48 @@ describe Statsd::Client do
55
55
  c = Statsd::Client.new(:prefix => prefix)
56
56
  c.prefix.should match(prefix)
57
57
  end
58
+
59
+ it 'should accept a :resolve_always keyword argument' do
60
+ lookup = false
61
+ c = Statsd::Client.new(:resolve_always => lookup)
62
+ c.resolve_always.should be(lookup)
63
+ end
64
+
65
+ context 'when :resolve_always is not specified' do
66
+
67
+ context 'when host is localhost or 127.0.0.1' do
68
+ it ':resolve_always should default to false' do
69
+ c = Statsd::Client.new(:host => 'localhost')
70
+ c.resolve_always.should be(false)
71
+ end
72
+ end
73
+
74
+ context 'when host is not local' do
75
+ it ':resolve_always should default to true' do
76
+ c = Statsd::Client.new(:host => 'statsd.example.example')
77
+ c.resolve_always.should be(true)
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+
85
+ describe '#send_stats' do
86
+
87
+ it 'should use cached resolve address when :resolve_always is false' do
88
+ c = Statsd::Client.new(:resolve_always => false)
89
+ sock = c.instance_variable_get(:@socket)
90
+ expect(sock).to receive(:send).with(anything, 0)
91
+ c.increment('foo')
92
+ end
93
+
94
+ it 'should always resolve address when :resolve_always is true' do
95
+ c = Statsd::Client.new(:resolve_always => true)
96
+ sock = c.instance_variable_get(:@socket)
97
+ expect(sock).to receive(:send).with(anything, 0, c.host, c.port)
98
+ c.increment('foo')
99
+ end
58
100
  end
59
101
 
60
102
  describe '#timing' do
@@ -148,4 +190,18 @@ describe Statsd::Client do
148
190
  c.gauge('foo' => 1)
149
191
  end
150
192
  end
151
- end
193
+
194
+ describe '#batch' do
195
+ let(:c) { Statsd::Client.new }
196
+ subject { c.batch { |b| b.increment('foo'); b.increment('bar'); } }
197
+
198
+ it 'should take a block and put increments into a buffer' do
199
+ Statsd::Batch.any_instance do |b|
200
+ b.backlog.should_receive(:<<).exactly.twice
201
+ end
202
+ Statsd::Batch.any_instance.should_receive(:flush).and_call_original
203
+ c.should_receive(:send_data).once
204
+ subject
205
+ end
206
+ end
207
+ end
data/statsd.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "lookout-statsd"
5
- s.version = "1.0.0"
5
+ s.version = "2.0.0"
6
6
  s.platform = Gem::Platform::RUBY
7
7
 
8
8
  s.authors = ['R. Tyler Croy', 'Andrew Coldham', 'Ben VandenBos']
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lookout-statsd
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - R. Tyler Croy
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-07-09 00:00:00.000000000 Z
13
+ date: 2016-05-16 00:00:00.000000000 Z
14
14
  dependencies: []
15
15
  description: A simple ruby statsd client.
16
16
  email:
@@ -20,6 +20,7 @@ extensions: []
20
20
  extra_rdoc_files: []
21
21
  files:
22
22
  - ".gitignore"
23
+ - ".travis.yml"
23
24
  - Gemfile
24
25
  - Guardfile
25
26
  - README.md
@@ -50,7 +51,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
50
51
  version: 1.3.6
51
52
  requirements: []
52
53
  rubyforge_project:
53
- rubygems_version: 2.4.5
54
+ rubygems_version: 2.4.6
54
55
  signing_key:
55
56
  specification_version: 4
56
57
  summary: Ruby statsd client.