dogstatsd-ruby 3.0.0 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|