dogstatsd-ruby 3.0.0 → 3.3.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 +5 -5
- data/lib/datadog/statsd.rb +85 -53
- metadata +4 -61
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 046a0af9f230451c91fdeb9ae128c550b1c20623fa017d326e63a2f053f7cc9a
|
4
|
+
data.tar.gz: e2ba838497de521e89d386645a0228f819fdd03c28acc05a4789aa7f8d979de8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2048376477bd1af31a63b75d17638df999c9f6341f967b2c826177add2a13831a54a72729e2a5c62aa09fa4aca6dccbaba308c79d9adcd470808d3bb80cde59
|
7
|
+
data.tar.gz: 2e0ac5fc90f8a2359f35a754034bb6474c1169ac8c8f3301257555553e1aca4f708cecd4d9245ff835cbe4396561a89d3bd3700ef6cea6c92c343a1e41ca2055
|
data/lib/datadog/statsd.rb
CHANGED
@@ -49,8 +49,10 @@ module Datadog
|
|
49
49
|
COUNTER_TYPE = 'c'.freeze
|
50
50
|
GAUGE_TYPE = 'g'.freeze
|
51
51
|
HISTOGRAM_TYPE = 'h'.freeze
|
52
|
+
DISTRIBUTION_TYPE = 'd'.freeze
|
52
53
|
TIMING_TYPE = 'ms'.freeze
|
53
54
|
SET_TYPE = 's'.freeze
|
55
|
+
VERSION = "3.3.0".freeze
|
54
56
|
|
55
57
|
# A namespace to prepend to all statsd calls. Defaults to no namespace.
|
56
58
|
attr_reader :namespace
|
@@ -61,13 +63,12 @@ module Datadog
|
|
61
63
|
# StatsD port. Defaults to 8125.
|
62
64
|
attr_reader :port
|
63
65
|
|
66
|
+
# DogStatsd unix socket path. Not used by default.
|
67
|
+
attr_reader :socket_path
|
68
|
+
|
64
69
|
# Global tags to be added to every statsd call. Defaults to no tags.
|
65
70
|
attr_reader :tags
|
66
71
|
|
67
|
-
# True if we should batch up data before sending it, or false if we
|
68
|
-
# want to send data immediately.
|
69
|
-
attr_reader :should_batch
|
70
|
-
|
71
72
|
# Buffer containing the statsd message before they are sent in batch
|
72
73
|
attr_reader :buffer
|
73
74
|
|
@@ -80,8 +81,9 @@ module Datadog
|
|
80
81
|
end
|
81
82
|
|
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
|
83
85
|
def self.VERSION
|
84
|
-
|
86
|
+
VERSION
|
85
87
|
end
|
86
88
|
|
87
89
|
# @param [String] host your statsd host
|
@@ -90,13 +92,14 @@ module Datadog
|
|
90
92
|
# @option opts [Array<String>] :tags tags to be added to every metric
|
91
93
|
def initialize(host = DEFAULT_HOST, port = DEFAULT_PORT, opts = {}, max_buffer_size=50)
|
92
94
|
self.host, self.port = host, port
|
95
|
+
@socket_path = opts[:socket_path]
|
93
96
|
@prefix = nil
|
94
|
-
@socket = connect_to_socket
|
97
|
+
@socket = connect_to_socket if @socket_path.nil?
|
95
98
|
self.namespace = opts[:namespace]
|
96
99
|
self.tags = opts[:tags]
|
97
100
|
@buffer = Array.new
|
98
101
|
self.max_buffer_size = max_buffer_size
|
99
|
-
@
|
102
|
+
@batch_nesting_depth = 0
|
100
103
|
end
|
101
104
|
|
102
105
|
def namespace=(namespace) #:nodoc:
|
@@ -114,7 +117,7 @@ module Datadog
|
|
114
117
|
|
115
118
|
def tags=(tags) #:nodoc:
|
116
119
|
raise ArgumentError, 'tags must be a Array<String>' unless tags.nil? or tags.is_a? Array
|
117
|
-
@tags = (tags || []).map {|tag| escape_tag_content(tag)}
|
120
|
+
@tags = (tags || []).compact.map! {|tag| escape_tag_content(tag)}
|
118
121
|
end
|
119
122
|
|
120
123
|
# Sends an increment (count = 1) for the given stat to the statsd server.
|
@@ -126,6 +129,7 @@ module Datadog
|
|
126
129
|
# @option opts [Numeric] :by increment value, default 1
|
127
130
|
# @see #count
|
128
131
|
def increment(stat, opts={})
|
132
|
+
opts = {:sample_rate => opts} if opts.is_a? Numeric
|
129
133
|
incr_value = opts.fetch(:by, 1)
|
130
134
|
count stat, incr_value, opts
|
131
135
|
end
|
@@ -139,6 +143,7 @@ module Datadog
|
|
139
143
|
# @option opts [Numeric] :by decrement value, default 1
|
140
144
|
# @see #count
|
141
145
|
def decrement(stat, opts={})
|
146
|
+
opts = {:sample_rate => opts} if opts.is_a? Numeric
|
142
147
|
decr_value = - opts.fetch(:by, 1)
|
143
148
|
count stat, decr_value, opts
|
144
149
|
end
|
@@ -151,6 +156,7 @@ module Datadog
|
|
151
156
|
# @option opts [Numeric] :sample_rate sample rate, 1 for always
|
152
157
|
# @option opts [Array<String>] :tags An array of tags
|
153
158
|
def count(stat, count, opts={})
|
159
|
+
opts = {:sample_rate => opts} if opts.is_a? Numeric
|
154
160
|
send_stats stat, count, COUNTER_TYPE, opts
|
155
161
|
end
|
156
162
|
|
@@ -168,6 +174,7 @@ module Datadog
|
|
168
174
|
# @example Report the current user count:
|
169
175
|
# $statsd.gauge('user.count', User.count)
|
170
176
|
def gauge(stat, value, opts={})
|
177
|
+
opts = {:sample_rate => opts} if opts.is_a? Numeric
|
171
178
|
send_stats stat, value, GAUGE_TYPE, opts
|
172
179
|
end
|
173
180
|
|
@@ -184,6 +191,22 @@ module Datadog
|
|
184
191
|
send_stats stat, value, HISTOGRAM_TYPE, opts
|
185
192
|
end
|
186
193
|
|
194
|
+
# Sends a value to be tracked as a distribution to the statsd server.
|
195
|
+
# Note: Distributions are a beta feature of Datadog and not generally
|
196
|
+
# available. Distributions must be specifically enabled for your
|
197
|
+
# organization.
|
198
|
+
#
|
199
|
+
# @param [String] stat stat name.
|
200
|
+
# @param [Numeric] value distribution value.
|
201
|
+
# @param [Hash] opts the options to create the metric with
|
202
|
+
# @option opts [Numeric] :sample_rate sample rate, 1 for always
|
203
|
+
# @option opts [Array<String>] :tags An array of tags
|
204
|
+
# @example Report the current user count:
|
205
|
+
# $statsd.distribution('user.count', User.count)
|
206
|
+
def distribution(stat, value, opts={})
|
207
|
+
send_stats stat, value, DISTRIBUTION_TYPE, opts
|
208
|
+
end
|
209
|
+
|
187
210
|
# Sends a timing (in ms) for the given stat to the statsd server. The
|
188
211
|
# sample_rate determines what percentage of the time this report is sent. The
|
189
212
|
# statsd server then uses the sample_rate to correctly track the average
|
@@ -195,6 +218,7 @@ module Datadog
|
|
195
218
|
# @option opts [Numeric] :sample_rate sample rate, 1 for always
|
196
219
|
# @option opts [Array<String>] :tags An array of tags
|
197
220
|
def timing(stat, ms, opts={})
|
221
|
+
opts = {:sample_rate => opts} if opts.is_a? Numeric
|
198
222
|
send_stats stat, ms, TIMING_TYPE, opts
|
199
223
|
end
|
200
224
|
|
@@ -212,10 +236,12 @@ module Datadog
|
|
212
236
|
# @example Report the time (in ms) taken to activate an account
|
213
237
|
# $statsd.time('account.activate') { @account.activate! }
|
214
238
|
def time(stat, opts={})
|
215
|
-
|
239
|
+
opts = {:sample_rate => opts} if opts.is_a? Numeric
|
240
|
+
start = (PROCESS_TIME_SUPPORTED ? Process.clock_gettime(Process::CLOCK_MONOTONIC) : Time.now.to_f)
|
216
241
|
return yield
|
217
242
|
ensure
|
218
|
-
|
243
|
+
finished = (PROCESS_TIME_SUPPORTED ? Process.clock_gettime(Process::CLOCK_MONOTONIC) : Time.now.to_f)
|
244
|
+
timing(stat, ((finished - start) * 1000).round, opts)
|
219
245
|
end
|
220
246
|
# Sends a value to be tracked as a set to the statsd server.
|
221
247
|
#
|
@@ -227,10 +253,10 @@ module Datadog
|
|
227
253
|
# @example Record a unique visitory by id:
|
228
254
|
# $statsd.set('visitors.uniques', User.id)
|
229
255
|
def set(stat, value, opts={})
|
256
|
+
opts = {:sample_rate => opts} if opts.is_a? Numeric
|
230
257
|
send_stats stat, value, SET_TYPE, opts
|
231
258
|
end
|
232
259
|
|
233
|
-
|
234
260
|
# This method allows you to send custom service check statuses.
|
235
261
|
#
|
236
262
|
# @param [String] name Service check name
|
@@ -254,9 +280,9 @@ module Datadog
|
|
254
280
|
next unless opts[key]
|
255
281
|
|
256
282
|
if key == :tags
|
257
|
-
|
258
|
-
|
259
|
-
|
283
|
+
if tags_string = tags_as_string(opts)
|
284
|
+
sc_string << "|##{tags_string}"
|
285
|
+
end
|
260
286
|
elsif key == :message
|
261
287
|
message = remove_pipes(opts[:message])
|
262
288
|
escaped_message = escape_service_check_message(message)
|
@@ -303,11 +329,11 @@ module Datadog
|
|
303
329
|
# s.increment('page.views')
|
304
330
|
# end
|
305
331
|
def batch()
|
306
|
-
@
|
332
|
+
@batch_nesting_depth += 1
|
307
333
|
yield self
|
308
|
-
flush_buffer
|
309
334
|
ensure
|
310
|
-
@
|
335
|
+
@batch_nesting_depth -= 1
|
336
|
+
flush_buffer if @batch_nesting_depth == 0
|
311
337
|
end
|
312
338
|
|
313
339
|
def format_event(title, text, opts={})
|
@@ -325,9 +351,8 @@ module Datadog
|
|
325
351
|
end
|
326
352
|
|
327
353
|
# Tags are joined and added as last part to the string to be sent
|
328
|
-
|
329
|
-
|
330
|
-
event_string_data << "|##{full_tags.join(COMMA)}"
|
354
|
+
if tags_string = tags_as_string(opts)
|
355
|
+
event_string_data << "|##{tags_string}"
|
331
356
|
end
|
332
357
|
|
333
358
|
raise "Event #{title} payload is too big (more that 8KB), event discarded" if event_string_data.length > 8192 # 8 * 1024 = 8192
|
@@ -344,48 +369,40 @@ module Datadog
|
|
344
369
|
NEW_LINE = "\n".freeze
|
345
370
|
ESC_NEW_LINE = "\\n".freeze
|
346
371
|
COMMA = ",".freeze
|
347
|
-
BLANK = "".freeze
|
348
372
|
PIPE = "|".freeze
|
349
373
|
DOT = ".".freeze
|
350
374
|
DOUBLE_COLON = "::".freeze
|
351
375
|
UNDERSCORE = "_".freeze
|
376
|
+
PROCESS_TIME_SUPPORTED = (RUBY_VERSION >= "2.1.0")
|
352
377
|
|
353
|
-
private_constant :NEW_LINE, :ESC_NEW_LINE, :COMMA, :
|
378
|
+
private_constant :NEW_LINE, :ESC_NEW_LINE, :COMMA, :PIPE, :DOT,
|
354
379
|
:DOUBLE_COLON, :UNDERSCORE
|
355
380
|
|
381
|
+
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
|
385
|
+
tag_arr.join(COMMA) unless tag_arr.empty?
|
386
|
+
end
|
387
|
+
|
356
388
|
def escape_event_content(msg)
|
357
389
|
msg.gsub NEW_LINE, ESC_NEW_LINE
|
358
390
|
end
|
359
391
|
|
360
392
|
def escape_tag_content(tag)
|
361
|
-
remove_pipes(tag)
|
362
|
-
|
363
|
-
|
364
|
-
def escape_tag_content!(tag)
|
365
|
-
tag.gsub!(PIPE, BLANK)
|
366
|
-
tag.gsub!(COMMA, BLANK)
|
393
|
+
tag = remove_pipes(tag.to_s)
|
394
|
+
tag.delete! COMMA
|
367
395
|
tag
|
368
396
|
end
|
369
397
|
|
370
398
|
def remove_pipes(msg)
|
371
|
-
msg.
|
399
|
+
msg.delete PIPE
|
372
400
|
end
|
373
401
|
|
374
402
|
def escape_service_check_message(msg)
|
375
403
|
escape_event_content(msg).gsub('m:'.freeze, 'm\:'.freeze)
|
376
404
|
end
|
377
405
|
|
378
|
-
def time_since(stat, start, opts)
|
379
|
-
timing(stat, ((Time.now - start) * 1000).round, opts)
|
380
|
-
end
|
381
|
-
|
382
|
-
def join_array_to_str(str, array, joiner)
|
383
|
-
array.each_with_index do |item, i|
|
384
|
-
str << joiner unless i == 0
|
385
|
-
str << item
|
386
|
-
end
|
387
|
-
end
|
388
|
-
|
389
406
|
def send_stats(stat, delta, type, opts={})
|
390
407
|
sample_rate = opts[:sample_rate] || 1
|
391
408
|
if sample_rate == 1 or rand < sample_rate
|
@@ -409,14 +426,10 @@ module Datadog
|
|
409
426
|
full_stat << sample_rate.to_s
|
410
427
|
end
|
411
428
|
|
412
|
-
|
413
|
-
tag_arr = opts[:tags].to_a
|
414
|
-
tag_arr.map! { |tag| t = tag.dup; escape_tag_content!(t); t }
|
415
|
-
ts = tags.to_a + tag_arr
|
416
|
-
unless ts.empty?
|
429
|
+
if tags_string = tags_as_string(opts)
|
417
430
|
full_stat << PIPE
|
418
431
|
full_stat << '#'.freeze
|
419
|
-
|
432
|
+
full_stat << tags_string
|
420
433
|
end
|
421
434
|
|
422
435
|
send_stat(full_stat)
|
@@ -424,7 +437,7 @@ module Datadog
|
|
424
437
|
end
|
425
438
|
|
426
439
|
def send_stat(message)
|
427
|
-
if @
|
440
|
+
if @batch_nesting_depth > 0
|
428
441
|
@buffer << message
|
429
442
|
flush_buffer if @buffer.length >= @max_buffer_size
|
430
443
|
else
|
@@ -432,27 +445,46 @@ module Datadog
|
|
432
445
|
end
|
433
446
|
end
|
434
447
|
|
435
|
-
def flush_buffer
|
448
|
+
def flush_buffer
|
449
|
+
return @buffer if @buffer.empty?
|
436
450
|
send_to_socket(@buffer.join(NEW_LINE))
|
437
451
|
@buffer = Array.new
|
438
452
|
end
|
439
453
|
|
440
|
-
def connect_to_socket
|
441
|
-
|
442
|
-
|
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
|
443
462
|
socket
|
444
463
|
end
|
445
464
|
|
465
|
+
def sock
|
466
|
+
@socket ||= connect_to_socket
|
467
|
+
end
|
468
|
+
|
446
469
|
def send_to_socket(message)
|
447
470
|
self.class.logger.debug { "Statsd: #{message}" } if self.class.logger
|
448
|
-
@
|
471
|
+
if @socket_path.nil?
|
472
|
+
sock.send(message, 0)
|
473
|
+
else
|
474
|
+
sock.sendmsg_nonblock(message)
|
475
|
+
end
|
449
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
|
450
482
|
# Try once to reconnect if the socket has been closed
|
451
483
|
retries ||= 1
|
452
484
|
if retries <= 1 && boom.is_a?(IOError) && boom.message =~ /closed stream/i
|
453
485
|
retries += 1
|
454
486
|
begin
|
455
|
-
@socket = connect_to_socket
|
487
|
+
@socket = connect_to_socket
|
456
488
|
retry
|
457
489
|
rescue => e
|
458
490
|
boom = e
|
metadata
CHANGED
@@ -1,71 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dogstatsd-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.3.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:
|
12
|
-
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: minitest
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :development
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: yard
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 0.6.0
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: 0.6.0
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: jeweler
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '1.8'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '1.8'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: simplecov
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
11
|
+
date: 2018-02-04 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
69
13
|
description: A Ruby DogStastd client
|
70
14
|
email: code@datadoghq.com
|
71
15
|
executables: []
|
@@ -97,9 +41,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
97
41
|
version: '0'
|
98
42
|
requirements: []
|
99
43
|
rubyforge_project:
|
100
|
-
rubygems_version: 2.
|
44
|
+
rubygems_version: 2.7.1
|
101
45
|
signing_key:
|
102
46
|
specification_version: 4
|
103
47
|
summary: A Ruby DogStatsd client
|
104
48
|
test_files: []
|
105
|
-
has_rdoc:
|