dogstatsd-ruby 5.5.0 → 5.6.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 +11 -1
- data/lib/datadog/statsd/connection.rb +1 -1
- data/lib/datadog/statsd/connection_cfg.rb +56 -7
- data/lib/datadog/statsd/forwarder.rb +7 -2
- data/lib/datadog/statsd/message_buffer.rb +9 -1
- data/lib/datadog/statsd/sender.rb +4 -1
- data/lib/datadog/statsd/single_thread_sender.rb +16 -2
- data/lib/datadog/statsd/version.rb +1 -1
- data/lib/datadog/statsd.rb +11 -2
- metadata +6 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 20363c18876c0641ab23a8cee8d28c22de3e4210420e398d639d6a7b384da168
|
|
4
|
+
data.tar.gz: 851d63e75192dd81451f7a94abba7efe5c81e9c4afdc2dce8102a76e44a10d9a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 72f565700a7ddf32ca56a686617e840c53ad167770be812a66ad6af5d1641c96f89796fe147c1565c38c7d83be14fc638e0f8ce76a00e62e980f43a510826d18
|
|
7
|
+
data.tar.gz: 659bbd4b5b669a11bf62f723387d0263d76a243bda5c6b5de101700b20ad2991d6fd6535832857acdd15b0f809faff80cb1e9f459e1ddacb3262a6be27c4785f
|
data/README.md
CHANGED
|
@@ -183,7 +183,7 @@ There is also an implicit message which closes the queue which will cause the se
|
|
|
183
183
|
statsd = Datadog::Statsd.new('localhost', 8125)
|
|
184
184
|
```
|
|
185
185
|
|
|
186
|
-
The message queue's maximum size (in messages) is given by the `sender_queue_size` argument, and has appropriate defaults for UDP (2048)
|
|
186
|
+
The message queue's maximum size (in messages) is given by the `sender_queue_size` argument, and has appropriate defaults for UDP (2048), UDS (512) and `single_thread: true` (1).
|
|
187
187
|
|
|
188
188
|
The `buffer_flush_interval`, if enabled, is implemented with an additional thread which manages the timing of those flushes. This additional thread is used even if `single_thread: true`.
|
|
189
189
|
|
|
@@ -209,6 +209,16 @@ By default, instances of `Datadog::Statsd` are thread-safe and we recommend that
|
|
|
209
209
|
|
|
210
210
|
When using the `single_thread: true` mode, instances of `Datadog::Statsd` are still thread-safe, but you may run into contention on heavily-threaded applications, so we don’t recommend (for performance reasons) reusing these instances.
|
|
211
211
|
|
|
212
|
+
### Delaying serialization
|
|
213
|
+
|
|
214
|
+
By default, message serialization happens synchronously whenever stat methods such as `#increment` gets called, blocking the caller. If the blocking is impacting your program's performance, you may want to consider the `delay_serialization: true` mode.
|
|
215
|
+
|
|
216
|
+
The `delay_serialization: true` mode delays the serialization of metrics to avoid the wait when submitting metrics. Serialization will still have to happen at some point, but it might be postponed until a more convenient time, such as after an HTTP request has completed.
|
|
217
|
+
|
|
218
|
+
In `single_thread: true` mode, you'll probably want to set `sender_queue_size:` from it's default of `1` to some greater value, so that it can benefit from `delay_serialization: true`. Messages will then be queued unserialized in the sender queue and processed normally whenever `sender_queue_size` is reached or `#flush` is called. You might set `sender_queue_size: Float::INFINITY` to allow for an unbounded queue that will only be processed on explicit `#flush`.
|
|
219
|
+
|
|
220
|
+
In `single_thread: false` mode, `delay_serialization: true`, will cause serialization to happen inside the sender thread.
|
|
221
|
+
|
|
212
222
|
## Versioning
|
|
213
223
|
|
|
214
224
|
This Ruby gem is using [Semantic Versioning](https://guides.rubygems.org/patterns/#semantic-versioning) but please note that supported Ruby versions can change in a minor release of this library.
|
|
@@ -23,12 +23,25 @@ module Datadog
|
|
|
23
23
|
|
|
24
24
|
private
|
|
25
25
|
|
|
26
|
+
ERROR_MESSAGE = "Valid environment variables combination for connection configuration:\n" +
|
|
27
|
+
" - DD_DOGSTATSD_URL for UDP or UDS connection.\n" +
|
|
28
|
+
" Example for UDP: DD_DOGSTATSD_URL='udp://localhost:8125'\n" +
|
|
29
|
+
" Example for UDS: DD_DOGSTATSD_URL='unix:///path/to/unix.sock'\n" +
|
|
30
|
+
" or\n" +
|
|
31
|
+
" - DD_AGENT_HOST and DD_DOGSTATSD_PORT for an UDP connection. E.g. DD_AGENT_HOST='localhost' DD_DOGSTATSD_PORT=8125\n" +
|
|
32
|
+
" or\n" +
|
|
33
|
+
" - DD_DOGSTATSD_SOCKET for an UDS connection: E.g. DD_DOGSTATSD_SOCKET='/path/to/unix.sock'\n" +
|
|
34
|
+
" Note that DD_DOGSTATSD_URL has priority on other environment variables."
|
|
35
|
+
|
|
26
36
|
DEFAULT_HOST = '127.0.0.1'
|
|
27
37
|
DEFAULT_PORT = 8125
|
|
28
38
|
|
|
39
|
+
UDP_PREFIX = 'udp://'
|
|
40
|
+
UDS_PREFIX = 'unix://'
|
|
41
|
+
|
|
29
42
|
def initialize_with_constructor_args(host: nil, port: nil, socket_path: nil)
|
|
30
43
|
try_initialize_with(host: host, port: port, socket_path: socket_path,
|
|
31
|
-
|
|
44
|
+
error_message:
|
|
32
45
|
"Both UDP: (host/port #{host}:#{port}) and UDS (socket_path #{socket_path}) " +
|
|
33
46
|
"constructor arguments were given. Use only one or the other.",
|
|
34
47
|
)
|
|
@@ -36,13 +49,11 @@ module Datadog
|
|
|
36
49
|
|
|
37
50
|
def initialize_with_env_vars()
|
|
38
51
|
try_initialize_with(
|
|
52
|
+
dogstatsd_url: ENV['DD_DOGSTATSD_URL'],
|
|
39
53
|
host: ENV['DD_AGENT_HOST'],
|
|
40
54
|
port: ENV['DD_DOGSTATSD_PORT'] && ENV['DD_DOGSTATSD_PORT'].to_i,
|
|
41
55
|
socket_path: ENV['DD_DOGSTATSD_SOCKET'],
|
|
42
|
-
|
|
43
|
-
"Both UDP (DD_AGENT_HOST/DD_DOGSTATSD_PORT #{ENV['DD_AGENT_HOST']}:#{ENV['DD_DOGSTATSD_PORT']}) " +
|
|
44
|
-
"and UDS (DD_DOGSTATSD_SOCKET #{ENV['DD_DOGSTATSD_SOCKET']}) environment variables are set. " +
|
|
45
|
-
"Set only one or the other.",
|
|
56
|
+
error_message: ERROR_MESSAGE,
|
|
46
57
|
)
|
|
47
58
|
end
|
|
48
59
|
|
|
@@ -50,9 +61,13 @@ module Datadog
|
|
|
50
61
|
try_initialize_with(host: DEFAULT_HOST, port: DEFAULT_PORT)
|
|
51
62
|
end
|
|
52
63
|
|
|
53
|
-
def try_initialize_with(host: nil, port: nil, socket_path: nil,
|
|
64
|
+
def try_initialize_with(dogstatsd_url: nil, host: nil, port: nil, socket_path: nil, error_message: ERROR_MESSAGE)
|
|
54
65
|
if (host || port) && socket_path
|
|
55
|
-
raise ArgumentError,
|
|
66
|
+
raise ArgumentError, error_message
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
if dogstatsd_url
|
|
70
|
+
host, port, socket_path = parse_dogstatsd_url(str: dogstatsd_url.to_s)
|
|
56
71
|
end
|
|
57
72
|
|
|
58
73
|
if host || port
|
|
@@ -71,6 +86,40 @@ module Datadog
|
|
|
71
86
|
|
|
72
87
|
return false
|
|
73
88
|
end
|
|
89
|
+
|
|
90
|
+
def parse_dogstatsd_url(str:)
|
|
91
|
+
# udp socket connection
|
|
92
|
+
|
|
93
|
+
if str.start_with?(UDP_PREFIX)
|
|
94
|
+
dogstatsd_url = str[UDP_PREFIX.size..str.size]
|
|
95
|
+
host = nil
|
|
96
|
+
port = nil
|
|
97
|
+
|
|
98
|
+
if dogstatsd_url.include?(":")
|
|
99
|
+
parts = dogstatsd_url.split(":")
|
|
100
|
+
if parts.size > 2
|
|
101
|
+
raise ArgumentError, "Error: DD_DOGSTATSD_URL wrong format for an UDP connection. E.g. 'udp://localhost:8125'"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
host = parts[0]
|
|
105
|
+
port = parts[1].to_i
|
|
106
|
+
else
|
|
107
|
+
host = dogstatsd_url
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
return host, port, nil
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# unix socket connection
|
|
114
|
+
|
|
115
|
+
if str.start_with?(UDS_PREFIX)
|
|
116
|
+
return nil, nil, str[UDS_PREFIX.size..str.size]
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# malformed value
|
|
120
|
+
|
|
121
|
+
raise ArgumentError, "Error: DD_DOGSTATSD_URL has been provided but is not starting with 'udp://' nor 'unix://'"
|
|
122
|
+
end
|
|
74
123
|
end
|
|
75
124
|
end
|
|
76
125
|
end
|
|
@@ -21,7 +21,9 @@ module Datadog
|
|
|
21
21
|
|
|
22
22
|
single_thread: false,
|
|
23
23
|
|
|
24
|
-
logger: nil
|
|
24
|
+
logger: nil,
|
|
25
|
+
|
|
26
|
+
serializer:
|
|
25
27
|
)
|
|
26
28
|
@transport_type = connection_cfg.transport_type
|
|
27
29
|
|
|
@@ -52,8 +54,10 @@ module Datadog
|
|
|
52
54
|
max_payload_size: buffer_max_payload_size,
|
|
53
55
|
max_pool_size: buffer_max_pool_size || DEFAULT_BUFFER_POOL_SIZE,
|
|
54
56
|
overflowing_stategy: buffer_overflowing_stategy,
|
|
57
|
+
serializer: serializer
|
|
55
58
|
)
|
|
56
59
|
|
|
60
|
+
sender_queue_size ||= 1 if single_thread
|
|
57
61
|
sender_queue_size ||= (@transport_type == :udp ?
|
|
58
62
|
UDP_DEFAULT_SENDER_QUEUE_SIZE : UDS_DEFAULT_SENDER_QUEUE_SIZE)
|
|
59
63
|
|
|
@@ -61,7 +65,8 @@ module Datadog
|
|
|
61
65
|
SingleThreadSender.new(
|
|
62
66
|
buffer,
|
|
63
67
|
logger: logger,
|
|
64
|
-
flush_interval: buffer_flush_interval
|
|
68
|
+
flush_interval: buffer_flush_interval,
|
|
69
|
+
queue_size: sender_queue_size) :
|
|
65
70
|
Sender.new(
|
|
66
71
|
buffer,
|
|
67
72
|
logger: logger,
|
|
@@ -8,7 +8,8 @@ module Datadog
|
|
|
8
8
|
def initialize(connection,
|
|
9
9
|
max_payload_size: nil,
|
|
10
10
|
max_pool_size: DEFAULT_BUFFER_POOL_SIZE,
|
|
11
|
-
overflowing_stategy: :drop
|
|
11
|
+
overflowing_stategy: :drop,
|
|
12
|
+
serializer:
|
|
12
13
|
)
|
|
13
14
|
raise ArgumentError, 'max_payload_size keyword argument must be provided' unless max_payload_size
|
|
14
15
|
raise ArgumentError, 'max_pool_size keyword argument must be provided' unless max_pool_size
|
|
@@ -17,12 +18,19 @@ module Datadog
|
|
|
17
18
|
@max_payload_size = max_payload_size
|
|
18
19
|
@max_pool_size = max_pool_size
|
|
19
20
|
@overflowing_stategy = overflowing_stategy
|
|
21
|
+
@serializer = serializer
|
|
20
22
|
|
|
21
23
|
@buffer = String.new
|
|
22
24
|
clear_buffer
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
def add(message)
|
|
28
|
+
# Serializes the message if it hasn't been already. Part of the
|
|
29
|
+
# delay_serialization feature.
|
|
30
|
+
if message.is_a?(Array)
|
|
31
|
+
message = @serializer.to_stat(*message[0], **message[1])
|
|
32
|
+
end
|
|
33
|
+
|
|
26
34
|
message_size = message.bytesize
|
|
27
35
|
|
|
28
36
|
return nil unless message_size > 0 # to avoid adding empty messages to the buffer
|
|
@@ -84,7 +84,10 @@ module Datadog
|
|
|
84
84
|
if message_queue.length <= @queue_size
|
|
85
85
|
message_queue << message
|
|
86
86
|
else
|
|
87
|
-
|
|
87
|
+
if @telemetry
|
|
88
|
+
bytesize = message.respond_to?(:bytesize) ? message.bytesize : 0
|
|
89
|
+
@telemetry.dropped_queue(packets: 1, bytes: bytesize)
|
|
90
|
+
end
|
|
88
91
|
end
|
|
89
92
|
end
|
|
90
93
|
|
|
@@ -7,10 +7,12 @@ module Datadog
|
|
|
7
7
|
# It is using current Process.PID to check it is the result of a recent fork
|
|
8
8
|
# and it is reseting the MessageBuffer if that's the case.
|
|
9
9
|
class SingleThreadSender
|
|
10
|
-
def initialize(message_buffer, logger: nil, flush_interval: nil)
|
|
10
|
+
def initialize(message_buffer, logger: nil, flush_interval: nil, queue_size: 1)
|
|
11
11
|
@message_buffer = message_buffer
|
|
12
12
|
@logger = logger
|
|
13
13
|
@mx = Mutex.new
|
|
14
|
+
@message_queue_size = queue_size
|
|
15
|
+
@message_queue = []
|
|
14
16
|
@flush_timer = if flush_interval
|
|
15
17
|
Datadog::Statsd::Timer.new(flush_interval) { flush }
|
|
16
18
|
else
|
|
@@ -26,15 +28,21 @@ module Datadog
|
|
|
26
28
|
# not send, they belong to the parent process, let's clear the buffer.
|
|
27
29
|
if forked?
|
|
28
30
|
@message_buffer.reset
|
|
31
|
+
@message_queue.clear
|
|
29
32
|
@flush_timer.start if @flush_timer && @flush_timer.stop?
|
|
30
33
|
update_fork_pid
|
|
31
34
|
end
|
|
32
|
-
|
|
35
|
+
|
|
36
|
+
@message_queue << message
|
|
37
|
+
if @message_queue.size >= @message_queue_size
|
|
38
|
+
drain_message_queue
|
|
39
|
+
end
|
|
33
40
|
}
|
|
34
41
|
end
|
|
35
42
|
|
|
36
43
|
def flush(*)
|
|
37
44
|
@mx.synchronize {
|
|
45
|
+
drain_message_queue
|
|
38
46
|
@message_buffer.flush()
|
|
39
47
|
}
|
|
40
48
|
end
|
|
@@ -53,6 +61,12 @@ module Datadog
|
|
|
53
61
|
|
|
54
62
|
private
|
|
55
63
|
|
|
64
|
+
def drain_message_queue
|
|
65
|
+
while msg = @message_queue.shift
|
|
66
|
+
@message_buffer.add(msg)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
56
70
|
# below are "fork management" methods to be able to clean the MessageBuffer
|
|
57
71
|
# if it detects that it is running in a unknown PID.
|
|
58
72
|
|
data/lib/datadog/statsd.rb
CHANGED
|
@@ -76,11 +76,12 @@ module Datadog
|
|
|
76
76
|
# @option [Logger] logger for debugging
|
|
77
77
|
# @option [Integer] buffer_max_payload_size max bytes to buffer
|
|
78
78
|
# @option [Integer] buffer_max_pool_size max messages to buffer
|
|
79
|
-
# @option [Integer] sender_queue_size size of the sender queue in number of buffers
|
|
79
|
+
# @option [Integer] sender_queue_size size of the sender queue in number of buffers
|
|
80
80
|
# @option [Numeric] buffer_flush_interval interval in second to flush buffer
|
|
81
81
|
# @option [String] socket_path unix socket path
|
|
82
82
|
# @option [Float] default sample rate if not overridden
|
|
83
83
|
# @option [Boolean] single_thread flushes the metrics on the main thread instead of in a companion thread
|
|
84
|
+
# @option [Boolean] delay_serialization delays stat serialization
|
|
84
85
|
def initialize(
|
|
85
86
|
host = nil,
|
|
86
87
|
port = nil,
|
|
@@ -100,6 +101,7 @@ module Datadog
|
|
|
100
101
|
logger: nil,
|
|
101
102
|
|
|
102
103
|
single_thread: false,
|
|
104
|
+
delay_serialization: false,
|
|
103
105
|
|
|
104
106
|
telemetry_enable: true,
|
|
105
107
|
telemetry_flush_interval: DEFAULT_TELEMETRY_FLUSH_INTERVAL
|
|
@@ -112,6 +114,7 @@ module Datadog
|
|
|
112
114
|
@prefix = @namespace ? "#{@namespace}.".freeze : nil
|
|
113
115
|
@serializer = Serialization::Serializer.new(prefix: @prefix, global_tags: tags)
|
|
114
116
|
@sample_rate = sample_rate
|
|
117
|
+
@delay_serialization = delay_serialization
|
|
115
118
|
|
|
116
119
|
@forwarder = Forwarder.new(
|
|
117
120
|
connection_cfg: ConnectionCfg.new(
|
|
@@ -133,6 +136,7 @@ module Datadog
|
|
|
133
136
|
sender_queue_size: sender_queue_size,
|
|
134
137
|
|
|
135
138
|
telemetry_flush_interval: telemetry_enable ? telemetry_flush_interval : nil,
|
|
139
|
+
serializer: serializer
|
|
136
140
|
)
|
|
137
141
|
end
|
|
138
142
|
|
|
@@ -425,7 +429,12 @@ module Datadog
|
|
|
425
429
|
sample_rate = opts[:sample_rate] || @sample_rate || 1
|
|
426
430
|
|
|
427
431
|
if sample_rate == 1 || opts[:pre_sampled] || rand <= sample_rate
|
|
428
|
-
full_stat =
|
|
432
|
+
full_stat =
|
|
433
|
+
if @delay_serialization
|
|
434
|
+
[[stat, delta, type], {tags: opts[:tags], sample_rate: sample_rate}]
|
|
435
|
+
else
|
|
436
|
+
serializer.to_stat(stat, delta, type, tags: opts[:tags], sample_rate: sample_rate)
|
|
437
|
+
end
|
|
429
438
|
|
|
430
439
|
forwarder.send_message(full_stat)
|
|
431
440
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dogstatsd-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.
|
|
4
|
+
version: 5.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rein Henrichs
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date:
|
|
12
|
+
date: 2023-07-10 00:00:00.000000000 Z
|
|
13
13
|
dependencies: []
|
|
14
14
|
description: A Ruby DogStatsd client
|
|
15
15
|
email: code@datadoghq.com
|
|
@@ -44,9 +44,9 @@ licenses:
|
|
|
44
44
|
- MIT
|
|
45
45
|
metadata:
|
|
46
46
|
bug_tracker_uri: https://github.com/DataDog/dogstatsd-ruby/issues
|
|
47
|
-
changelog_uri: https://github.com/DataDog/dogstatsd-ruby/blob/v5.
|
|
48
|
-
documentation_uri: https://www.rubydoc.info/gems/dogstatsd-ruby/5.
|
|
49
|
-
source_code_uri: https://github.com/DataDog/dogstatsd-ruby/tree/v5.
|
|
47
|
+
changelog_uri: https://github.com/DataDog/dogstatsd-ruby/blob/v5.6.0/CHANGELOG.md
|
|
48
|
+
documentation_uri: https://www.rubydoc.info/gems/dogstatsd-ruby/5.6.0
|
|
49
|
+
source_code_uri: https://github.com/DataDog/dogstatsd-ruby/tree/v5.6.0
|
|
50
50
|
post_install_message: |2+
|
|
51
51
|
|
|
52
52
|
If you are upgrading from v4.x of the dogstatsd-ruby library, note the major change to the threading model:
|
|
@@ -66,8 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
67
|
version: '0'
|
|
68
68
|
requirements: []
|
|
69
|
-
|
|
70
|
-
rubygems_version: 2.7.10
|
|
69
|
+
rubygems_version: 3.2.3
|
|
71
70
|
signing_key:
|
|
72
71
|
specification_version: 4
|
|
73
72
|
summary: A Ruby DogStatsd client
|