afstatsd 0.0.6 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fcd5274479446c117aaebad88da0017217811b42
4
+ data.tar.gz: c51a9ebb07b3a6bdc1a103abf482f8ad70b80ba0
5
+ SHA512:
6
+ metadata.gz: a2bb4716829b8cf60545a28843ac7d5241f7bef16e2df343bbbeb8e1162ec0f63d8b4a3736307302bb0fb00bae1b4e9d0d65e7a38bfc1413af8f65f1a5a10055
7
+ data.tar.gz: 340cc6a81b6c9c35431738e148458596b60fbf8c35fb1ebf7955aa8fab544136794ac3066207c903bccfa7476fb92e562edc8ede9032bf28c983956c2db7151e
@@ -1,10 +1,9 @@
1
1
  require 'afstatsd'
2
2
 
3
- #$statsd = Statsd.new 'statsd_server.my_company.com', 8125, 20
4
-
3
+ #$statsd = Statsd.new 'localhost', 8125, 0, 'udp'
5
4
  $statsd = Statsd.new # use defaults
6
- $statsd.namespace = 'test.ruby'
7
5
 
6
+ $statsd.namespace = 'test.ruby'
8
7
 
9
8
  $statsd.increment 'counter1'
10
9
  $statsd.increment 'counter1'
@@ -13,34 +12,34 @@ $statsd.decrement 'counter1' #counters accumulate
13
12
  $statsd.gauge 'gauge1', 1024
14
13
  $statsd.gauge 'gauge1', 1025
15
14
  $statsd.gauge 'gauge1', 1026
16
- $statsd.gauge 'gauge1', 1027
15
+ $statsd.gauge 'gauge1', 1027
17
16
  $statsd.gauge 'gauge1', 1028 # gauges get overwritten when aggregated
18
17
 
19
- $statsd.time('timing1'){sleep 0.01}
20
- $statsd.time('timing1'){sleep 0.02}
21
- $statsd.time('timing1'){sleep 0.03}
22
- $statsd.time('timing1'){sleep 0.04} # timings get averaged when aggregated
18
+ $statsd.time('timing1'){sleep 0.1}
19
+ $statsd.time('timing1'){sleep 0.2}
20
+ $statsd.time('timing1'){sleep 0.3}
21
+ $statsd.time('timing1'){sleep 0.4} # timings get averaged when aggregated
23
22
 
24
23
 
25
24
  =begin
26
25
 
27
- 100.times do
28
- $statsd.increment 'sampled', 0.1, 'sampled'
26
+ 100.times do
27
+ $statsd.increment 'sampled', 0.1
29
28
  end
30
29
 
31
- $statsd.set 'set1', 1099, "ez"
30
+ $statsd.set 'set1', 1099
32
31
 
33
32
  for i in 10..19 do
34
33
  $statsd.increment "counter#{i}" # create a group of counters
35
- end
34
+ end
36
35
 
37
- 1000.times do
36
+ 1000.times do
38
37
  $statsd.increment 'fast' # don't do this if aggregation is off
39
- end
38
+ end
40
39
 
41
40
  15.times do
42
41
  sleep 2
43
- $statsd.increment 'slow'
42
+ $statsd.increment 'slow'
44
43
  end
45
44
 
46
45
  =end
@@ -50,11 +49,11 @@ end
50
49
  threads = []
51
50
  start = Time.now
52
51
  for i in 0..9 do
53
- threads << Thread.new(i) do |j|
52
+ threads << Thread.new(i) do |j|
54
53
  start = Time.now
55
54
  1000000.times do
56
55
  $statsd.increment 'inthethread'
57
- # sleep(0.01)
56
+ sleep(0.01)
58
57
  end
59
58
  puts "thread #{j} says: I took #{((Time.now - start)*1000).round} ms"
60
59
  end
@@ -7,9 +7,10 @@ require 'afstatsd/statsd_aggregator'
7
7
  require 'monitor'
8
8
  require 'fcntl'
9
9
 
10
- # = Statsd: A Statsd client (https://github.com/etsy/statsd)
10
+ # = Statsd: An AppFirst Statsd client
11
+ # (https://github.com/appfirst/statsd_clients/tree/master/ruby)
11
12
  #
12
- # @example Set up a global Statsd client for a server on localhost:9125,
13
+ # @example Set up a global Statsd client for a server on localhost:9125,
13
14
  # aggregate 20 seconds worth of metrics
14
15
  # $statsd = Statsd.new 'localhost', 8125, 20
15
16
  # @example Send some stats
@@ -43,7 +44,7 @@ class Statsd
43
44
  attr_reader :prefix
44
45
 
45
46
  # a postfix to append to all metrics
46
- attr_reader :postfix
47
+ attr_reader :postfix
47
48
 
48
49
  # count of messages that were dropped due to transmit error
49
50
  attr_reader :dropped
@@ -58,13 +59,13 @@ class Statsd
58
59
 
59
60
  # @param [String] host your statsd host
60
61
  # @param [Integer] port your statsd port
61
- # @param [Integer] interval for aggregatore
62
- def initialize(host = '127.0.0.1', port = 8125, interval = 20)
62
+ # @param [Integer] interval for aggregator
63
+ def initialize(host='127.0.0.1', port=8125, interval=20, transport='mq')
63
64
  self.host, self.port = host, port
64
65
  @prefix = nil
65
66
  @postfix = nil
66
67
  @aggregator = StatsdAggregator.new(interval)
67
- if RUBY_PLATFORM =~ /linux/i
68
+ if RUBY_PLATFORM =~ /linux/i and transport == 'mq'
68
69
  set_transport :mq_transport
69
70
  else
70
71
  set_transport :udp_transport
@@ -134,20 +135,18 @@ class Statsd
134
135
  #
135
136
  # @param [String] stat stat name
136
137
  # @param [Numeric] sample_rate sample rate, 1 for always
137
- # @param [String] optional note (AppFirst extension to StatsD)
138
138
  # @see #count
139
- def increment(stat, sample_rate=1, note="")
140
- count stat, 1, sample_rate, note
139
+ def increment(stat, sample_rate=1)
140
+ count stat, 1, sample_rate
141
141
  end
142
142
 
143
143
  # Sends a decrement (count = -1) for the given stat to the statsd server.
144
144
  #
145
145
  # @param [String] stat stat name
146
146
  # @param [Numeric] sample_rate sample rate, 1 for always
147
- # @param [String] optional note (AppFirst extension to StatsD)
148
147
  # @see #count
149
- def decrement(stat, sample_rate=1, note="")
150
- count stat, -1, sample_rate, note
148
+ def decrement(stat, sample_rate=1)
149
+ count stat, -1, sample_rate
151
150
  end
152
151
 
153
152
  # Sends an arbitrary count for the given stat to the statsd server.
@@ -155,10 +154,9 @@ class Statsd
155
154
  # @param [String] stat stat name
156
155
  # @param [Integer] count count
157
156
  # @param [Numeric] sample_rate sample rate, 1 for always
158
- # @param [String] optional note (AppFirst extension to StatsD)
159
- def count(stat, count, sample_rate=1, note="")
157
+ def count(stat, count, sample_rate=1)
160
158
  if sample_rate == 1 or rand < sample_rate
161
- send_metric StatsdMetrics::CMetric.new(expand_name(stat), count.round, sample_rate, note)
159
+ send_metric StatsdMetrics::CMetric.new(expand_name(stat), count.round, sample_rate)
162
160
  end
163
161
  end
164
162
 
@@ -170,11 +168,10 @@ class Statsd
170
168
  #
171
169
  # @param [String] stat stat name.
172
170
  # @param [Numeric] value gauge value.
173
- # @param [String] optional note (AppFirst extension to StatsD)
174
171
  # @example Report the current user count:
175
172
  # $statsd.gauge('user.count', User.count)
176
- def gauge(stat, value, note="")
177
- send_metric StatsdMetrics::GMetric.new(expand_name(stat), value, note)
173
+ def gauge(stat, value)
174
+ send_metric StatsdMetrics::GMetric.new(expand_name(stat), value)
178
175
  end
179
176
 
180
177
  # Sends an arbitary set value for the given stat to the statsd server.
@@ -186,11 +183,10 @@ class Statsd
186
183
  #
187
184
  # @param [String] stat stat name.
188
185
  # @param [Numeric] value event value.
189
- # @param [String] optional note (AppFirst extension to StatsD)
190
186
  # @example Report a deployment happening:
191
187
  # $statsd.set('deployment', DEPLOYMENT_EVENT_CODE)
192
- def set(stat, value, note="")
193
- send_metric StatsdMetrics::SMetric.new(expand_name(stat), value, note)
188
+ def set(stat, value)
189
+ send_metric StatsdMetrics::SMetric.new(expand_name(stat), value)
194
190
  end
195
191
 
196
192
  # Sends a timing (in ms) for the given stat to the statsd server. The
@@ -201,26 +197,24 @@ class Statsd
201
197
  # @param [String] stat stat name
202
198
  # @param [Integer] ms timing in milliseconds
203
199
  # @param [Numeric] sample_rate sample rate, 1 for always
204
- # @param [String] optional note (AppFirst extension to StatsD)
205
- def timing(stat, ms, sample_rate=1, note="")
200
+ def timing(stat, ms, sample_rate=1)
206
201
  if sample_rate == 1 or rand < sample_rate
207
- send_metric StatsdMetrics::TMetric.new(expand_name(stat), ms.round, sample_rate, note)
208
- end
202
+ send_metric StatsdMetrics::TMetric.new(expand_name(stat), ms.round, sample_rate)
203
+ end
209
204
  end
210
205
 
211
206
  # Reports execution time of the provided block using {#timing}.
212
207
  #
213
208
  # @param [String] stat stat name
214
209
  # @param [Numeric] sample_rate sample rate, 1 for always
215
- # @param [String] optional note (AppFirst extension to StatsD)
216
210
  # @yield The operation to be timed
217
211
  # @see #timing
218
212
  # @example Report the time (in ms) taken to activate an account
219
213
  # $statsd.time('account.activate') { @account.activate! }
220
- def time(stat, sample_rate=1, note="")
214
+ def time(stat, sample_rate=1)
221
215
  start = Time.now
222
216
  result = yield
223
- timing(stat, ((Time.now - start) * 1000).round, sample_rate, note)
217
+ timing(stat, ((Time.now - start) * 1000).round, sample_rate)
224
218
  result
225
219
  end
226
220
 
@@ -230,70 +224,74 @@ class Statsd
230
224
  # All the metric types above funnel to here. We will send or aggregate.
231
225
  if aggregating
232
226
  @aggregator.add metric
233
- else
227
+ else
234
228
  @transport.call(metric)
235
229
  end
236
230
  end
237
231
 
238
232
  def expand_name(name)
239
233
  # Replace Ruby module scoping with '.' and reserved chars (: | @) with underscores.
240
- name = name.to_s.gsub('::', '.').tr(':|@', '_')
234
+ name = name.to_s.gsub('::', '.').tr(':|@', '_')
241
235
  "#{prefix}#{name}#{postfix}"
242
236
  end
243
237
 
244
238
  def udp_transport(metric)
245
239
  if @debugging
246
- puts "socket < #{metric}\n" #debug
247
- end
248
- self.class.logger.debug { "Statsd: #{metric}" } if self.class.logger
249
- socket.send(metric.to_s, 0, @host, @port)
240
+ puts "Sending to UDP -- #{metric.to_s(true)} \n" #debug
241
+ end
242
+ self.class.logger.debug { "Statsd: #{metric.to_s(true)}" } if self.class.logger
243
+ socket.send(metric.to_s(true), 0, @host, @port)
250
244
  rescue => boom
251
- #puts "socket send error"
252
245
  @dropped +=1
253
246
  self.class.logger.debug { "Statsd: #{boom.class} #{boom}" } if self.class.logger
247
+ if @debugging
248
+ puts "UDP: socket send error\n"
249
+ end
254
250
  nil
255
251
  end
256
252
 
257
253
  STATSD_SEVERITY = 3
258
254
  def mq_transport(metric)
259
255
  if @debugging
260
- puts "MQ < #{metric}\n" #debug
261
- end
262
- self.class.logger.debug { "Statsd: #{metric}" } if self.class.logger
263
- if not @mq
256
+ puts "Sending to MQ -- #{metric.to_s} \n" #debug
257
+ end
258
+ self.class.logger.debug { "Statsd: #{metric.to_s}" } if self.class.logger
259
+ if not @mq
264
260
  begin
265
261
  @mq = POSIX_MQ.new("/afcollectorapi", Fcntl::O_WRONLY | Fcntl::O_NONBLOCK)
266
262
  rescue => boom
267
263
  self.class.logger.debug { "Statsd: MQ open error #{boom.class} #{boom}" } if self.class.logger
264
+ if @debugging
265
+ puts "Statsd: MQ open error. Fallback to UDP.\n"
266
+ end
268
267
  # failed to open MQ. Fall back to UPD transport. Note: Current message will be lost.
269
268
  @dropped += 1
270
- # puts "fallback to udp"
271
269
  set_transport :udp_transport
272
270
  return nil
273
- end
271
+ end
274
272
  end
275
273
  begin
276
274
  @mq.send(metric.to_s, STATSD_SEVERITY)
277
275
  rescue => boom
278
276
  # just drop it on the floor
279
277
  @dropped += 1
280
- #puts "MQ send error: #{boom.class} #{boom}"
281
278
  self.class.logger.debug { "Statsd: MQ Send Error#{boom.class} #{boom}" } if self.class.logger
279
+ if @debugging
280
+ puts "Statsd: MQ send error: #{boom.class} #{boom}\n"
281
+ end
282
282
  nil
283
- end
283
+ end
284
284
  end
285
285
 
286
286
  def both_transport(metric)
287
287
  mq_transport(metric)
288
288
  udp_transport(metric)
289
289
  end
290
-
290
+
291
291
  private
292
292
 
293
293
  def socket
294
294
  Thread.current[:statsd_socket] ||= UDPSocket.new
295
295
  end
296
-
297
- end # class Statsd
298
-
299
296
 
297
+ end # class Statsd
@@ -1,19 +1,19 @@
1
1
  # Statsd Aggregator
2
2
  #
3
- # Used to aggregate metrics in a threaded environment. Only one of these
3
+ # Used to aggregate metrics in a threaded environment. Only one of these
4
4
  # should be created, in the main thread.
5
- # For each thread, we create 2 buffers. The thread will be writing to
5
+ # For each thread, we create 2 buffers. The thread will be writing to
6
6
  # one, while the aggregator reads from the other. The aggregator will
7
7
  # control which set is which.
8
-
9
-
10
- class StatsdAggregator
8
+
9
+
10
+ class StatsdAggregator
11
11
  attr_accessor :transport
12
12
 
13
13
  def initialize(interval=20)
14
14
  @interval = interval
15
15
  @timer = nil
16
- @mutex = Mutex.new
16
+ @mutex = Mutex.new
17
17
  @running = false
18
18
  @left_buffers = {} # 2 buffer groups
19
19
  @right_buffers = {} # each buffer group is a hash
@@ -23,10 +23,10 @@
23
23
  # register for at_exit call back, so we can flush our buffers
24
24
  at_exit do
25
25
  if @running
26
- flush_buffers
26
+ flush_buffers
27
27
  swap_buffers
28
28
  flush_buffers
29
- end
29
+ end
30
30
  end
31
31
 
32
32
  # in Rails, under PhusionPassener, we may be spun up in a new process,
@@ -36,8 +36,8 @@
36
36
  if forked
37
37
  Statsd.logger.debug {"PHUSION Forked! pid:#{Process.pid}"} if Statsd.logger
38
38
  self.start(nil, true) if @running
39
- end
40
- end
39
+ end
40
+ end
41
41
  end
42
42
 
43
43
  if RUBY_PLATFORM =~ /linux/i
@@ -58,7 +58,7 @@
58
58
  flush_buffers
59
59
  end
60
60
  end
61
- end
61
+ end
62
62
 
63
63
  def start(transport, force_restart=false)
64
64
  Statsd.logger.debug {"START pid:#{Process.pid}"} if Statsd.logger
@@ -78,29 +78,29 @@
78
78
  @running = true
79
79
  #puts "aggregation started. Interval=#{@interval}"
80
80
  end
81
-
81
+
82
82
  def stop
83
83
  return if not @running # already stopped
84
- flush_buffers
84
+ flush_buffers
85
85
  @timer.kill if @timer
86
86
  @timer = nil
87
87
  @running = false
88
88
  #puts "aggregation stopped"
89
89
  end
90
-
90
+
91
91
  def set_interval(interval)
92
92
  @interval = interval
93
93
  end
94
-
94
+
95
95
  # the following methods are thread safe
96
-
96
+
97
97
  def running
98
98
  @running
99
99
  end
100
100
 
101
101
  # this is the only method that should be used by child threads.
102
102
  def add(metric)
103
- # We should have a write buffer assigned to our thread.
103
+ # We should have a write buffer assigned to our thread.
104
104
  # Create one if not.
105
105
  #Statsd.logger.debug {"ADD pid:#{Process.pid}"} if Statsd.logger
106
106
  unless write_buffer = @wbufs[Thread.current]
@@ -121,13 +121,13 @@
121
121
  end
122
122
  #puts "Thread #{Thread.current}: Added metric: #{metric}"
123
123
  end
124
-
124
+
125
125
  private
126
-
126
+
127
127
  # Next two methods are called at different times during the interval,
128
128
  # so any writes in progress after the swap will have time to complete.
129
129
 
130
- def swap_buffers
130
+ def swap_buffers
131
131
  #Statsd.logger.debug {"SWAP pid:#{Process.pid}"} if Statsd.logger
132
132
  if @rbufs == @left_buffers
133
133
  @rbufs = @right_buffers
@@ -137,33 +137,33 @@
137
137
  @wbufs = @right_buffers
138
138
  end
139
139
  end
140
-
140
+
141
141
  def flush_buffers
142
142
  # Statsd.logger.debug {"FLUSH pid:#{Process.pid}"} if Statsd.logger
143
143
  # Each thread has it's own read buffer. If it's empty, the
144
144
  # thread might be dead. We'll delete it's read buffer.
145
145
  @rbufs.delete_if { |k, rb| rb.empty? }
146
-
147
- # If not empty, aggregate all the data across all the threads,
146
+
147
+ # If not empty, aggregate all the data across all the threads,
148
148
  # then send.
149
149
  send_buffer = {}
150
150
  @rbufs.each_value do |rb|
151
151
  rb.each_value do |metric|
152
152
  if m = send_buffer[metric.name]
153
153
  m.aggregate metric.value
154
- else
154
+ else
155
155
  send_buffer[metric.name] = metric
156
- end
156
+ end
157
157
  end
158
- # once we've aggregated all the metrics from this
159
- # thread, clear out the buffer, but don't remove it.
158
+ # once we've aggregated all the metrics from this
159
+ # thread, clear out the buffer, but don't remove it.
160
160
  rb.clear
161
- end
162
- #puts "nothing to send" if send_buffer.empty?
161
+ end
162
+ #puts "nothing to send" if send_buffer.empty?
163
163
  send_buffer.each_value do |metric|
164
164
  #Statsd.logger.debug {" transporting metric #{metric.to_s}"} if Statsd.logger
165
165
  @transport.call(metric)
166
- end
166
+ end
167
167
  end
168
-
168
+
169
169
  end # class StatsdAggregator
@@ -7,97 +7,105 @@ class Metric
7
7
  # all metrics share these
8
8
  attr_accessor :name
9
9
  attr_accessor :value
10
- attr_accessor :message
10
+
11
+ def to_s(udp=false)
12
+ # Handle differences in upload method if sending via UDP or to AppFirst
13
+ if udp
14
+ _to_udp_s
15
+ else
16
+ _to_af_s
17
+ end
18
+ end
19
+
20
+ def _to_udp_s
21
+ # Should be overridden by child class
22
+ raise NotImplementedError
23
+ end
24
+
25
+ def _to_af_s
26
+ # Return the same value by default
27
+ _to_udp_s
28
+ end
29
+
11
30
  end
12
31
 
13
32
  class CMetric < Metric
14
33
  # Counter
15
- def initialize(name, value, rate=1, msg="")
34
+ def initialize(name, value, rate=1)
16
35
  @name = name
17
36
  @value = value
18
- @message = msg
19
37
  @sample_rate = rate
20
38
  end
21
-
39
+
22
40
  def aggregate(delta)
23
41
  @value += delta #accumulate
24
42
  end
25
-
26
- def to_s
27
- if @sample_rate == 1 then r = "" else r = "|@#{@sample_rate}" end
28
- if @message == ""
29
- m = ""
30
- else
31
- if r == ""
32
- m = "||#{@message}"
33
- else
34
- m = "|#{@message}"
35
- end
36
- end
37
- "#{name}:#{@value}|c#{r}#{m}"
43
+
44
+ def _to_udp_s
45
+ if @sample_rate == 1 then r = "" else r = "|@#{@sample_rate}" end
46
+ "#{name}:#{@value}|c#{r}"
38
47
  end
39
48
  end
40
49
 
41
50
  class GMetric < Metric
42
- # Guage
43
- def initialize(name, value, msg="")
51
+ # Gauge
52
+ def initialize(name, value)
44
53
  @name = name
45
54
  @value = value
46
- @message = msg
47
55
  end
48
-
56
+
49
57
  def aggregate(value)
50
58
  @value = value #overwrite
51
59
  end
52
-
53
- def to_s
54
- if @message == "" then m = "" else m = "|#{@message}" end
55
- "#{name}:#{@value}|g#{m}"
60
+
61
+ def _to_udp_s
62
+ "#{name}:#{@value}|g"
56
63
  end
57
64
 
58
65
  end
59
66
 
60
67
  class TMetric < Metric
61
68
  # Timing
62
- def initialize(name, value, rate=1, msg="")
69
+ def initialize(name, value, rate=1)
63
70
  @name = name
64
- @value = value
65
- @sample_rate = rate
66
- @message = msg
71
+ @value = [value]
67
72
  @count = 1
68
73
  end
69
-
74
+
70
75
  def aggregate(value)
71
- @value += value #average
76
+ # Value is another TMetric @value attribute (Array)
77
+ @value += value
72
78
  @count += 1
73
79
  end
74
-
75
- def to_s
76
- avg = @value / @count
77
- if @message == "" then m = "" else m = "|#{@message}" end
78
- "#{name}:#{avg}|ms#{m}"
80
+
81
+ def _to_udp_s
82
+ sumvals = @value.inject(0) {|sum, i| sum + i }
83
+ avg = sumvals / @count
84
+ "#{name}:#{avg}|ms"
85
+ end
86
+
87
+ def _to_af_s
88
+ vals = @value.join(",")
89
+ "#{name}:#{vals}|ms"
79
90
  end
80
91
 
81
92
  end
82
93
 
83
94
  class SMetric < Metric
84
95
  # Set (per the etsy standard)
85
- def initialize(name, value, msg="")
96
+ def initialize(name, value)
86
97
  @name = name
87
98
  @value = value
88
- @message = msg
89
99
  end
90
-
100
+
91
101
  def aggregate(value)
92
102
  @value = value #overwrite
93
103
  end
94
-
95
- def to_s
96
- if @message == "" then m = "" else m = "|#{@message}" end
97
- "#{name}:#{@value}|s#{m}"
104
+
105
+ def _to_udp_s
106
+ "#{name}:#{@value}|s"
98
107
  end
99
108
 
100
109
  end
101
110
 
102
111
  end #module StatsdMetrics
103
-
metadata CHANGED
@@ -1,18 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: afstatsd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
5
- prerelease:
4
+ version: 1.1.0
6
5
  platform: ruby
7
6
  authors:
7
+ - Mike Okner
8
8
  - Clark Bremer
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-07-23 00:00:00.000000000 Z
12
+ date: 2014-08-26 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: A StatsD library with AppFirst Extensions
15
- email: clark@appfirst.com
15
+ email: michael@appfirst.com
16
16
  executables: []
17
17
  extensions:
18
18
  - ext/mkrf_conf.rb
@@ -23,29 +23,28 @@ files:
23
23
  - lib/afstatsd/statsd_metrics.rb
24
24
  - example/example.rb
25
25
  - ext/mkrf_conf.rb
26
- homepage: http://appfirst.com
26
+ homepage: http://www.appfirst.com/
27
27
  licenses:
28
28
  - APACHE
29
+ metadata: {}
29
30
  post_install_message:
30
31
  rdoc_options: []
31
32
  require_paths:
32
33
  - lib
33
34
  required_ruby_version: !ruby/object:Gem::Requirement
34
- none: false
35
35
  requirements:
36
- - - ! '>='
36
+ - - '>='
37
37
  - !ruby/object:Gem::Version
38
38
  version: '0'
39
39
  required_rubygems_version: !ruby/object:Gem::Requirement
40
- none: false
41
40
  requirements:
42
- - - ! '>='
41
+ - - '>='
43
42
  - !ruby/object:Gem::Version
44
43
  version: '0'
45
44
  requirements: []
46
45
  rubyforge_project:
47
- rubygems_version: 1.8.25
46
+ rubygems_version: 2.0.14
48
47
  signing_key:
49
- specification_version: 3
48
+ specification_version: 4
50
49
  summary: AppFirst StatsD Library
51
50
  test_files: []