dogstatsd-ruby 4.0.0 → 4.3.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 +28 -4
  3. data/lib/datadog/statsd.rb +80 -45
  4. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6d2b1b9e7ec2a48c5305f6acda103d0b7a09787801dd899a38fb665f5389e4f3
4
- data.tar.gz: 3d974fffb4ace3bc248e69dcdaabb4c556e6783a25d65af98cb65bdccafc52ee
3
+ metadata.gz: b0a17784b24e078a39ee2717d1b7b25d1879e067a5e356db6f98eb012d2bbef2
4
+ data.tar.gz: 9559cb5d04e7b8dee34becbd0adb9182fb1cbda48ae5de13a470cd1d843d4d8d
5
5
  SHA512:
6
- metadata.gz: 16c82cb62bfd324d5e1dc1c6293fa121b92bd0c88d00474210c5da67f2cb07ae350cc0b717b15739c7a6f09e9021323ba348cec70ec2d0ac66a362f15f81007b
7
- data.tar.gz: 6e82cef56d746ecf7b10890d397e313c143611b18b4ae65db67eb2f252cb27acacb45de03f6447b7b4ebb1666209806d6b048fb2857c5c8790f1f6729f4ae806
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,35 +33,19 @@ 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 || DEFAULT_HOST
38
- @port = port || 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
- if retries <= 1 && boom.is_a?(IOError) && boom.message =~ /closed stream/i
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
- 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
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.0.0".freeze
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>] tags tags to be added to every metric
204
- # @option [Loger] logger for debugging
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
- @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
217
238
  @logger = logger
218
239
 
219
240
  @namespace = namespace
220
241
  @prefix = @namespace ? "#{@namespace}.".freeze : nil
221
242
 
222
- 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
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 \n
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.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
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.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
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 < sample_rate
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.0.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: 2018-08-20 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
@@ -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.7
44
+ rubygems_version: 2.7.6
45
45
  signing_key:
46
46
  specification_version: 4
47
47
  summary: A Ruby DogStatsd client