ddtrace 0.52.0 → 0.54.2
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/CHANGELOG.md +174 -11
- data/ddtrace.gemspec +6 -3
- data/docs/DevelopmentGuide.md +1 -6
- data/docs/GettingStarted.md +109 -18
- data/docs/ProfilingDevelopment.md +2 -2
- data/ext/ddtrace_profiling_native_extension/NativeExtensionDesign.md +86 -0
- data/ext/ddtrace_profiling_native_extension/clock_id.h +4 -0
- data/ext/ddtrace_profiling_native_extension/clock_id_from_pthread.c +52 -0
- data/ext/ddtrace_profiling_native_extension/clock_id_noop.c +14 -0
- data/ext/ddtrace_profiling_native_extension/extconf.rb +177 -8
- data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +35 -0
- data/ext/ddtrace_profiling_native_extension/private_vm_api_access.h +3 -0
- data/ext/ddtrace_profiling_native_extension/profiling.c +6 -1
- data/lib/datadog/ci/contrib/cucumber/formatter.rb +1 -0
- data/lib/datadog/ci/contrib/rspec/example.rb +1 -0
- data/lib/datadog/ci/contrib/rspec/integration.rb +2 -2
- data/lib/datadog/ci/ext/environment.rb +64 -22
- data/lib/datadog/ci/ext/test.rb +1 -0
- data/lib/datadog/ci/test.rb +5 -1
- data/lib/datadog/contrib.rb +2 -0
- data/lib/datadog/core/environment/vm_cache.rb +46 -0
- data/lib/ddtrace/buffer.rb +28 -16
- data/lib/ddtrace/configuration/agent_settings_resolver.rb +131 -53
- data/lib/ddtrace/configuration/components.rb +1 -1
- data/lib/ddtrace/configuration/settings.rb +13 -3
- data/lib/ddtrace/context.rb +10 -2
- data/lib/ddtrace/contrib/action_cable/instrumentation.rb +46 -0
- data/lib/ddtrace/contrib/action_cable/patcher.rb +1 -0
- data/lib/ddtrace/contrib/action_mailer/configuration/settings.rb +32 -0
- data/lib/ddtrace/contrib/action_mailer/event.rb +50 -0
- data/lib/ddtrace/contrib/action_mailer/events/deliver.rb +54 -0
- data/lib/ddtrace/contrib/action_mailer/events/process.rb +41 -0
- data/lib/ddtrace/contrib/action_mailer/events.rb +31 -0
- data/lib/ddtrace/contrib/action_mailer/ext.rb +32 -0
- data/lib/ddtrace/contrib/action_mailer/integration.rb +45 -0
- data/lib/ddtrace/contrib/action_mailer/patcher.rb +27 -0
- data/lib/ddtrace/contrib/active_job/configuration/settings.rb +33 -0
- data/lib/ddtrace/contrib/active_job/event.rb +54 -0
- data/lib/ddtrace/contrib/active_job/events/discard.rb +46 -0
- data/lib/ddtrace/contrib/active_job/events/enqueue.rb +45 -0
- data/lib/ddtrace/contrib/active_job/events/enqueue_at.rb +45 -0
- data/lib/ddtrace/contrib/active_job/events/enqueue_retry.rb +47 -0
- data/lib/ddtrace/contrib/active_job/events/perform.rb +45 -0
- data/lib/ddtrace/contrib/active_job/events/retry_stopped.rb +46 -0
- data/lib/ddtrace/contrib/active_job/events.rb +39 -0
- data/lib/ddtrace/contrib/active_job/ext.rb +32 -0
- data/lib/ddtrace/contrib/active_job/integration.rb +46 -0
- data/lib/ddtrace/contrib/active_job/log_injection.rb +21 -0
- data/lib/ddtrace/contrib/active_job/patcher.rb +33 -0
- data/lib/ddtrace/contrib/auto_instrument.rb +0 -1
- data/lib/ddtrace/contrib/delayed_job/plugin.rb +2 -2
- data/lib/ddtrace/contrib/mongodb/instrumentation.rb +1 -1
- data/lib/ddtrace/contrib/mongodb/integration.rb +5 -0
- data/lib/ddtrace/contrib/rails/auto_instrument_railtie.rb +0 -1
- data/lib/ddtrace/contrib/rails/configuration/settings.rb +7 -0
- data/lib/ddtrace/contrib/rails/framework.rb +24 -1
- data/lib/ddtrace/contrib/rails/patcher.rb +19 -10
- data/lib/ddtrace/contrib/redis/instrumentation.rb +90 -0
- data/lib/ddtrace/contrib/redis/patcher.rb +2 -84
- data/lib/ddtrace/contrib/registerable.rb +0 -1
- data/lib/ddtrace/contrib/resque/integration.rb +1 -5
- data/lib/ddtrace/contrib/sidekiq/ext.rb +3 -0
- data/lib/ddtrace/contrib/sidekiq/integration.rb +10 -0
- data/lib/ddtrace/contrib/sidekiq/patcher.rb +26 -0
- data/lib/ddtrace/contrib/sidekiq/server_internal_tracer/heartbeat.rb +30 -0
- data/lib/ddtrace/contrib/sidekiq/server_internal_tracer/job_fetch.rb +30 -0
- data/lib/ddtrace/contrib/sidekiq/server_internal_tracer/scheduled_push.rb +29 -0
- data/lib/ddtrace/contrib/sinatra/env.rb +2 -1
- data/lib/ddtrace/contrib/sinatra/tracer.rb +15 -2
- data/lib/ddtrace/ext/git.rb +12 -0
- data/lib/ddtrace/ext/priority.rb +6 -4
- data/lib/ddtrace/ext/profiling.rb +8 -11
- data/lib/ddtrace/ext/runtime.rb +3 -0
- data/lib/ddtrace/ext/transport.rb +11 -0
- data/lib/ddtrace/metrics.rb +2 -2
- data/lib/ddtrace/profiling/collectors/stack.rb +112 -72
- data/lib/ddtrace/profiling/encoding/profile.rb +10 -2
- data/lib/ddtrace/profiling/events/stack.rb +13 -13
- data/lib/ddtrace/profiling/native_extension.rb +23 -1
- data/lib/ddtrace/profiling/pprof/builder.rb +8 -2
- data/lib/ddtrace/profiling/pprof/converter.rb +22 -9
- data/lib/ddtrace/profiling/pprof/stack_sample.rb +32 -9
- data/lib/ddtrace/profiling/pprof/template.rb +2 -2
- data/lib/ddtrace/profiling/scheduler.rb +20 -4
- data/lib/ddtrace/profiling/tasks/setup.rb +21 -13
- data/lib/ddtrace/profiling/trace_identifiers/ddtrace.rb +10 -9
- data/lib/ddtrace/profiling/trace_identifiers/helper.rb +5 -5
- data/lib/ddtrace/profiling/transport/http/api/endpoint.rb +8 -15
- data/lib/ddtrace/profiling/transport/http.rb +8 -17
- data/lib/ddtrace/profiling.rb +0 -2
- data/lib/ddtrace/runtime/metrics.rb +14 -0
- data/lib/ddtrace/sampler.rb +18 -8
- data/lib/ddtrace/sampling/rule_sampler.rb +13 -1
- data/lib/ddtrace/span.rb +7 -19
- data/lib/ddtrace/tracer.rb +1 -1
- data/lib/ddtrace/transport/http/adapters/net.rb +13 -3
- data/lib/ddtrace/transport/http/adapters/test.rb +4 -2
- data/lib/ddtrace/transport/http/adapters/unix_socket.rb +23 -12
- data/lib/ddtrace/transport/http/builder.rb +13 -6
- data/lib/ddtrace/transport/http.rb +5 -11
- data/lib/ddtrace/utils/time.rb +11 -6
- data/lib/ddtrace/version.rb +2 -2
- data/lib/ddtrace/workers/{loop.rb → interval_loop.rb} +0 -16
- data/lib/ddtrace/workers/polling.rb +1 -1
- metadata +40 -10
- data/lib/ddtrace/profiling/ext/cpu.rb +0 -67
- data/lib/ddtrace/profiling/ext/cthread.rb +0 -156
data/lib/datadog/contrib.rb
CHANGED
|
@@ -26,9 +26,11 @@ module Datadog
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
require 'ddtrace/contrib/action_cable/integration'
|
|
29
|
+
require 'ddtrace/contrib/action_mailer/integration'
|
|
29
30
|
require 'ddtrace/contrib/action_pack/integration'
|
|
30
31
|
require 'ddtrace/contrib/action_view/integration'
|
|
31
32
|
require 'ddtrace/contrib/active_model_serializers/integration'
|
|
33
|
+
require 'ddtrace/contrib/active_job/integration'
|
|
32
34
|
require 'ddtrace/contrib/active_record/integration'
|
|
33
35
|
require 'ddtrace/contrib/active_support/integration'
|
|
34
36
|
require 'ddtrace/contrib/aws/integration'
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
module Datadog
|
|
3
|
+
module Core
|
|
4
|
+
module Environment
|
|
5
|
+
# Reports Ruby VM cache performance statistics.
|
|
6
|
+
# This currently encompasses cache invalidation counters and is CRuby-specific.
|
|
7
|
+
#
|
|
8
|
+
# JRuby emulates some CRuby global cache statistics, but they are synthetic and don't
|
|
9
|
+
# provide actionable performance information in the same way CRuby does.
|
|
10
|
+
# @see https://github.com/jruby/jruby/issues/4384#issuecomment-267069314
|
|
11
|
+
#
|
|
12
|
+
# TruffleRuby does not have a global runtime cache invalidation cache.
|
|
13
|
+
# @see http://archive.today/2021.09.10-205702/https://medium.com/graalvm/precise-method-and-constant-invalidation-in-truffleruby-4dd56c6bac1a
|
|
14
|
+
module VMCache
|
|
15
|
+
module_function
|
|
16
|
+
|
|
17
|
+
# Global constant cache "generation" counter.
|
|
18
|
+
#
|
|
19
|
+
# Whenever a constant creation busts the global constant cache
|
|
20
|
+
# this value is incremented. This has a measurable performance impact
|
|
21
|
+
# and thus show be avoided after application warm up.
|
|
22
|
+
def global_constant_state
|
|
23
|
+
::RubyVM.stat[:global_constant_state]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Global method cache "generation" counter.
|
|
27
|
+
#
|
|
28
|
+
# Whenever a method creation busts the global method cache
|
|
29
|
+
# this value is incremented. This has a measurable performance impact
|
|
30
|
+
# and thus show be avoided after application warm up.
|
|
31
|
+
#
|
|
32
|
+
# Since Ruby 3.0, the method class is kept on a per-class basis,
|
|
33
|
+
# largely mitigating global method cache busting. `global_method_state`
|
|
34
|
+
# is thus not available since Ruby 3.0.
|
|
35
|
+
# @see https://bugs.ruby-lang.org/issues/16614
|
|
36
|
+
def global_method_state
|
|
37
|
+
::RubyVM.stat[:global_method_state]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def available?
|
|
41
|
+
defined?(::RubyVM) && ::RubyVM.respond_to?(:stat)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
data/lib/ddtrace/buffer.rb
CHANGED
|
@@ -14,7 +14,11 @@ module Datadog
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
# Add a new ``item`` in the local queue. This method doesn't block the execution
|
|
17
|
-
# even if the buffer is full.
|
|
17
|
+
# even if the buffer is full.
|
|
18
|
+
#
|
|
19
|
+
# When the buffer is full, we try to ensure that we are fairly sampling newly
|
|
20
|
+
# pushed traces by randomly inserting them into the buffer slots. This discards
|
|
21
|
+
# old traces randomly while trying to ensure that recent traces are still captured.
|
|
18
22
|
def push(item)
|
|
19
23
|
return if closed?
|
|
20
24
|
|
|
@@ -64,7 +68,7 @@ module Datadog
|
|
|
64
68
|
|
|
65
69
|
protected
|
|
66
70
|
|
|
67
|
-
# Segment items into two
|
|
71
|
+
# Segment items into two segments: underflow and overflow.
|
|
68
72
|
# Underflow are items that will fit into buffer.
|
|
69
73
|
# Overflow are items that will exceed capacity, after underflow is added.
|
|
70
74
|
# Returns each array, and nil if there is no underflow/overflow.
|
|
@@ -176,9 +180,6 @@ module Datadog
|
|
|
176
180
|
# Buffer that stores objects, has a maximum size, and
|
|
177
181
|
# can be safely used concurrently with CRuby.
|
|
178
182
|
#
|
|
179
|
-
# Under extreme concurrency scenarios, this class can exceed
|
|
180
|
-
# its +max_size+ by up to 4%.
|
|
181
|
-
#
|
|
182
183
|
# Because singular +Array+ operations are thread-safe in CRuby,
|
|
183
184
|
# we can implement the trace buffer without an explicit lock,
|
|
184
185
|
# while making the compromise of allowing the buffer to go
|
|
@@ -187,7 +188,6 @@ module Datadog
|
|
|
187
188
|
# On the following scenario:
|
|
188
189
|
# * 4.5 million spans/second.
|
|
189
190
|
# * Pushed into a single CRubyTraceBuffer from 1000 threads.
|
|
190
|
-
# The buffer can exceed its maximum size by no more than 4%.
|
|
191
191
|
#
|
|
192
192
|
# This implementation allocates less memory and is faster
|
|
193
193
|
# than {Datadog::ThreadSafeBuffer}.
|
|
@@ -195,19 +195,31 @@ module Datadog
|
|
|
195
195
|
# @see spec/ddtrace/benchmark/buffer_benchmark_spec.rb Buffer benchmarks
|
|
196
196
|
# @see https://github.com/ruby-concurrency/concurrent-ruby/blob/c1114a0c6891d9634f019f1f9fe58dcae8658964/lib/concurrent-ruby/concurrent/array.rb#L23-L27
|
|
197
197
|
class CRubyBuffer < Buffer
|
|
198
|
+
# A very large number to allow us to effectively
|
|
199
|
+
# drop all items when invoking `slice!(i, FIXNUM_MAX)`.
|
|
200
|
+
FIXNUM_MAX = (1 << 62) - 1
|
|
201
|
+
|
|
198
202
|
# Add a new ``trace`` in the local queue. This method doesn't block the execution
|
|
199
203
|
# even if the buffer is full. In that case, a random trace is discarded.
|
|
200
204
|
def replace!(item)
|
|
201
|
-
#
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
# We
|
|
207
|
-
#
|
|
208
|
-
#
|
|
209
|
-
# performed
|
|
210
|
-
|
|
205
|
+
# Ensure buffer stays within +max_size+ items.
|
|
206
|
+
# This can happen when there's concurrent modification
|
|
207
|
+
# between a call the check in `full?` and the `add!` call in
|
|
208
|
+
# `full? ? replace!(item) : add!(item)`.
|
|
209
|
+
#
|
|
210
|
+
# We can still have `@items.size > @max_size` for a short period of
|
|
211
|
+
# time, but we will always try to correct it here.
|
|
212
|
+
#
|
|
213
|
+
# `slice!` is performed before `delete_at` & `<<` to avoid always
|
|
214
|
+
# removing the item that was just inserted.
|
|
215
|
+
#
|
|
216
|
+
# DEV: `slice!` with two integer arguments is ~10% faster than
|
|
217
|
+
# `slice!` with a {Range} argument.
|
|
218
|
+
@items.slice!(@max_size, FIXNUM_MAX)
|
|
219
|
+
|
|
220
|
+
# We should replace a random trace with the new one
|
|
221
|
+
replace_index = rand(@max_size)
|
|
222
|
+
@items[replace_index] = item
|
|
211
223
|
end
|
|
212
224
|
end
|
|
213
225
|
|
|
@@ -20,25 +20,49 @@ module Datadog
|
|
|
20
20
|
class AgentSettingsResolver
|
|
21
21
|
AgentSettings = \
|
|
22
22
|
Struct.new(
|
|
23
|
+
:adapter,
|
|
23
24
|
:ssl,
|
|
24
25
|
:hostname,
|
|
25
26
|
:port,
|
|
27
|
+
:uds_path,
|
|
26
28
|
:timeout_seconds,
|
|
27
29
|
:deprecated_for_removal_transport_configuration_proc,
|
|
28
30
|
:deprecated_for_removal_transport_configuration_options
|
|
29
31
|
) do
|
|
30
32
|
def initialize(
|
|
33
|
+
adapter:,
|
|
31
34
|
ssl:,
|
|
32
35
|
hostname:,
|
|
33
36
|
port:,
|
|
37
|
+
uds_path:,
|
|
34
38
|
timeout_seconds:,
|
|
35
39
|
deprecated_for_removal_transport_configuration_proc:,
|
|
36
40
|
deprecated_for_removal_transport_configuration_options:
|
|
37
41
|
)
|
|
38
|
-
super(
|
|
39
|
-
|
|
42
|
+
super(
|
|
43
|
+
adapter,
|
|
44
|
+
ssl,
|
|
45
|
+
hostname,
|
|
46
|
+
port,
|
|
47
|
+
uds_path,
|
|
48
|
+
timeout_seconds,
|
|
49
|
+
deprecated_for_removal_transport_configuration_proc,
|
|
50
|
+
deprecated_for_removal_transport_configuration_options,
|
|
51
|
+
)
|
|
40
52
|
freeze
|
|
41
53
|
end
|
|
54
|
+
|
|
55
|
+
# Returns a frozen copy of this struct
|
|
56
|
+
# with the provided +member_values+ modified.
|
|
57
|
+
def merge(**member_values)
|
|
58
|
+
new_struct = dup
|
|
59
|
+
|
|
60
|
+
member_values.each do |member, value|
|
|
61
|
+
new_struct[member] = value
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
new_struct.freeze
|
|
65
|
+
end
|
|
42
66
|
end
|
|
43
67
|
|
|
44
68
|
def self.call(settings, logger: Datadog.logger)
|
|
@@ -58,9 +82,11 @@ module Datadog
|
|
|
58
82
|
|
|
59
83
|
def call
|
|
60
84
|
AgentSettings.new(
|
|
85
|
+
adapter: adapter,
|
|
61
86
|
ssl: ssl?,
|
|
62
87
|
hostname: hostname,
|
|
63
88
|
port: port,
|
|
89
|
+
uds_path: uds_path,
|
|
64
90
|
timeout_seconds: timeout_seconds,
|
|
65
91
|
# NOTE: When provided, the deprecated_for_removal_transport_configuration_proc can override all
|
|
66
92
|
# values above (ssl, hostname, port, timeout), or even make them irrelevant (by using an unix socket or
|
|
@@ -72,65 +98,99 @@ module Datadog
|
|
|
72
98
|
)
|
|
73
99
|
end
|
|
74
100
|
|
|
75
|
-
def
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
101
|
+
def adapter
|
|
102
|
+
# If no agent settings have been provided, we try to connect using a local unix socket.
|
|
103
|
+
# We only do so if the socket is present when `ddtrace` runs.
|
|
104
|
+
if should_use_uds_fallback?
|
|
105
|
+
Ext::Transport::UnixSocket::ADAPTER
|
|
106
|
+
else
|
|
107
|
+
Ext::Transport::HTTP::ADAPTER
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def configured_hostname
|
|
112
|
+
return @configured_hostname if defined?(@configured_hostname)
|
|
113
|
+
|
|
114
|
+
@configured_hostname = pick_from(
|
|
115
|
+
DetectedConfiguration.new(
|
|
116
|
+
friendly_name: "'c.tracer.hostname'",
|
|
117
|
+
value: settings.tracer.hostname
|
|
118
|
+
),
|
|
119
|
+
DetectedConfiguration.new(
|
|
120
|
+
friendly_name: "#{Datadog::Ext::Transport::HTTP::ENV_DEFAULT_URL} environment variable",
|
|
121
|
+
value: parsed_url && parsed_url.hostname
|
|
122
|
+
),
|
|
123
|
+
DetectedConfiguration.new(
|
|
124
|
+
friendly_name: "#{Datadog::Ext::Transport::HTTP::ENV_DEFAULT_HOST} environment variable",
|
|
125
|
+
value: ENV[Datadog::Ext::Transport::HTTP::ENV_DEFAULT_HOST]
|
|
126
|
+
)
|
|
92
127
|
)
|
|
93
128
|
end
|
|
94
129
|
|
|
95
|
-
def
|
|
96
|
-
|
|
130
|
+
def configured_port
|
|
131
|
+
return @configured_port if defined?(@configured_port)
|
|
132
|
+
|
|
97
133
|
parsed_port_from_env =
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
log_warning(
|
|
103
|
-
"Invalid value for #{Datadog::Ext::Transport::HTTP::ENV_DEFAULT_PORT} environment variable " \
|
|
104
|
-
"('#{port_from_env}'). Ignoring this configuration."
|
|
105
|
-
)
|
|
106
|
-
end
|
|
107
|
-
end
|
|
134
|
+
try_parsing_as_integer(
|
|
135
|
+
friendly_name: "#{Datadog::Ext::Transport::HTTP::ENV_DEFAULT_PORT} environment variable",
|
|
136
|
+
value: ENV[Datadog::Ext::Transport::HTTP::ENV_DEFAULT_PORT],
|
|
137
|
+
)
|
|
108
138
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
139
|
+
parsed_settings_tracer_port =
|
|
140
|
+
try_parsing_as_integer(
|
|
141
|
+
friendly_name: '"c.tracer.port"',
|
|
142
|
+
value: settings.tracer.port,
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
@configured_port = pick_from(
|
|
146
|
+
DetectedConfiguration.new(
|
|
147
|
+
friendly_name: '"c.tracer.port"',
|
|
148
|
+
value: parsed_settings_tracer_port,
|
|
149
|
+
),
|
|
150
|
+
DetectedConfiguration.new(
|
|
151
|
+
friendly_name: "#{Datadog::Ext::Transport::HTTP::ENV_DEFAULT_URL} environment variable",
|
|
152
|
+
value: parsed_url && parsed_url.port,
|
|
153
|
+
),
|
|
154
|
+
DetectedConfiguration.new(
|
|
155
|
+
friendly_name: "#{Datadog::Ext::Transport::HTTP::ENV_DEFAULT_PORT} environment variable",
|
|
156
|
+
value: parsed_port_from_env,
|
|
157
|
+
)
|
|
125
158
|
)
|
|
126
159
|
end
|
|
127
160
|
|
|
161
|
+
def try_parsing_as_integer(value:, friendly_name:)
|
|
162
|
+
return unless value
|
|
163
|
+
|
|
164
|
+
begin
|
|
165
|
+
Integer(value)
|
|
166
|
+
rescue ArgumentError, TypeError
|
|
167
|
+
log_warning("Invalid value for #{friendly_name} (#{value.inspect}). Ignoring this configuration.")
|
|
168
|
+
|
|
169
|
+
nil
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
128
173
|
def ssl?
|
|
129
174
|
!parsed_url.nil? && parsed_url.scheme == 'https'
|
|
130
175
|
end
|
|
131
176
|
|
|
177
|
+
def hostname
|
|
178
|
+
configured_hostname || (should_use_uds_fallback? ? nil : Datadog::Ext::Transport::HTTP::DEFAULT_HOST)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def port
|
|
182
|
+
configured_port || (should_use_uds_fallback? ? nil : Datadog::Ext::Transport::HTTP::DEFAULT_PORT)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Unix socket path in the file system
|
|
186
|
+
def uds_path
|
|
187
|
+
uds_fallback
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Defaults to +nil+, letting the adapter choose what default
|
|
191
|
+
# works best in their case.
|
|
132
192
|
def timeout_seconds
|
|
133
|
-
|
|
193
|
+
nil
|
|
134
194
|
end
|
|
135
195
|
|
|
136
196
|
def deprecated_for_removal_transport_configuration_proc
|
|
@@ -150,6 +210,26 @@ module Datadog
|
|
|
150
210
|
end
|
|
151
211
|
end
|
|
152
212
|
|
|
213
|
+
# We only use the default unix socket if it is already present.
|
|
214
|
+
# This is by design, as we still want to use the default host:port if no unix socket is present.
|
|
215
|
+
def uds_fallback
|
|
216
|
+
return @uds_fallback if defined?(@uds_fallback)
|
|
217
|
+
|
|
218
|
+
@uds_fallback =
|
|
219
|
+
if configured_hostname.nil? &&
|
|
220
|
+
configured_port.nil? &&
|
|
221
|
+
deprecated_for_removal_transport_configuration_proc.nil? &&
|
|
222
|
+
deprecated_for_removal_transport_configuration_options.nil? &&
|
|
223
|
+
File.exist?(Ext::Transport::UnixSocket::DEFAULT_PATH)
|
|
224
|
+
|
|
225
|
+
Ext::Transport::UnixSocket::DEFAULT_PATH
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def should_use_uds_fallback?
|
|
230
|
+
uds_fallback != nil
|
|
231
|
+
end
|
|
232
|
+
|
|
153
233
|
def parsed_url
|
|
154
234
|
return @parsed_url if defined?(@parsed_url)
|
|
155
235
|
|
|
@@ -177,7 +257,7 @@ module Datadog
|
|
|
177
257
|
@unparsed_url_from_env ||= ENV[Datadog::Ext::Transport::HTTP::ENV_DEFAULT_URL]
|
|
178
258
|
end
|
|
179
259
|
|
|
180
|
-
def pick_from(configurations_in_priority_order
|
|
260
|
+
def pick_from(*configurations_in_priority_order)
|
|
181
261
|
detected_configurations_in_priority_order = configurations_in_priority_order.select(&:value?)
|
|
182
262
|
|
|
183
263
|
if detected_configurations_in_priority_order.any?
|
|
@@ -186,8 +266,6 @@ module Datadog
|
|
|
186
266
|
# The configurations are listed in priority, so we only need to look at the first; if there's more than
|
|
187
267
|
# one, we emit a warning above
|
|
188
268
|
detected_configurations_in_priority_order.first.value
|
|
189
|
-
else
|
|
190
|
-
or_use_default
|
|
191
269
|
end
|
|
192
270
|
end
|
|
193
271
|
|
|
@@ -197,8 +275,8 @@ module Datadog
|
|
|
197
275
|
log_warning(
|
|
198
276
|
'Configuration mismatch: values differ between ' \
|
|
199
277
|
"#{detected_configurations_in_priority_order
|
|
200
|
-
.map { |config| "#{config.friendly_name} (
|
|
201
|
-
". Using
|
|
278
|
+
.map { |config| "#{config.friendly_name} (#{config.value.inspect})" }.join(' and ')}" \
|
|
279
|
+
". Using #{detected_configurations_in_priority_order.first.value.inspect}."
|
|
202
280
|
)
|
|
203
281
|
end
|
|
204
282
|
|
|
@@ -117,7 +117,7 @@ module Datadog
|
|
|
117
117
|
|
|
118
118
|
trace_identifiers_helper = Datadog::Profiling::TraceIdentifiers::Helper.new(
|
|
119
119
|
tracer: tracer,
|
|
120
|
-
|
|
120
|
+
endpoint_collection_enabled: settings.profiling.advanced.endpoint.collection.enabled
|
|
121
121
|
)
|
|
122
122
|
|
|
123
123
|
recorder = build_profiler_recorder(settings)
|
|
@@ -161,6 +161,9 @@ module Datadog
|
|
|
161
161
|
end
|
|
162
162
|
|
|
163
163
|
settings :advanced do
|
|
164
|
+
# This should never be reduced, as it can cause the resulting profiles to become biased.
|
|
165
|
+
# The current default should be enough for most services, allowing 16 threads to be sampled around 30 times
|
|
166
|
+
# per second for a 60 second period.
|
|
164
167
|
option :max_events, default: 32768
|
|
165
168
|
|
|
166
169
|
# Controls the maximum number of frames for each thread sampled. Can be tuned to avoid omitted frames in the
|
|
@@ -170,9 +173,16 @@ module Datadog
|
|
|
170
173
|
o.lazy
|
|
171
174
|
end
|
|
172
175
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
+
settings :endpoint do
|
|
177
|
+
settings :collection do
|
|
178
|
+
# When using profiling together with tracing, this controls if endpoint names
|
|
179
|
+
# are gathered and reported together with profiles.
|
|
180
|
+
option :enabled do |o|
|
|
181
|
+
o.default { env_to_bool(Ext::Profiling::ENV_ENDPOINT_COLLECTION_ENABLED, true) }
|
|
182
|
+
o.lazy
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
176
186
|
end
|
|
177
187
|
|
|
178
188
|
settings :upload do
|
data/lib/ddtrace/context.rb
CHANGED
|
@@ -78,13 +78,21 @@ module Datadog
|
|
|
78
78
|
# earlier while child spans still need to finish their traced execution.
|
|
79
79
|
def current_span
|
|
80
80
|
@mutex.synchronize do
|
|
81
|
-
|
|
81
|
+
@current_span
|
|
82
82
|
end
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
def current_root_span
|
|
86
86
|
@mutex.synchronize do
|
|
87
|
-
|
|
87
|
+
@current_root_span
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Same as calling #current_span and #current_root_span, but works atomically thus preventing races when we need to
|
|
92
|
+
# retrieve both
|
|
93
|
+
def current_span_and_root_span
|
|
94
|
+
@mutex.synchronize do
|
|
95
|
+
[@current_span, @current_root_span]
|
|
88
96
|
end
|
|
89
97
|
end
|
|
90
98
|
|
|
@@ -26,6 +26,52 @@ module Datadog
|
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
|
+
|
|
30
|
+
# Instrumentation for when a Channel is subscribed to/unsubscribed from.
|
|
31
|
+
module ActionCableChannel
|
|
32
|
+
def self.included(base)
|
|
33
|
+
base.class_eval do
|
|
34
|
+
set_callback(
|
|
35
|
+
:subscribe,
|
|
36
|
+
:around,
|
|
37
|
+
->(channel, block) { Tracer.trace(channel, :subscribe, &block) },
|
|
38
|
+
prepend: true
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
set_callback(
|
|
42
|
+
:unsubscribe,
|
|
43
|
+
:around,
|
|
44
|
+
->(channel, block) { Tracer.trace(channel, :unsubscribe, &block) },
|
|
45
|
+
prepend: true
|
|
46
|
+
)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Instrumentation for Channel hooks.
|
|
51
|
+
class Tracer
|
|
52
|
+
def self.trace(channel, hook)
|
|
53
|
+
configuration = Datadog.configuration[:action_cable]
|
|
54
|
+
|
|
55
|
+
Datadog.tracer.trace("action_cable.#{hook}") do |span|
|
|
56
|
+
span.service = configuration[:service_name]
|
|
57
|
+
span.resource = "#{channel.class}##{hook}"
|
|
58
|
+
span.span_type = Datadog::Ext::AppTypes::WEB
|
|
59
|
+
|
|
60
|
+
# Set analytics sample rate
|
|
61
|
+
if Contrib::Analytics.enabled?(configuration[:analytics_enabled])
|
|
62
|
+
Contrib::Analytics.set_sample_rate(span, configuration[:analytics_sample_rate])
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Measure service stats
|
|
66
|
+
Contrib::Analytics.set_measured(span)
|
|
67
|
+
|
|
68
|
+
span.set_tag(Ext::TAG_CHANNEL_CLASS, channel.class.to_s)
|
|
69
|
+
|
|
70
|
+
yield
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
29
75
|
end
|
|
30
76
|
end
|
|
31
77
|
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# typed: false
|
|
2
|
+
require 'ddtrace/contrib/configuration/settings'
|
|
3
|
+
require 'ddtrace/contrib/action_mailer/ext'
|
|
4
|
+
|
|
5
|
+
module Datadog
|
|
6
|
+
module Contrib
|
|
7
|
+
module ActionMailer
|
|
8
|
+
module Configuration
|
|
9
|
+
# Custom settings for the ActionMailer integration
|
|
10
|
+
class Settings < Contrib::Configuration::Settings
|
|
11
|
+
option :enabled do |o|
|
|
12
|
+
o.default { env_to_bool(Ext::ENV_ENABLED, true) }
|
|
13
|
+
o.lazy
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
option :analytics_enabled do |o|
|
|
17
|
+
o.default { env_to_bool([Ext::ENV_ANALYTICS_ENABLED, Ext::ENV_ANALYTICS_ENABLED_OLD], false) }
|
|
18
|
+
o.lazy
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
option :analytics_sample_rate do |o|
|
|
22
|
+
o.default { env_to_float([Ext::ENV_ANALYTICS_SAMPLE_RATE, Ext::ENV_ANALYTICS_SAMPLE_RATE_OLD], 1.0) }
|
|
23
|
+
o.lazy
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
option :service_name, default: Ext::SERVICE_NAME
|
|
27
|
+
option :email_data, default: false
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# typed: false
|
|
2
|
+
require 'ddtrace/contrib/analytics'
|
|
3
|
+
require 'ddtrace/contrib/active_support/notifications/event'
|
|
4
|
+
require 'ddtrace/contrib/action_mailer/ext'
|
|
5
|
+
|
|
6
|
+
module Datadog
|
|
7
|
+
module Contrib
|
|
8
|
+
module ActionMailer
|
|
9
|
+
# Defines basic behaviors for an ActionMailer event.
|
|
10
|
+
module Event
|
|
11
|
+
def self.included(base)
|
|
12
|
+
base.send(:include, ActiveSupport::Notifications::Event)
|
|
13
|
+
base.send(:extend, ClassMethods)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Class methods for ActionMailer events.
|
|
17
|
+
module ClassMethods
|
|
18
|
+
def span_options
|
|
19
|
+
{ service: configuration[:service_name] }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def tracer
|
|
23
|
+
-> { configuration[:tracer] }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def configuration
|
|
27
|
+
Datadog.configuration[:action_mailer]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def process(span, event, _id, payload)
|
|
31
|
+
span.service = configuration[:service_name]
|
|
32
|
+
span.resource = payload[:mailer]
|
|
33
|
+
|
|
34
|
+
# Set analytics sample rate
|
|
35
|
+
if Contrib::Analytics.enabled?(configuration[:analytics_enabled])
|
|
36
|
+
Contrib::Analytics.set_sample_rate(span, configuration[:analytics_sample_rate])
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Measure service stats
|
|
40
|
+
Contrib::Analytics.set_measured(span)
|
|
41
|
+
|
|
42
|
+
report_if_exception(span, payload)
|
|
43
|
+
rescue StandardError => e
|
|
44
|
+
Datadog.logger.debug(e.message)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# typed: false
|
|
2
|
+
require 'ddtrace/contrib/action_mailer/ext'
|
|
3
|
+
require 'ddtrace/contrib/action_mailer/event'
|
|
4
|
+
|
|
5
|
+
module Datadog
|
|
6
|
+
module Contrib
|
|
7
|
+
module ActionMailer
|
|
8
|
+
module Events
|
|
9
|
+
# Defines instrumentation for process.action_mailer event
|
|
10
|
+
module Deliver
|
|
11
|
+
include ActionMailer::Event
|
|
12
|
+
|
|
13
|
+
EVENT_NAME = 'deliver.action_mailer'.freeze
|
|
14
|
+
|
|
15
|
+
module_function
|
|
16
|
+
|
|
17
|
+
def event_name
|
|
18
|
+
self::EVENT_NAME
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def span_name
|
|
22
|
+
Ext::SPAN_DELIVER
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def span_type
|
|
26
|
+
# deliver.action_mailer sends emails
|
|
27
|
+
Datadog::Ext::AppTypes::WORKER
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def process(span, event, _id, payload)
|
|
31
|
+
super
|
|
32
|
+
|
|
33
|
+
span.span_type = span_type
|
|
34
|
+
span.set_tag(Ext::TAG_MAILER, payload[:mailer])
|
|
35
|
+
span.set_tag(Ext::TAG_MSG_ID, payload[:message_id])
|
|
36
|
+
|
|
37
|
+
# Since email date can contain PII we disable by default
|
|
38
|
+
# Some of these fields can be either strings or arrays, so we try to normalize
|
|
39
|
+
# https://github.com/rails/rails/blob/18707ab17fa492eb25ad2e8f9818a320dc20b823/actionmailer/lib/action_mailer/base.rb#L742-L754
|
|
40
|
+
if configuration[:email_data] == true
|
|
41
|
+
span.set_tag(Ext::TAG_SUBJECT, payload[:subject].to_s) if payload[:subject]
|
|
42
|
+
span.set_tag(Ext::TAG_TO, payload[:to].join(',')) if payload[:to]
|
|
43
|
+
span.set_tag(Ext::TAG_FROM, payload[:from].join(',')) if payload[:from]
|
|
44
|
+
span.set_tag(Ext::TAG_BCC, payload[:bcc].join(',')) if payload[:bcc]
|
|
45
|
+
span.set_tag(Ext::TAG_CC, payload[:cc].join(',')) if payload[:cc]
|
|
46
|
+
span.set_tag(Ext::TAG_DATE, payload[:date].to_s) if payload[:date]
|
|
47
|
+
span.set_tag(Ext::TAG_PERFORM_DELIVERIES, payload[:perform_deliveries]) if payload[:perform_deliveries]
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|