dogstatsd-ruby 4.0.0 → 4.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 +4 -4
- data/README.md +28 -4
- data/lib/datadog/statsd.rb +80 -45
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b0a17784b24e078a39ee2717d1b7b25d1879e067a5e356db6f98eb012d2bbef2
|
|
4
|
+
data.tar.gz: 9559cb5d04e7b8dee34becbd0adb9182fb1cbda48ae5de13a470cd1d843d4d8d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 652f8010045d42ae2fe2056d6c97f645d54c430b491a1e878cdf85abd22fda2dfbeae74022fb71faa51f5ce636c1bb6dcef60e172ba15c4b74fcd3eded1d9b05
|
|
7
|
+
data.tar.gz: 42f8763913be88f9871568ac966403f19437c4e477792a771b4b10d9645e2e73f6a588f89c4ba8bd218feb44842f1f6a491434eb0cdc64a2e0a47b30287da8f2
|
data/README.md
CHANGED
|
@@ -28,9 +28,10 @@ statsd = Datadog::Statsd.new('localhost', 8125)
|
|
|
28
28
|
|
|
29
29
|
# Increment a counter.
|
|
30
30
|
statsd.increment('page.views')
|
|
31
|
+
statsd.increment('messages.count', by: 2, tags: ['kind:incoming'])
|
|
31
32
|
|
|
32
33
|
# Record a gauge 50% of the time.
|
|
33
|
-
statsd.gauge('users.online', 123, :
|
|
34
|
+
statsd.gauge('users.online', 123, sample_rate: 0.5)
|
|
34
35
|
|
|
35
36
|
# Sample a histogram
|
|
36
37
|
statsd.histogram('file.upload.size', 1234)
|
|
@@ -48,7 +49,10 @@ statsd.batch do |s|
|
|
|
48
49
|
end
|
|
49
50
|
|
|
50
51
|
# Tag a metric.
|
|
51
|
-
statsd.histogram('query.time', 10, :
|
|
52
|
+
statsd.histogram('query.time', 10, tags: ['version:1'])
|
|
53
|
+
|
|
54
|
+
# Tag a metric by passing in a Hash
|
|
55
|
+
statsd.histogram('query.time', 10, :tags => {version: 1})
|
|
52
56
|
|
|
53
57
|
# Auto-close socket after end of block
|
|
54
58
|
Datadog::Statsd.open('localhost', 8125) do |s|
|
|
@@ -62,14 +66,34 @@ Aggregation in the stream is made on hostname/event_type/source_type/aggregation
|
|
|
62
66
|
|
|
63
67
|
``` ruby
|
|
64
68
|
# Post a simple message
|
|
65
|
-
statsd.event(
|
|
69
|
+
statsd.event('There might be a storm tomorrow', 'A friend warned me earlier.')
|
|
66
70
|
|
|
67
71
|
# Cry for help
|
|
68
|
-
statsd.event(
|
|
72
|
+
statsd.event(
|
|
73
|
+
'SO MUCH SNOW',
|
|
74
|
+
"Started yesterday and it won't stop !!",
|
|
75
|
+
alert_type: 'error',
|
|
76
|
+
tags: ['urgent', 'endoftheworld']
|
|
77
|
+
)
|
|
69
78
|
```
|
|
70
79
|
|
|
71
80
|
|
|
72
81
|
|
|
82
|
+
Origin detection over UDP
|
|
83
|
+
-------------
|
|
84
|
+
Origin detection is a method to detect which pod DogStatsD packets are coming from in order to add the pod's tags to the tag list.
|
|
85
|
+
|
|
86
|
+
To enable origin detection over UDP, add the following lines to your application manifest
|
|
87
|
+
```yaml
|
|
88
|
+
env:
|
|
89
|
+
- name: DD_ENTITY_ID
|
|
90
|
+
valueFrom:
|
|
91
|
+
fieldRef:
|
|
92
|
+
fieldPath: metadata.uid
|
|
93
|
+
```
|
|
94
|
+
The DogStatsD client attaches an internal tag, `entity_id`. The value of this tag is the content of the `DD_ENTITY_ID` environment variable, which is the pod’s UID.
|
|
95
|
+
|
|
96
|
+
|
|
73
97
|
Documentation
|
|
74
98
|
-------------
|
|
75
99
|
|
data/lib/datadog/statsd.rb
CHANGED
|
@@ -33,35 +33,19 @@ module Datadog
|
|
|
33
33
|
# DogStatsd unix socket path. Not used by default.
|
|
34
34
|
attr_reader :socket_path
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
@
|
|
39
|
-
@socket_path = socket_path
|
|
40
|
-
@logger = logger
|
|
36
|
+
# Close the underlying socket
|
|
37
|
+
def close
|
|
38
|
+
@socket && @socket.close
|
|
41
39
|
end
|
|
42
40
|
|
|
43
41
|
def write(message)
|
|
44
42
|
@logger.debug { "Statsd: #{message}" } if @logger
|
|
45
|
-
|
|
46
|
-
socket.send(message, 0)
|
|
47
|
-
else
|
|
48
|
-
socket.sendmsg_nonblock(message)
|
|
49
|
-
end
|
|
43
|
+
send_message(message)
|
|
50
44
|
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
45
|
# Try once to reconnect if the socket has been closed
|
|
63
46
|
retries ||= 1
|
|
64
|
-
if retries <= 1 && boom.is_a?(
|
|
47
|
+
if retries <= 1 && boom.is_a?(Errno::ENOTCONN) or
|
|
48
|
+
retries <= 1 && boom.is_a?(IOError) && boom.message =~ /closed stream/i
|
|
65
49
|
retries += 1
|
|
66
50
|
begin
|
|
67
51
|
@socket = connect
|
|
@@ -75,27 +59,55 @@ module Datadog
|
|
|
75
59
|
nil
|
|
76
60
|
end
|
|
77
61
|
|
|
78
|
-
# Close the underlying socket
|
|
79
|
-
def close
|
|
80
|
-
@socket && @socket.close
|
|
81
|
-
end
|
|
82
|
-
|
|
83
62
|
private
|
|
84
63
|
|
|
85
64
|
def socket
|
|
86
65
|
@socket ||= connect
|
|
87
66
|
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
class UDPConnection < Connection
|
|
70
|
+
def initialize(host, port, logger)
|
|
71
|
+
@host = host || ENV.fetch('DD_AGENT_HOST', nil) || DEFAULT_HOST
|
|
72
|
+
@port = port || ENV.fetch('DD_DOGSTATSD_PORT', nil) || DEFAULT_PORT
|
|
73
|
+
@logger = logger
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
88
77
|
|
|
89
78
|
def connect
|
|
90
|
-
|
|
91
|
-
|
|
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
|
|
79
|
+
socket = UDPSocket.new
|
|
80
|
+
socket.connect(@host, @port)
|
|
97
81
|
socket
|
|
98
82
|
end
|
|
83
|
+
|
|
84
|
+
def send_message(message)
|
|
85
|
+
socket.send(message, 0)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
class UDSConnection < Connection
|
|
90
|
+
class BadSocketError < StandardError; end
|
|
91
|
+
|
|
92
|
+
def initialize(socket_path, logger)
|
|
93
|
+
@socket_path = socket_path
|
|
94
|
+
@logger = logger
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
private
|
|
98
|
+
|
|
99
|
+
def connect
|
|
100
|
+
socket = Socket.new(Socket::AF_UNIX, Socket::SOCK_DGRAM)
|
|
101
|
+
socket.connect(Socket.pack_sockaddr_un(@socket_path))
|
|
102
|
+
socket
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def send_message(message)
|
|
106
|
+
socket.sendmsg_nonblock(message)
|
|
107
|
+
rescue Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ENOENT => e
|
|
108
|
+
@socket = nil
|
|
109
|
+
raise BadSocketError, "#{e.class}: #{e}"
|
|
110
|
+
end
|
|
99
111
|
end
|
|
100
112
|
|
|
101
113
|
class Batch
|
|
@@ -180,7 +192,7 @@ module Datadog
|
|
|
180
192
|
DISTRIBUTION_TYPE = 'd'.freeze
|
|
181
193
|
TIMING_TYPE = 'ms'.freeze
|
|
182
194
|
SET_TYPE = 's'.freeze
|
|
183
|
-
VERSION = "4.
|
|
195
|
+
VERSION = "4.3.0".freeze
|
|
184
196
|
|
|
185
197
|
# A namespace to prepend to all statsd calls. Defaults to no namespace.
|
|
186
198
|
attr_reader :namespace
|
|
@@ -194,16 +206,20 @@ module Datadog
|
|
|
194
206
|
# Maximum buffer size in bytes before it is flushed
|
|
195
207
|
attr_reader :max_buffer_bytes
|
|
196
208
|
|
|
209
|
+
# Default sample rate
|
|
210
|
+
attr_reader :sample_rate
|
|
211
|
+
|
|
197
212
|
# Connection
|
|
198
213
|
attr_reader :connection
|
|
199
214
|
|
|
200
215
|
# @param [String] host your statsd host
|
|
201
216
|
# @param [Integer] port your statsd port
|
|
202
217
|
# @option [String] namespace set a namespace to be prepended to every metric name
|
|
203
|
-
# @option [Array<String
|
|
204
|
-
# @option [
|
|
218
|
+
# @option [Array<String>|Hash] tags tags to be added to every metric
|
|
219
|
+
# @option [Logger] logger for debugging
|
|
205
220
|
# @option [Integer] max_buffer_bytes max bytes to buffer when using #batch
|
|
206
221
|
# @option [String] socket_path unix socket path
|
|
222
|
+
# @option [Float] default sample rate if not overridden
|
|
207
223
|
def initialize(
|
|
208
224
|
host = nil,
|
|
209
225
|
port = nil,
|
|
@@ -211,17 +227,31 @@ module Datadog
|
|
|
211
227
|
tags: nil,
|
|
212
228
|
max_buffer_bytes: 8192,
|
|
213
229
|
socket_path: nil,
|
|
214
|
-
logger: nil
|
|
230
|
+
logger: nil,
|
|
231
|
+
sample_rate: nil
|
|
215
232
|
)
|
|
216
|
-
|
|
233
|
+
if socket_path.nil?
|
|
234
|
+
@connection = UDPConnection.new(host, port, logger)
|
|
235
|
+
else
|
|
236
|
+
@connection = UDSConnection.new(socket_path, logger)
|
|
237
|
+
end
|
|
217
238
|
@logger = logger
|
|
218
239
|
|
|
219
240
|
@namespace = namespace
|
|
220
241
|
@prefix = @namespace ? "#{@namespace}.".freeze : nil
|
|
221
242
|
|
|
222
|
-
|
|
243
|
+
@sample_rate = sample_rate
|
|
244
|
+
|
|
245
|
+
unless tags.nil? or tags.is_a? Array or tags.is_a? Hash
|
|
246
|
+
raise ArgumentError, 'tags must be a Array<String> or a Hash'
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
tags = tag_hash_to_array(tags) if tags.is_a? Hash
|
|
223
250
|
@tags = (tags || []).compact.map! {|tag| escape_tag_content(tag)}
|
|
224
251
|
|
|
252
|
+
# append the entity id to tags if DD_ENTITY_ID env var is not nil
|
|
253
|
+
@tags << 'dd.internal.entity_id:' + escape_tag_content(ENV.fetch('DD_ENTITY_ID', nil)) unless ENV.fetch('DD_ENTITY_ID', nil).nil?
|
|
254
|
+
|
|
225
255
|
@batch = Batch.new @connection, max_buffer_bytes
|
|
226
256
|
end
|
|
227
257
|
|
|
@@ -394,7 +424,7 @@ module Datadog
|
|
|
394
424
|
# it will be grouped with other events that don't have an event type.
|
|
395
425
|
#
|
|
396
426
|
# @param [String] title Event title
|
|
397
|
-
# @param [String] text Event text. Supports
|
|
427
|
+
# @param [String] text Event text. Supports newlines (+\n+)
|
|
398
428
|
# @param [Hash] opts the additional data about the event
|
|
399
429
|
# @option opts [Integer, nil] :date_happened (nil) Assign a timestamp to the event. Default is now when none
|
|
400
430
|
# @option opts [String, nil] :hostname (nil) Assign a hostname to the event.
|
|
@@ -466,7 +496,7 @@ module Datadog
|
|
|
466
496
|
def format_event(title, text, opts=EMPTY_OPTIONS)
|
|
467
497
|
escaped_title = escape_event_content(title)
|
|
468
498
|
escaped_text = escape_event_content(text)
|
|
469
|
-
event_string_data = "_e{#{escaped_title.
|
|
499
|
+
event_string_data = "_e{#{escaped_title.bytesize},#{escaped_text.bytesize}}:#{escaped_title}|#{escaped_text}".dup
|
|
470
500
|
|
|
471
501
|
# We construct the string to be sent by adding '|key:value' parts to it when needed
|
|
472
502
|
# All pipes ('|') in the metadata are removed. Title and Text can keep theirs
|
|
@@ -482,12 +512,13 @@ module Datadog
|
|
|
482
512
|
event_string_data << "|##{tags_string}"
|
|
483
513
|
end
|
|
484
514
|
|
|
485
|
-
raise "Event #{title} payload is too big (more that 8KB), event discarded" if event_string_data.
|
|
515
|
+
raise "Event #{title} payload is too big (more that 8KB), event discarded" if event_string_data.bytesize > MAX_EVENT_SIZE
|
|
486
516
|
event_string_data
|
|
487
517
|
end
|
|
488
518
|
|
|
489
519
|
def tags_as_string(opts)
|
|
490
520
|
if tag_arr = opts[:tags]
|
|
521
|
+
tag_arr = tag_hash_to_array(tag_arr) if tag_arr.is_a? Hash
|
|
491
522
|
tag_arr = tag_arr.map { |tag| escape_tag_content(tag) }
|
|
492
523
|
tag_arr = tags + tag_arr # @tags are normalized when set, so not need to normalize them again
|
|
493
524
|
else
|
|
@@ -496,6 +527,10 @@ module Datadog
|
|
|
496
527
|
tag_arr.join(COMMA) unless tag_arr.empty?
|
|
497
528
|
end
|
|
498
529
|
|
|
530
|
+
def tag_hash_to_array(tag_hash)
|
|
531
|
+
tag_hash.to_a.map {|pair| pair.compact.join(":")}
|
|
532
|
+
end
|
|
533
|
+
|
|
499
534
|
def escape_event_content(msg)
|
|
500
535
|
msg.gsub NEW_LINE, ESC_NEW_LINE
|
|
501
536
|
end
|
|
@@ -515,8 +550,8 @@ module Datadog
|
|
|
515
550
|
end
|
|
516
551
|
|
|
517
552
|
def send_stats(stat, delta, type, opts=EMPTY_OPTIONS)
|
|
518
|
-
sample_rate = opts[:sample_rate] || 1
|
|
519
|
-
if sample_rate == 1 or rand
|
|
553
|
+
sample_rate = opts[:sample_rate] || @sample_rate || 1
|
|
554
|
+
if sample_rate == 1 or rand <= sample_rate
|
|
520
555
|
full_stat = ''.dup
|
|
521
556
|
full_stat << @prefix if @prefix
|
|
522
557
|
|
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: 4.
|
|
4
|
+
version: 4.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:
|
|
11
|
+
date: 2019-06-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: A Ruby DogStastd client
|
|
14
14
|
email: code@datadoghq.com
|
|
@@ -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.
|
|
44
|
+
rubygems_version: 2.7.6
|
|
45
45
|
signing_key:
|
|
46
46
|
specification_version: 4
|
|
47
47
|
summary: A Ruby DogStatsd client
|