dogstatsd-ruby 3.3.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -0
  3. data/lib/datadog/statsd.rb +236 -176
  4. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 046a0af9f230451c91fdeb9ae128c550b1c20623fa017d326e63a2f053f7cc9a
4
- data.tar.gz: e2ba838497de521e89d386645a0228f819fdd03c28acc05a4789aa7f8d979de8
3
+ metadata.gz: 6d2b1b9e7ec2a48c5305f6acda103d0b7a09787801dd899a38fb665f5389e4f3
4
+ data.tar.gz: 3d974fffb4ace3bc248e69dcdaabb4c556e6783a25d65af98cb65bdccafc52ee
5
5
  SHA512:
6
- metadata.gz: f2048376477bd1af31a63b75d17638df999c9f6341f967b2c826177add2a13831a54a72729e2a5c62aa09fa4aca6dccbaba308c79d9adcd470808d3bb80cde59
7
- data.tar.gz: 2e0ac5fc90f8a2359f35a754034bb6474c1169ac8c8f3301257555553e1aca4f708cecd4d9245ff835cbe4396561a89d3bd3700ef6cea6c92c343a1e41ca2055
6
+ metadata.gz: 16c82cb62bfd324d5e1dc1c6293fa121b92bd0c88d00474210c5da67f2cb07ae350cc0b717b15739c7a6f09e9021323ba348cec70ec2d0ac66a362f15f81007b
7
+ data.tar.gz: 6e82cef56d746ecf7b10890d397e313c143611b18b4ae65db67eb2f252cb27acacb45de03f6447b7b4ebb1666209806d6b048fb2857c5c8790f1f6729f4ae806
data/README.md CHANGED
@@ -49,6 +49,11 @@ end
49
49
 
50
50
  # Tag a metric.
51
51
  statsd.histogram('query.time', 10, :tags => ["version:1"])
52
+
53
+ # Auto-close socket after end of block
54
+ Datadog::Statsd.open('localhost', 8125) do |s|
55
+ s.increment('page.views')
56
+ end
52
57
  ```
53
58
 
54
59
  You can also post events to your stream. You can tag them, set priority and even aggregate them with other events.
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'socket'
2
3
 
3
4
  # = Datadog::Statsd: A DogStatsd client (https://www.datadoghq.com)
@@ -15,12 +16,137 @@ require 'socket'
15
16
  # statsd = Datadog::Statsd.new 'localhost', 8125, :namespace => 'account'
16
17
  # statsd.increment 'activate'
17
18
  # @example Create a statsd client with global tags
18
- # statsd = Datadog::Statsd.new 'localhost', 8125, :tags => 'tag1:true'
19
+ # statsd = Datadog::Statsd.new 'localhost', 8125, tags: 'tag1:true'
19
20
  module Datadog
20
21
  class Statsd
21
22
 
22
- DEFAULT_HOST = '127.0.0.1'
23
- DEFAULT_PORT = 8125
23
+ class Connection
24
+ DEFAULT_HOST = '127.0.0.1'
25
+ DEFAULT_PORT = 8125
26
+
27
+ # StatsD host. Defaults to 127.0.0.1.
28
+ attr_reader :host
29
+
30
+ # StatsD port. Defaults to 8125.
31
+ attr_reader :port
32
+
33
+ # DogStatsd unix socket path. Not used by default.
34
+ attr_reader :socket_path
35
+
36
+ def initialize(host, port, socket_path, logger)
37
+ @host = host || DEFAULT_HOST
38
+ @port = port || DEFAULT_PORT
39
+ @socket_path = socket_path
40
+ @logger = logger
41
+ end
42
+
43
+ def write(message)
44
+ @logger.debug { "Statsd: #{message}" } if @logger
45
+ if @socket_path.nil?
46
+ socket.send(message, 0)
47
+ else
48
+ socket.sendmsg_nonblock(message)
49
+ end
50
+ rescue StandardError => boom
51
+ # Give up on this socket if it looks like it is bad
52
+ bad_socket = !@socket_path.nil? && (
53
+ boom.is_a?(Errno::ECONNREFUSED) ||
54
+ boom.is_a?(Errno::ECONNRESET) ||
55
+ boom.is_a?(Errno::ENOENT)
56
+ )
57
+ if bad_socket
58
+ @socket = nil
59
+ return
60
+ end
61
+
62
+ # Try once to reconnect if the socket has been closed
63
+ retries ||= 1
64
+ if retries <= 1 && boom.is_a?(IOError) && boom.message =~ /closed stream/i
65
+ retries += 1
66
+ begin
67
+ @socket = connect
68
+ retry
69
+ rescue StandardError => e
70
+ boom = e
71
+ end
72
+ end
73
+
74
+ @logger.error { "Statsd: #{boom.class} #{boom}" } if @logger
75
+ nil
76
+ end
77
+
78
+ # Close the underlying socket
79
+ def close
80
+ @socket && @socket.close
81
+ end
82
+
83
+ private
84
+
85
+ def socket
86
+ @socket ||= connect
87
+ end
88
+
89
+ def connect
90
+ if @socket_path.nil?
91
+ socket = UDPSocket.new
92
+ socket.connect(@host, @port)
93
+ else
94
+ socket = Socket.new(Socket::AF_UNIX, Socket::SOCK_DGRAM)
95
+ socket.connect(Socket.pack_sockaddr_un(@socket_path))
96
+ end
97
+ socket
98
+ end
99
+ end
100
+
101
+ class Batch
102
+ def initialize(connection, max_buffer_bytes)
103
+ @connection = connection
104
+ @max_buffer_bytes = max_buffer_bytes
105
+ @depth = 0
106
+ reset
107
+ end
108
+
109
+ def open
110
+ @depth += 1
111
+ yield
112
+ ensure
113
+ @depth -= 1
114
+ flush if !open?
115
+ end
116
+
117
+ def open?
118
+ @depth > 0
119
+ end
120
+
121
+ def add(message)
122
+ message_bytes = message.bytesize
123
+
124
+ unless @buffer_bytes == 0
125
+ if @buffer_bytes + 1 + message_bytes >= @max_buffer_bytes
126
+ flush
127
+ else
128
+ @buffer << NEW_LINE
129
+ @buffer_bytes += 1
130
+ end
131
+ end
132
+
133
+ @buffer << message
134
+ @buffer_bytes += message_bytes
135
+ end
136
+
137
+ def flush
138
+ return if @buffer_bytes == 0
139
+ @connection.write @buffer
140
+ reset
141
+ end
142
+
143
+ private
144
+
145
+ def reset
146
+ @buffer = String.new
147
+ @buffer_bytes = 0
148
+ end
149
+ end
24
150
 
25
151
  # Create a dictionary to assign a key to every parameter's name, except for tags (treated differently)
26
152
  # Goal: Simple and fast to add some other parameters
@@ -46,78 +172,66 @@ module Datadog
46
172
  CRITICAL = 2
47
173
  UNKNOWN = 3
48
174
 
175
+ MAX_EVENT_SIZE = 8 * 1024
176
+
49
177
  COUNTER_TYPE = 'c'.freeze
50
178
  GAUGE_TYPE = 'g'.freeze
51
179
  HISTOGRAM_TYPE = 'h'.freeze
52
180
  DISTRIBUTION_TYPE = 'd'.freeze
53
181
  TIMING_TYPE = 'ms'.freeze
54
182
  SET_TYPE = 's'.freeze
55
- VERSION = "3.3.0".freeze
183
+ VERSION = "4.0.0".freeze
56
184
 
57
185
  # A namespace to prepend to all statsd calls. Defaults to no namespace.
58
186
  attr_reader :namespace
59
187
 
60
- # StatsD host. Defaults to 127.0.0.1.
61
- attr_reader :host
62
-
63
- # StatsD port. Defaults to 8125.
64
- attr_reader :port
65
-
66
- # DogStatsd unix socket path. Not used by default.
67
- attr_reader :socket_path
68
-
69
188
  # Global tags to be added to every statsd call. Defaults to no tags.
70
189
  attr_reader :tags
71
190
 
72
191
  # Buffer containing the statsd message before they are sent in batch
73
192
  attr_reader :buffer
74
193
 
75
- # Maximum number of metrics in the buffer before it is flushed
76
- attr_accessor :max_buffer_size
194
+ # Maximum buffer size in bytes before it is flushed
195
+ attr_reader :max_buffer_bytes
77
196
 
78
- class << self
79
- # Set to a standard logger instance to enable debug logging.
80
- attr_accessor :logger
81
- end
82
-
83
- # Return the current version of the library.
84
- # deprecated, but cannot be removed since uses might use it to check the version against older releases
85
- def self.VERSION
86
- VERSION
87
- end
197
+ # Connection
198
+ attr_reader :connection
88
199
 
89
200
  # @param [String] host your statsd host
90
201
  # @param [Integer] port your statsd port
91
- # @option opts [String] :namespace set a namespace to be prepended to every metric name
92
- # @option opts [Array<String>] :tags tags to be added to every metric
93
- def initialize(host = DEFAULT_HOST, port = DEFAULT_PORT, opts = {}, max_buffer_size=50)
94
- self.host, self.port = host, port
95
- @socket_path = opts[:socket_path]
96
- @prefix = nil
97
- @socket = connect_to_socket if @socket_path.nil?
98
- self.namespace = opts[:namespace]
99
- self.tags = opts[:tags]
100
- @buffer = Array.new
101
- self.max_buffer_size = max_buffer_size
102
- @batch_nesting_depth = 0
103
- end
202
+ # @option [String] namespace set a namespace to be prepended to every metric name
203
+ # @option [Array<String>] tags tags to be added to every metric
204
+ # @option [Loger] logger for debugging
205
+ # @option [Integer] max_buffer_bytes max bytes to buffer when using #batch
206
+ # @option [String] socket_path unix socket path
207
+ def initialize(
208
+ host = nil,
209
+ port = nil,
210
+ namespace: nil,
211
+ tags: nil,
212
+ max_buffer_bytes: 8192,
213
+ socket_path: nil,
214
+ logger: nil
215
+ )
216
+ @connection = Connection.new(host, port, socket_path, logger)
217
+ @logger = logger
104
218
 
105
- def namespace=(namespace) #:nodoc:
106
219
  @namespace = namespace
107
- @prefix = namespace.nil? ? nil : "#{namespace}.".freeze
108
- end
220
+ @prefix = @namespace ? "#{@namespace}.".freeze : nil
109
221
 
110
- def host=(host) #:nodoc:
111
- @host = host || DEFAULT_HOST
112
- end
222
+ raise ArgumentError, 'tags must be a Array<String>' unless tags.nil? or tags.is_a? Array
223
+ @tags = (tags || []).compact.map! {|tag| escape_tag_content(tag)}
113
224
 
114
- def port=(port) #:nodoc:
115
- @port = port || DEFAULT_PORT
225
+ @batch = Batch.new @connection, max_buffer_bytes
116
226
  end
117
227
 
118
- def tags=(tags) #:nodoc:
119
- raise ArgumentError, 'tags must be a Array<String>' unless tags.nil? or tags.is_a? Array
120
- @tags = (tags || []).compact.map! {|tag| escape_tag_content(tag)}
228
+ # yield a new instance to a block and close it when done
229
+ # for short-term use-cases that don't want to close the socket manually
230
+ def self.open(*args)
231
+ instance = new(*args)
232
+ yield instance
233
+ ensure
234
+ instance.close
121
235
  end
122
236
 
123
237
  # Sends an increment (count = 1) for the given stat to the statsd server.
@@ -128,7 +242,7 @@ module Datadog
128
242
  # @option opts [Array<String>] :tags An array of tags
129
243
  # @option opts [Numeric] :by increment value, default 1
130
244
  # @see #count
131
- def increment(stat, opts={})
245
+ def increment(stat, opts=EMPTY_OPTIONS)
132
246
  opts = {:sample_rate => opts} if opts.is_a? Numeric
133
247
  incr_value = opts.fetch(:by, 1)
134
248
  count stat, incr_value, opts
@@ -142,7 +256,7 @@ module Datadog
142
256
  # @option opts [Array<String>] :tags An array of tags
143
257
  # @option opts [Numeric] :by decrement value, default 1
144
258
  # @see #count
145
- def decrement(stat, opts={})
259
+ def decrement(stat, opts=EMPTY_OPTIONS)
146
260
  opts = {:sample_rate => opts} if opts.is_a? Numeric
147
261
  decr_value = - opts.fetch(:by, 1)
148
262
  count stat, decr_value, opts
@@ -155,7 +269,7 @@ module Datadog
155
269
  # @param [Hash] opts the options to create the metric with
156
270
  # @option opts [Numeric] :sample_rate sample rate, 1 for always
157
271
  # @option opts [Array<String>] :tags An array of tags
158
- def count(stat, count, opts={})
272
+ def count(stat, count, opts=EMPTY_OPTIONS)
159
273
  opts = {:sample_rate => opts} if opts.is_a? Numeric
160
274
  send_stats stat, count, COUNTER_TYPE, opts
161
275
  end
@@ -173,7 +287,7 @@ module Datadog
173
287
  # @option opts [Array<String>] :tags An array of tags
174
288
  # @example Report the current user count:
175
289
  # $statsd.gauge('user.count', User.count)
176
- def gauge(stat, value, opts={})
290
+ def gauge(stat, value, opts=EMPTY_OPTIONS)
177
291
  opts = {:sample_rate => opts} if opts.is_a? Numeric
178
292
  send_stats stat, value, GAUGE_TYPE, opts
179
293
  end
@@ -187,7 +301,7 @@ module Datadog
187
301
  # @option opts [Array<String>] :tags An array of tags
188
302
  # @example Report the current user count:
189
303
  # $statsd.histogram('user.count', User.count)
190
- def histogram(stat, value, opts={})
304
+ def histogram(stat, value, opts=EMPTY_OPTIONS)
191
305
  send_stats stat, value, HISTOGRAM_TYPE, opts
192
306
  end
193
307
 
@@ -203,7 +317,7 @@ module Datadog
203
317
  # @option opts [Array<String>] :tags An array of tags
204
318
  # @example Report the current user count:
205
319
  # $statsd.distribution('user.count', User.count)
206
- def distribution(stat, value, opts={})
320
+ def distribution(stat, value, opts=EMPTY_OPTIONS)
207
321
  send_stats stat, value, DISTRIBUTION_TYPE, opts
208
322
  end
209
323
 
@@ -217,7 +331,7 @@ module Datadog
217
331
  # @param [Hash] opts the options to create the metric with
218
332
  # @option opts [Numeric] :sample_rate sample rate, 1 for always
219
333
  # @option opts [Array<String>] :tags An array of tags
220
- def timing(stat, ms, opts={})
334
+ def timing(stat, ms, opts=EMPTY_OPTIONS)
221
335
  opts = {:sample_rate => opts} if opts.is_a? Numeric
222
336
  send_stats stat, ms, TIMING_TYPE, opts
223
337
  end
@@ -235,7 +349,7 @@ module Datadog
235
349
  # @see #timing
236
350
  # @example Report the time (in ms) taken to activate an account
237
351
  # $statsd.time('account.activate') { @account.activate! }
238
- def time(stat, opts={})
352
+ def time(stat, opts=EMPTY_OPTIONS)
239
353
  opts = {:sample_rate => opts} if opts.is_a? Numeric
240
354
  start = (PROCESS_TIME_SUPPORTED ? Process.clock_gettime(Process::CLOCK_MONOTONIC) : Time.now.to_f)
241
355
  return yield
@@ -243,6 +357,7 @@ module Datadog
243
357
  finished = (PROCESS_TIME_SUPPORTED ? Process.clock_gettime(Process::CLOCK_MONOTONIC) : Time.now.to_f)
244
358
  timing(stat, ((finished - start) * 1000).round, opts)
245
359
  end
360
+
246
361
  # Sends a value to be tracked as a set to the statsd server.
247
362
  #
248
363
  # @param [String] stat stat name.
@@ -252,7 +367,7 @@ module Datadog
252
367
  # @option opts [Array<String>] :tags An array of tags
253
368
  # @example Record a unique visitory by id:
254
369
  # $statsd.set('visitors.uniques', User.id)
255
- def set(stat, value, opts={})
370
+ def set(stat, value, opts=EMPTY_OPTIONS)
256
371
  opts = {:sample_rate => opts} if opts.is_a? Numeric
257
372
  send_stats stat, value, SET_TYPE, opts
258
373
  end
@@ -268,31 +383,8 @@ module Datadog
268
383
  # @option opts [String, nil] :message (nil) A message to associate with this service check status
269
384
  # @example Report a critical service check status
270
385
  # $statsd.service_check('my.service.check', Statsd::CRITICAL, :tags=>['urgent'])
271
- def service_check(name, status, opts={})
272
- service_check_string = format_service_check(name, status, opts)
273
- send_to_socket service_check_string
274
- end
275
-
276
- def format_service_check(name, status, opts={})
277
- sc_string = "_sc|#{name}|#{status}"
278
-
279
- SC_OPT_KEYS.each do |key, shorthand_key|
280
- next unless opts[key]
281
-
282
- if key == :tags
283
- if tags_string = tags_as_string(opts)
284
- sc_string << "|##{tags_string}"
285
- end
286
- elsif key == :message
287
- message = remove_pipes(opts[:message])
288
- escaped_message = escape_service_check_message(message)
289
- sc_string << "|m:#{escaped_message}"
290
- else
291
- value = remove_pipes(opts[key])
292
- sc_string << "|#{shorthand_key}#{value}"
293
- end
294
- end
295
- return sc_string
386
+ def service_check(name, status, opts=EMPTY_OPTIONS)
387
+ send_stat format_service_check(name, status, opts)
296
388
  end
297
389
 
298
390
  # This end point allows you to post events to the stream. You can tag them, set priority and even aggregate them with other events.
@@ -313,11 +405,8 @@ module Datadog
313
405
  # @option opts [Array<String>] :tags tags to be added to every metric
314
406
  # @example Report an awful event:
315
407
  # $statsd.event('Something terrible happened', 'The end is near if we do nothing', :alert_type=>'warning', :tags=>['end_of_times','urgent'])
316
- def event(title, text, opts={})
317
- event_string = format_event(title, text, opts)
318
- raise "Event #{title} payload is too big (more that 8KB), event discarded" if event_string.length > 8 * 1024
319
-
320
- send_to_socket event_string
408
+ def event(title, text, opts=EMPTY_OPTIONS)
409
+ send_stat format_event(title, text, opts)
321
410
  end
322
411
 
323
412
  # Send several metrics in the same UDP Packet
@@ -328,18 +417,56 @@ module Datadog
328
417
  # s.gauge('users.online',156)
329
418
  # s.increment('page.views')
330
419
  # end
331
- def batch()
332
- @batch_nesting_depth += 1
333
- yield self
334
- ensure
335
- @batch_nesting_depth -= 1
336
- flush_buffer if @batch_nesting_depth == 0
420
+ def batch
421
+ @batch.open { yield self }
337
422
  end
338
423
 
339
- def format_event(title, text, opts={})
424
+ # Close the underlying socket
425
+ def close
426
+ @connection.close
427
+ end
428
+
429
+ private
430
+
431
+ NEW_LINE = "\n".freeze
432
+ ESC_NEW_LINE = "\\n".freeze
433
+ COMMA = ",".freeze
434
+ PIPE = "|".freeze
435
+ DOT = ".".freeze
436
+ DOUBLE_COLON = "::".freeze
437
+ UNDERSCORE = "_".freeze
438
+ PROCESS_TIME_SUPPORTED = (RUBY_VERSION >= "2.1.0")
439
+ EMPTY_OPTIONS = {}.freeze
440
+
441
+ private_constant :NEW_LINE, :ESC_NEW_LINE, :COMMA, :PIPE, :DOT,
442
+ :DOUBLE_COLON, :UNDERSCORE, :EMPTY_OPTIONS
443
+
444
+ def format_service_check(name, status, opts=EMPTY_OPTIONS)
445
+ sc_string = "_sc|#{name}|#{status}".dup
446
+
447
+ SC_OPT_KEYS.each do |key, shorthand_key|
448
+ next unless opts[key]
449
+
450
+ if key == :tags
451
+ if tags_string = tags_as_string(opts)
452
+ sc_string << "|##{tags_string}"
453
+ end
454
+ elsif key == :message
455
+ message = remove_pipes(opts[:message])
456
+ escaped_message = escape_service_check_message(message)
457
+ sc_string << "|m:#{escaped_message}"
458
+ else
459
+ value = remove_pipes(opts[key])
460
+ sc_string << "|#{shorthand_key}#{value}"
461
+ end
462
+ end
463
+ sc_string
464
+ end
465
+
466
+ def format_event(title, text, opts=EMPTY_OPTIONS)
340
467
  escaped_title = escape_event_content(title)
341
468
  escaped_text = escape_event_content(text)
342
- event_string_data = "_e{#{escaped_title.length},#{escaped_text.length}}:#{escaped_title}|#{escaped_text}"
469
+ event_string_data = "_e{#{escaped_title.length},#{escaped_text.length}}:#{escaped_title}|#{escaped_text}".dup
343
470
 
344
471
  # We construct the string to be sent by adding '|key:value' parts to it when needed
345
472
  # All pipes ('|') in the metadata are removed. Title and Text can keep theirs
@@ -355,33 +482,17 @@ module Datadog
355
482
  event_string_data << "|##{tags_string}"
356
483
  end
357
484
 
358
- raise "Event #{title} payload is too big (more that 8KB), event discarded" if event_string_data.length > 8192 # 8 * 1024 = 8192
359
- return event_string_data
360
- end
361
-
362
- # Close the underlying socket
363
- def close()
364
- @socket.close
485
+ raise "Event #{title} payload is too big (more that 8KB), event discarded" if event_string_data.length > MAX_EVENT_SIZE
486
+ event_string_data
365
487
  end
366
488
 
367
- private
368
-
369
- NEW_LINE = "\n".freeze
370
- ESC_NEW_LINE = "\\n".freeze
371
- COMMA = ",".freeze
372
- PIPE = "|".freeze
373
- DOT = ".".freeze
374
- DOUBLE_COLON = "::".freeze
375
- UNDERSCORE = "_".freeze
376
- PROCESS_TIME_SUPPORTED = (RUBY_VERSION >= "2.1.0")
377
-
378
- private_constant :NEW_LINE, :ESC_NEW_LINE, :COMMA, :PIPE, :DOT,
379
- :DOUBLE_COLON, :UNDERSCORE
380
-
381
489
  def tags_as_string(opts)
382
- tag_arr = opts[:tags] || []
383
- tag_arr = tag_arr.map { |tag| escape_tag_content(tag) }
384
- tag_arr = tags + tag_arr # @tags are normalized when set, so not need to normalize them again
490
+ if tag_arr = opts[:tags]
491
+ tag_arr = tag_arr.map { |tag| escape_tag_content(tag) }
492
+ tag_arr = tags + tag_arr # @tags are normalized when set, so not need to normalize them again
493
+ else
494
+ tag_arr = tags
495
+ end
385
496
  tag_arr.join(COMMA) unless tag_arr.empty?
386
497
  end
387
498
 
@@ -403,10 +514,10 @@ module Datadog
403
514
  escape_event_content(msg).gsub('m:'.freeze, 'm\:'.freeze)
404
515
  end
405
516
 
406
- def send_stats(stat, delta, type, opts={})
517
+ def send_stats(stat, delta, type, opts=EMPTY_OPTIONS)
407
518
  sample_rate = opts[:sample_rate] || 1
408
519
  if sample_rate == 1 or rand < sample_rate
409
- full_stat = ''
520
+ full_stat = ''.dup
410
521
  full_stat << @prefix if @prefix
411
522
 
412
523
  stat = stat.is_a?(String) ? stat.dup : stat.to_s
@@ -437,62 +548,11 @@ module Datadog
437
548
  end
438
549
 
439
550
  def send_stat(message)
440
- if @batch_nesting_depth > 0
441
- @buffer << message
442
- flush_buffer if @buffer.length >= @max_buffer_size
443
- else
444
- send_to_socket(message)
445
- end
446
- end
447
-
448
- def flush_buffer
449
- return @buffer if @buffer.empty?
450
- send_to_socket(@buffer.join(NEW_LINE))
451
- @buffer = Array.new
452
- end
453
-
454
- def connect_to_socket
455
- if !@socket_path.nil?
456
- socket = Socket.new(Socket::AF_UNIX, Socket::SOCK_DGRAM)
457
- socket.connect(Socket.pack_sockaddr_un(@socket_path))
458
- else
459
- socket = UDPSocket.new
460
- socket.connect(@host, @port)
461
- end
462
- socket
463
- end
464
-
465
- def sock
466
- @socket ||= connect_to_socket
467
- end
468
-
469
- def send_to_socket(message)
470
- self.class.logger.debug { "Statsd: #{message}" } if self.class.logger
471
- if @socket_path.nil?
472
- sock.send(message, 0)
551
+ if @batch.open?
552
+ @batch.add message
473
553
  else
474
- sock.sendmsg_nonblock(message)
554
+ @connection.write(message)
475
555
  end
476
- rescue => boom
477
- if @socket_path && (boom.is_a?(Errno::ECONNREFUSED) ||
478
- boom.is_a?(Errno::ECONNRESET) ||
479
- boom.is_a?(Errno::ENOENT))
480
- return @socket = nil
481
- end
482
- # Try once to reconnect if the socket has been closed
483
- retries ||= 1
484
- if retries <= 1 && boom.is_a?(IOError) && boom.message =~ /closed stream/i
485
- retries += 1
486
- begin
487
- @socket = connect_to_socket
488
- retry
489
- rescue => e
490
- boom = e
491
- end
492
- end
493
-
494
- self.class.logger.error { "Statsd: #{boom.class} #{boom}" } if self.class.logger
495
- nil
496
556
  end
497
557
  end
498
558
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dogstatsd-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.0
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rein Henrichs
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-04 00:00:00.000000000 Z
11
+ date: 2018-08-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A Ruby DogStastd client
14
14
  email: code@datadoghq.com
@@ -33,7 +33,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
33
33
  requirements:
34
34
  - - ">="
35
35
  - !ruby/object:Gem::Version
36
- version: '0'
36
+ version: 2.0.0
37
37
  required_rubygems_version: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - ">="
@@ -41,7 +41,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
41
41
  version: '0'
42
42
  requirements: []
43
43
  rubyforge_project:
44
- rubygems_version: 2.7.1
44
+ rubygems_version: 2.7.7
45
45
  signing_key:
46
46
  specification_version: 4
47
47
  summary: A Ruby DogStatsd client