dogstatsd-ruby 4.5.0 → 4.6.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 +32 -79
  3. data/lib/datadog/statsd.rb +95 -29
  4. metadata +9 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fde2be6b614574c2555c8cbbd2ca16ef33bcd09837502f482f5f6baf582fd67b
4
- data.tar.gz: cc1523c5aa78643d93fc891116c46bb5322dda297f1676cd73d201c9beee2a26
3
+ metadata.gz: 7d521571f811d6206670773db4ac3808c02513d8761445ecf917f831578e2614
4
+ data.tar.gz: 97d68494f8520a777569dc8f7b3c04070152aa0924edabc67ffa0ae1f16cb615
5
5
  SHA512:
6
- metadata.gz: 9c96177f1ea0ab2288712cf9829cb8408687e12ce0f22f06ddbb1433447a3a4eaf05fe13f0fda8746b9f0e8fad71ea3b0b50ba7d8a028e464db334349951c64b
7
- data.tar.gz: 11e23d434a7e88925e049484dfbb252d5c78ce12a4a07fd3c09edca57835db30224cba202f86f57352357acdf2073b8c8e93f20bd403975242b201321bef8ecc
6
+ metadata.gz: f43fb9314373873b5d436824a3cae0a5dc0ef4fcc2a458b8a98b98dbd8b12cb28d3b32293436451829a53da8cb70f17c6104aa64403cfb6000822e59a74ca29a
7
+ data.tar.gz: a796456e38da22047d952b7a1bebaf1f923a0847c29a9e7548020c8b658144e729133e7e90a16453d0f48a815353734523870e2e391371d8699f1d6574bd8379
data/README.md CHANGED
@@ -1,86 +1,35 @@
1
+ # dogstatsd-ruby
1
2
 
2
- dogstatsd-ruby
3
- ==============
4
-
5
- A client for DogStatsD, an extension of the StatsD metric server for Datadog.
3
+ A client for DogStatsD, an extension of the StatsD metric server for Datadog. Full API documentation is available in [DogStatsD-ruby rubydoc](https://www.rubydoc.info/github/DataDog/dogstatsd-ruby/master/Datadog/Statsd).
6
4
 
7
5
  [![Build Status](https://secure.travis-ci.org/DataDog/dogstatsd-ruby.svg)](http://travis-ci.org/DataDog/dogstatsd-ruby)
8
6
 
9
- Quick Start Guide
10
- -----------------
11
-
12
- First install the library:
13
-
14
- gem install dogstatsd-ruby
15
-
16
- Then start instrumenting your code:
17
-
18
- ``` ruby
19
- # Load the dogstats module.
20
- require 'datadog/statsd'
21
-
22
- # Create a stats instance.
23
- statsd = Datadog::Statsd.new('localhost', 8125)
24
-
25
- # you could also create a statsd class if you need a drop in replacement
26
- # class Statsd < Datadog::Statsd
27
- # end
7
+ See [CHANGELOG.md](CHANGELOG.md) for changes. To suggest a feature, report a bug, or general discussion, [open an issue](http://github.com/DataDog/dogstatsd-ruby/issues/).
28
8
 
29
- # Increment a counter.
30
- statsd.increment('page.views')
31
- statsd.increment('messages.count', by: 2, tags: ['kind:incoming'])
9
+ ## Installation
32
10
 
33
- # Record a gauge 50% of the time.
34
- statsd.gauge('users.online', 123, sample_rate: 0.5)
35
-
36
- # Sample a histogram
37
- statsd.histogram('file.upload.size', 1234)
38
-
39
- # Time a block of code
40
- statsd.time('page.render') do
41
- render_page('home.html')
42
- end
43
-
44
- # Send several metrics at the same time
45
- # All metrics will be buffered and sent in one packet when the block completes
46
- statsd.batch do |s|
47
- s.increment('page.views')
48
- s.gauge('users.online', 123)
49
- end
50
-
51
- # Tag a metric.
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})
11
+ First install the library:
56
12
 
57
- # Auto-close socket after end of block
58
- Datadog::Statsd.open('localhost', 8125) do |s|
59
- s.increment('page.views')
60
- end
13
+ ```
14
+ gem install dogstatsd-ruby
61
15
  ```
62
16
 
63
- You can also post events to your stream. You can tag them, set priority and even aggregate them with other events.
17
+ ## Configuration
64
18
 
65
- Aggregation in the stream is made on hostname/event_type/source_type/aggregation_key.
19
+ To instantiate a DogStatsd client:
66
20
 
67
- ``` ruby
68
- # Post a simple message
69
- statsd.event('There might be a storm tomorrow', 'A friend warned me earlier.')
21
+ ```ruby
22
+ # Import the library
23
+ require 'datadog/statsd'
70
24
 
71
- # Cry for help
72
- statsd.event(
73
- 'SO MUCH SNOW',
74
- "Started yesterday and it won't stop !!",
75
- alert_type: 'error',
76
- tags: ['urgent', 'endoftheworld']
77
- )
25
+ # Create a DogStatsD client instance.
26
+ statsd = Datadog::Statsd.new('localhost', 8125)
78
27
  ```
79
28
 
29
+ Find a list of all the available options for your DogStatsD Client in the [DogStatsD-ruby rubydoc](https://www.rubydoc.info/github/DataDog/dogstatsd-ruby/master/Datadog/Statsd) or in the [Datadog public DogStatsD documentation](https://docs.datadoghq.com/developers/dogstatsd/?tab=go#client-instantiation-parameters).
80
30
 
31
+ ### Origin detection over UDP
81
32
 
82
- Origin detection over UDP
83
- -------------
84
33
  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
34
 
86
35
  To enable origin detection over UDP, add the following lines to your application manifest
@@ -93,27 +42,31 @@ env:
93
42
  ```
94
43
  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
44
 
45
+ ## Usage
46
+
47
+ In order to use DogStatsD metrics, events, and Service Checks the Agent must be [running and available](https://docs.datadoghq.com/developers/dogstatsd/?tab=ruby).
96
48
 
97
- Documentation
98
- -------------
49
+ ### Metrics
99
50
 
100
- Full API documentation is available
101
- [here](http://www.rubydoc.info/github/DataDog/dogstatsd-ruby/master/frames).
51
+ After the client is created, you can start sending custom metrics to Datadog. See the dedicated [Metric Submission: DogStatsD documentation](https://docs.datadoghq.com/developers/metrics/dogstatsd_metrics_submission/?tab=ruby) to see how to submit all supported metric types to Datadog with working code examples:
102
52
 
53
+ * [Submit a COUNT metric](https://docs.datadoghq.com/developers/metrics/dogstatsd_metrics_submission/?tab=ruby#count).
54
+ * [Submit a GAUGE metric](https://docs.datadoghq.com/developers/metrics/dogstatsd_metrics_submission/?tab=ruby#gauge).
55
+ * [Submit a SET metric](https://docs.datadoghq.com/developers/metrics/dogstatsd_metrics_submission/?tab=ruby#set)
56
+ * [Submit a HISTOGRAM metric](https://docs.datadoghq.com/developers/metrics/dogstatsd_metrics_submission/?tab=ruby#histogram)
57
+ * [Submit a DISTRIBUTION metric](https://docs.datadoghq.com/developers/metrics/dogstatsd_metrics_submission/?tab=ruby#distribution)
103
58
 
104
- Feedback
105
- --------
59
+ Some options are suppported when submitting metrics, like [applying a Sample Rate to your metrics](https://docs.datadoghq.com/developers/metrics/dogstatsd_metrics_submission/?tab=ruby#metric-submission-options) or [tagging your metrics with your custom tags](https://docs.datadoghq.com/developers/metrics/dogstatsd_metrics_submission/?tab=ruby#metric-tagging). Find all the available functions to report metrics in the [DogStatsD-ruby rubydoc](https://www.rubydoc.info/github/DataDog/dogstatsd-ruby/master/Datadog/Statsd).
106
60
 
107
- To suggest a feature, report a bug, or general discussion, head over
108
- [here](http://github.com/DataDog/dogstatsd-ruby/issues/).
61
+ ### Events
109
62
 
63
+ After the client is created, you can start sending events to your Datadog Event Stream. See the dedicated [Event Submission: DogStatsD documentation](https://docs.datadoghq.com/developers/events/dogstatsd/?tab=ruby) to see how to submit an event to Datadog your Event Stream.
110
64
 
111
- [Change Log](CHANGELOG.md)
112
- ----------------------------
65
+ ### Service Checks
113
66
 
67
+ After the client is created, you can start sending Service Checks to Datadog. See the dedicated [Service Check Submission: DogStatsD documentation](https://docs.datadoghq.com/developers/service_checks/dogstatsd_service_checks_submission/?tab=ruby) to see how to submit a Service Check to Datadog.
114
68
 
115
- Credits
116
- -------
69
+ ## Credits
117
70
 
118
71
  dogstatsd-ruby is forked from Rien Henrichs [original Statsd
119
72
  client](https://github.com/reinh/statsd).
@@ -20,6 +20,56 @@ require 'socket'
20
20
  module Datadog
21
21
  class Statsd
22
22
 
23
+ class Telemetry
24
+ attr_accessor :metrics
25
+ attr_accessor :events
26
+ attr_accessor :service_checks
27
+ attr_accessor :bytes_sent
28
+ attr_accessor :bytes_dropped
29
+ attr_accessor :packets_sent
30
+ attr_accessor :packets_dropped
31
+ attr_reader :estimate_max_size
32
+
33
+ def initialize(disabled, tags)
34
+ @disabled = disabled
35
+ @tags = tags
36
+ reset
37
+
38
+ # estimate_max_size is an estimation or the maximum size of the
39
+ # telemetry payload. Since we don't want our packet to go over
40
+ # 'max_buffer_bytes', we have to adjust with the size of the telemetry
41
+ # (and any tags used). The telemetry payload size will change depending
42
+ # on the actual value of metrics: metrics received, packet dropped,
43
+ # etc. This is why we add a 63bytes margin: 9 bytes for each of the 7
44
+ # telemetry metrics.
45
+ @estimate_max_size = @disabled ? 0 : flush().length + 9 * 7
46
+ end
47
+
48
+ def reset
49
+ @metrics = 0
50
+ @events = 0
51
+ @service_checks = 0
52
+ @bytes_sent = 0
53
+ @bytes_dropped = 0
54
+ @packets_sent = 0
55
+ @packets_dropped = 0
56
+ end
57
+
58
+ def flush
59
+ return '' if @disabled
60
+
61
+ # using shorthand syntax to reduce the garbage collection
62
+ return %Q(
63
+ datadog.dogstatsd.client.metrics:#{@metrics}|#{COUNTER_TYPE}|##{@tags}
64
+ datadog.dogstatsd.client.events:#{@events}|#{COUNTER_TYPE}|##{@tags}
65
+ datadog.dogstatsd.client.service_checks:#{@service_checks}|#{COUNTER_TYPE}|##{@tags}
66
+ datadog.dogstatsd.client.bytes_sent:#{@bytes_sent}|#{COUNTER_TYPE}|##{@tags}
67
+ datadog.dogstatsd.client.bytes_dropped:#{@bytes_dropped}|#{COUNTER_TYPE}|##{@tags}
68
+ datadog.dogstatsd.client.packets_sent:#{@packets_sent}|#{COUNTER_TYPE}|##{@tags}
69
+ datadog.dogstatsd.client.packets_dropped:#{@packets_dropped}|#{COUNTER_TYPE}|##{@tags})
70
+ end
71
+ end
72
+
23
73
  class Connection
24
74
  DEFAULT_HOST = '127.0.0.1'
25
75
  DEFAULT_PORT = 8125
@@ -33,6 +83,10 @@ module Datadog
33
83
  # DogStatsd unix socket path. Not used by default.
34
84
  attr_reader :socket_path
35
85
 
86
+ def initialize(telemetry)
87
+ @telemetry = telemetry
88
+ end
89
+
36
90
  # Close the underlying socket
37
91
  def close
38
92
  @socket && @socket.close
@@ -40,7 +94,12 @@ module Datadog
40
94
 
41
95
  def write(message)
42
96
  @logger.debug { "Statsd: #{message}" } if @logger
43
- send_message(message)
97
+ payload = message + @telemetry.flush()
98
+ send_message(payload)
99
+
100
+ @telemetry.reset
101
+ @telemetry.bytes_sent += payload.length
102
+ @telemetry.packets_sent += 1
44
103
  rescue StandardError => boom
45
104
  # Try once to reconnect if the socket has been closed
46
105
  retries ||= 1
@@ -57,6 +116,8 @@ module Datadog
57
116
  end
58
117
  end
59
118
 
119
+ @telemetry.bytes_dropped += payload.length
120
+ @telemetry.packets_dropped += 1
60
121
  @logger.error { "Statsd: #{boom.class} #{boom}" } if @logger
61
122
  nil
62
123
  end
@@ -69,7 +130,8 @@ module Datadog
69
130
  end
70
131
 
71
132
  class UDPConnection < Connection
72
- def initialize(host, port, logger)
133
+ def initialize(host, port, logger, telemetry)
134
+ super(telemetry)
73
135
  @host = host || ENV.fetch('DD_AGENT_HOST', nil) || DEFAULT_HOST
74
136
  @port = port || ENV.fetch('DD_DOGSTATSD_PORT', nil) || DEFAULT_PORT
75
137
  @logger = logger
@@ -91,7 +153,8 @@ module Datadog
91
153
  class UDSConnection < Connection
92
154
  class BadSocketError < StandardError; end
93
155
 
94
- def initialize(socket_path, logger)
156
+ def initialize(socket_path, logger, telemetry)
157
+ super(telemetry)
95
158
  @socket_path = socket_path
96
159
  @logger = logger
97
160
  end
@@ -186,7 +249,8 @@ module Datadog
186
249
  CRITICAL = 2
187
250
  UNKNOWN = 3
188
251
 
189
- MAX_EVENT_SIZE = 8 * 1024
252
+ DEFAULT_BUFFER_SIZE = 8 * 1_024
253
+ MAX_EVENT_SIZE = 8 * 1_024
190
254
 
191
255
  COUNTER_TYPE = 'c'.freeze
192
256
  GAUGE_TYPE = 'g'.freeze
@@ -194,7 +258,7 @@ module Datadog
194
258
  DISTRIBUTION_TYPE = 'd'.freeze
195
259
  TIMING_TYPE = 'ms'.freeze
196
260
  SET_TYPE = 's'.freeze
197
- VERSION = "4.5.0".freeze
261
+ VERSION = "4.6.0".freeze
198
262
 
199
263
  # A namespace to prepend to all statsd calls. Defaults to no namespace.
200
264
  attr_reader :namespace
@@ -227,23 +291,12 @@ module Datadog
227
291
  port = nil,
228
292
  namespace: nil,
229
293
  tags: nil,
230
- max_buffer_bytes: 8192,
294
+ max_buffer_bytes: DEFAULT_BUFFER_SIZE,
231
295
  socket_path: nil,
232
296
  logger: nil,
233
- sample_rate: nil
297
+ sample_rate: nil,
298
+ disable_telemetry: false
234
299
  )
235
- if socket_path.nil?
236
- @connection = UDPConnection.new(host, port, logger)
237
- else
238
- @connection = UDSConnection.new(socket_path, logger)
239
- end
240
- @logger = logger
241
-
242
- @namespace = namespace
243
- @prefix = @namespace ? "#{@namespace}.".freeze : nil
244
-
245
- @sample_rate = sample_rate
246
-
247
300
  unless tags.nil? or tags.is_a? Array or tags.is_a? Hash
248
301
  raise ArgumentError, 'tags must be a Array<String> or a Hash'
249
302
  end
@@ -254,7 +307,25 @@ module Datadog
254
307
  # append the entity id to tags if DD_ENTITY_ID env var is not nil
255
308
  @tags << 'dd.internal.entity_id:' + escape_tag_content(ENV.fetch('DD_ENTITY_ID', nil)) unless ENV.fetch('DD_ENTITY_ID', nil).nil?
256
309
 
257
- @batch = Batch.new @connection, max_buffer_bytes
310
+ # init telemetry
311
+ transport_type = socket_path.nil? ? "udp": "uds"
312
+ telemetry_tags = (["client:ruby", "client_version:#{VERSION}", "client_transport:#{transport_type}"] + @tags).join(COMMA).freeze
313
+ @telemetry = Telemetry.new(disable_telemetry, telemetry_tags)
314
+
315
+ if socket_path.nil?
316
+ @connection = UDPConnection.new(host, port, logger, @telemetry)
317
+ else
318
+ @connection = UDSConnection.new(socket_path, logger, @telemetry)
319
+ end
320
+ @logger = logger
321
+
322
+ @namespace = namespace
323
+ @prefix = @namespace ? "#{@namespace}.".freeze : nil
324
+
325
+ @sample_rate = sample_rate
326
+
327
+ # we reduce max_buffer_bytes by a the rough estimate of the telemetry payload
328
+ @batch = Batch.new(@connection, (max_buffer_bytes - @telemetry.estimate_max_size))
258
329
  end
259
330
 
260
331
  # yield a new instance to a block and close it when done
@@ -338,9 +409,6 @@ module Datadog
338
409
  end
339
410
 
340
411
  # Sends a value to be tracked as a distribution to the statsd server.
341
- # Note: Distributions are a beta feature of Datadog and not generally
342
- # available. Distributions must be specifically enabled for your
343
- # organization.
344
412
  #
345
413
  # @param [String] stat stat name.
346
414
  # @param [Numeric] value distribution value.
@@ -416,6 +484,7 @@ module Datadog
416
484
  # @example Report a critical service check status
417
485
  # $statsd.service_check('my.service.check', Statsd::CRITICAL, :tags=>['urgent'])
418
486
  def service_check(name, status, opts=EMPTY_OPTIONS)
487
+ @telemetry.service_checks += 1
419
488
  send_stat format_service_check(name, status, opts)
420
489
  end
421
490
 
@@ -438,6 +507,7 @@ module Datadog
438
507
  # @example Report an awful event:
439
508
  # $statsd.event('Something terrible happened', 'The end is near if we do nothing', :alert_type=>'warning', :tags=>['end_of_times','urgent'])
440
509
  def event(title, text, opts=EMPTY_OPTIONS)
510
+ @telemetry.events += 1
441
511
  send_stat format_event(title, text, opts)
442
512
  end
443
513
 
@@ -563,6 +633,7 @@ module Datadog
563
633
  end
564
634
 
565
635
  def send_stats(stat, delta, type, opts=EMPTY_OPTIONS)
636
+ @telemetry.metrics += 1
566
637
  sample_rate = opts[:sample_rate] || @sample_rate || 1
567
638
  if sample_rate == 1 or rand <= sample_rate
568
639
  full_stat = ''.dup
@@ -590,17 +661,12 @@ module Datadog
590
661
  full_stat << '#'.freeze
591
662
  full_stat << tags_string
592
663
  end
593
-
594
664
  send_stat(full_stat)
595
665
  end
596
666
  end
597
667
 
598
668
  def send_stat(message)
599
- if @batch.open?
600
- @batch.add message
601
- else
602
- @connection.write(message)
603
- end
669
+ @batch.open? ? @batch.add(message) : @connection.write(message)
604
670
  end
605
671
  end
606
672
  end
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.5.0
4
+ version: 4.6.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-08-22 00:00:00.000000000 Z
11
+ date: 2020-01-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A Ruby DogStastd client
14
14
  email: code@datadoghq.com
@@ -21,10 +21,14 @@ files:
21
21
  - LICENSE.txt
22
22
  - README.md
23
23
  - lib/datadog/statsd.rb
24
- homepage: http://github.com/datadog/dogstatsd-ruby
24
+ homepage: https://github.com/DataDog/dogstatsd-ruby
25
25
  licenses:
26
26
  - MIT
27
- metadata: {}
27
+ metadata:
28
+ bug_tracker_uri: https://github.com/DataDog/dogstatsd-ruby/issues
29
+ changelog_uri: https://github.com/DataDog/dogstatsd-ruby/blob/v4.6.0/CHANGELOG.md
30
+ documentation_uri: https://www.rubydoc.info/gems/dogstatsd-ruby/4.6.0
31
+ source_code_uri: https://github.com/DataDog/dogstatsd-ruby/tree/v4.6.0
28
32
  post_install_message:
29
33
  rdoc_options: []
30
34
  require_paths:
@@ -41,7 +45,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
41
45
  version: '0'
42
46
  requirements: []
43
47
  rubyforge_project:
44
- rubygems_version: 2.7.6
48
+ rubygems_version: 2.7.10
45
49
  signing_key:
46
50
  specification_version: 4
47
51
  summary: A Ruby DogStatsd client