dogstatsd-ruby 4.2.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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +28 -4
  3. data/lib/datadog/statsd.rb +75 -44
  4. metadata +4 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c8e8d0982550cf2f3e3dddee6eee8dcf88534ccf4e26ef47731c2866b85e81f2
4
- data.tar.gz: 8f9d33a02a6b86e343144c98511e243a65bdaeb2f881ae00cd7842528158f3f6
3
+ metadata.gz: b0a17784b24e078a39ee2717d1b7b25d1879e067a5e356db6f98eb012d2bbef2
4
+ data.tar.gz: 9559cb5d04e7b8dee34becbd0adb9182fb1cbda48ae5de13a470cd1d843d4d8d
5
5
  SHA512:
6
- metadata.gz: 68e6cc9c4bbbbffa546eaefd643785ca945ae00dfd03d84d5984262d0061f25b059c325063220fd15bdd354d6ec721ba7d50ad7b7c2310d2b64c24b49314ba36
7
- data.tar.gz: c070c0fd60a513b3c89a8eff5c4c755e38b5d646529840adca886a52651831f7bef1bdf437723329237f1faf4066960bee32ae5e5b6b9f4ddeb1eb69bfb87afe
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, :sample_rate=>0.5)
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, :tags => ["version:1"])
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("There might be a storm tomorrow", "A friend warned me earlier.")
69
+ statsd.event('There might be a storm tomorrow', 'A friend warned me earlier.')
66
70
 
67
71
  # Cry for help
68
- statsd.event("SO MUCH SNOW", "Started yesterday and it won't stop !!", :alert_type => "error", :tags => ["urgent", "endoftheworld"])
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
 
@@ -33,32 +33,15 @@ module Datadog
33
33
  # DogStatsd unix socket path. Not used by default.
34
34
  attr_reader :socket_path
35
35
 
36
- def initialize(host, port, socket_path, logger)
37
- @host = host || ENV.fetch('DD_AGENT_HOST', nil) || DEFAULT_HOST
38
- @port = port || ENV.fetch('DD_DOGSTATSD_PORT', nil) || DEFAULT_PORT
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
- if @socket_path.nil?
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
47
  if retries <= 1 && boom.is_a?(Errno::ENOTCONN) or
@@ -76,27 +59,55 @@ module Datadog
76
59
  nil
77
60
  end
78
61
 
79
- # Close the underlying socket
80
- def close
81
- @socket && @socket.close
82
- end
83
-
84
62
  private
85
63
 
86
64
  def socket
87
65
  @socket ||= connect
88
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
89
77
 
90
78
  def connect
91
- if @socket_path.nil?
92
- socket = UDPSocket.new
93
- socket.connect(@host, @port)
94
- else
95
- socket = Socket.new(Socket::AF_UNIX, Socket::SOCK_DGRAM)
96
- socket.connect(Socket.pack_sockaddr_un(@socket_path))
97
- end
79
+ socket = UDPSocket.new
80
+ socket.connect(@host, @port)
98
81
  socket
99
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
100
111
  end
101
112
 
102
113
  class Batch
@@ -181,7 +192,7 @@ module Datadog
181
192
  DISTRIBUTION_TYPE = 'd'.freeze
182
193
  TIMING_TYPE = 'ms'.freeze
183
194
  SET_TYPE = 's'.freeze
184
- VERSION = "4.2.0".freeze
195
+ VERSION = "4.3.0".freeze
185
196
 
186
197
  # A namespace to prepend to all statsd calls. Defaults to no namespace.
187
198
  attr_reader :namespace
@@ -195,16 +206,20 @@ module Datadog
195
206
  # Maximum buffer size in bytes before it is flushed
196
207
  attr_reader :max_buffer_bytes
197
208
 
209
+ # Default sample rate
210
+ attr_reader :sample_rate
211
+
198
212
  # Connection
199
213
  attr_reader :connection
200
214
 
201
215
  # @param [String] host your statsd host
202
216
  # @param [Integer] port your statsd port
203
217
  # @option [String] namespace set a namespace to be prepended to every metric name
204
- # @option [Array<String>] tags tags to be added to every metric
205
- # @option [Loger] logger for debugging
218
+ # @option [Array<String>|Hash] tags tags to be added to every metric
219
+ # @option [Logger] logger for debugging
206
220
  # @option [Integer] max_buffer_bytes max bytes to buffer when using #batch
207
221
  # @option [String] socket_path unix socket path
222
+ # @option [Float] default sample rate if not overridden
208
223
  def initialize(
209
224
  host = nil,
210
225
  port = nil,
@@ -212,15 +227,26 @@ module Datadog
212
227
  tags: nil,
213
228
  max_buffer_bytes: 8192,
214
229
  socket_path: nil,
215
- logger: nil
230
+ logger: nil,
231
+ sample_rate: nil
216
232
  )
217
- @connection = Connection.new(host, port, socket_path, logger)
233
+ if socket_path.nil?
234
+ @connection = UDPConnection.new(host, port, logger)
235
+ else
236
+ @connection = UDSConnection.new(socket_path, logger)
237
+ end
218
238
  @logger = logger
219
239
 
220
240
  @namespace = namespace
221
241
  @prefix = @namespace ? "#{@namespace}.".freeze : nil
222
242
 
223
- raise ArgumentError, 'tags must be a Array<String>' unless tags.nil? or tags.is_a? Array
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
224
250
  @tags = (tags || []).compact.map! {|tag| escape_tag_content(tag)}
225
251
 
226
252
  # append the entity id to tags if DD_ENTITY_ID env var is not nil
@@ -398,7 +424,7 @@ module Datadog
398
424
  # it will be grouped with other events that don't have an event type.
399
425
  #
400
426
  # @param [String] title Event title
401
- # @param [String] text Event text. Supports \n
427
+ # @param [String] text Event text. Supports newlines (+\n+)
402
428
  # @param [Hash] opts the additional data about the event
403
429
  # @option opts [Integer, nil] :date_happened (nil) Assign a timestamp to the event. Default is now when none
404
430
  # @option opts [String, nil] :hostname (nil) Assign a hostname to the event.
@@ -470,7 +496,7 @@ module Datadog
470
496
  def format_event(title, text, opts=EMPTY_OPTIONS)
471
497
  escaped_title = escape_event_content(title)
472
498
  escaped_text = escape_event_content(text)
473
- event_string_data = "_e{#{escaped_title.length},#{escaped_text.length}}:#{escaped_title}|#{escaped_text}".dup
499
+ event_string_data = "_e{#{escaped_title.bytesize},#{escaped_text.bytesize}}:#{escaped_title}|#{escaped_text}".dup
474
500
 
475
501
  # We construct the string to be sent by adding '|key:value' parts to it when needed
476
502
  # All pipes ('|') in the metadata are removed. Title and Text can keep theirs
@@ -486,12 +512,13 @@ module Datadog
486
512
  event_string_data << "|##{tags_string}"
487
513
  end
488
514
 
489
- raise "Event #{title} payload is too big (more that 8KB), event discarded" if event_string_data.length > MAX_EVENT_SIZE
515
+ raise "Event #{title} payload is too big (more that 8KB), event discarded" if event_string_data.bytesize > MAX_EVENT_SIZE
490
516
  event_string_data
491
517
  end
492
518
 
493
519
  def tags_as_string(opts)
494
520
  if tag_arr = opts[:tags]
521
+ tag_arr = tag_hash_to_array(tag_arr) if tag_arr.is_a? Hash
495
522
  tag_arr = tag_arr.map { |tag| escape_tag_content(tag) }
496
523
  tag_arr = tags + tag_arr # @tags are normalized when set, so not need to normalize them again
497
524
  else
@@ -500,6 +527,10 @@ module Datadog
500
527
  tag_arr.join(COMMA) unless tag_arr.empty?
501
528
  end
502
529
 
530
+ def tag_hash_to_array(tag_hash)
531
+ tag_hash.to_a.map {|pair| pair.compact.join(":")}
532
+ end
533
+
503
534
  def escape_event_content(msg)
504
535
  msg.gsub NEW_LINE, ESC_NEW_LINE
505
536
  end
@@ -519,8 +550,8 @@ module Datadog
519
550
  end
520
551
 
521
552
  def send_stats(stat, delta, type, opts=EMPTY_OPTIONS)
522
- sample_rate = opts[:sample_rate] || 1
523
- if sample_rate == 1 or rand < sample_rate
553
+ sample_rate = opts[:sample_rate] || @sample_rate || 1
554
+ if sample_rate == 1 or rand <= sample_rate
524
555
  full_stat = ''.dup
525
556
  full_stat << @prefix if @prefix
526
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.2.0
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: 2019-04-04 00:00:00.000000000 Z
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
@@ -40,7 +40,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
40
40
  - !ruby/object:Gem::Version
41
41
  version: '0'
42
42
  requirements: []
43
- rubygems_version: 3.0.2
43
+ rubyforge_project:
44
+ rubygems_version: 2.7.6
44
45
  signing_key:
45
46
  specification_version: 4
46
47
  summary: A Ruby DogStatsd client