afstatsd 0.0.6 → 1.1.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.
@@ -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: []