ddtrace 0.52.0 → 0.53.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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +65 -1
  3. data/ddtrace.gemspec +1 -1
  4. data/docs/DevelopmentGuide.md +1 -6
  5. data/docs/GettingStarted.md +66 -16
  6. data/lib/datadog/ci/contrib/rspec/integration.rb +2 -2
  7. data/lib/datadog/ci/ext/environment.rb +41 -4
  8. data/lib/datadog/contrib.rb +2 -0
  9. data/lib/datadog/core/environment/vm_cache.rb +46 -0
  10. data/lib/ddtrace/configuration/agent_settings_resolver.rb +107 -40
  11. data/lib/ddtrace/configuration/components.rb +1 -1
  12. data/lib/ddtrace/configuration/settings.rb +13 -3
  13. data/lib/ddtrace/contrib/action_cable/instrumentation.rb +46 -0
  14. data/lib/ddtrace/contrib/action_cable/patcher.rb +1 -0
  15. data/lib/ddtrace/contrib/action_mailer/configuration/settings.rb +32 -0
  16. data/lib/ddtrace/contrib/action_mailer/event.rb +50 -0
  17. data/lib/ddtrace/contrib/action_mailer/events/deliver.rb +54 -0
  18. data/lib/ddtrace/contrib/action_mailer/events/process.rb +41 -0
  19. data/lib/ddtrace/contrib/action_mailer/events.rb +31 -0
  20. data/lib/ddtrace/contrib/action_mailer/ext.rb +32 -0
  21. data/lib/ddtrace/contrib/action_mailer/integration.rb +45 -0
  22. data/lib/ddtrace/contrib/action_mailer/patcher.rb +27 -0
  23. data/lib/ddtrace/contrib/active_job/configuration/settings.rb +33 -0
  24. data/lib/ddtrace/contrib/active_job/event.rb +54 -0
  25. data/lib/ddtrace/contrib/active_job/events/discard.rb +46 -0
  26. data/lib/ddtrace/contrib/active_job/events/enqueue.rb +45 -0
  27. data/lib/ddtrace/contrib/active_job/events/enqueue_at.rb +45 -0
  28. data/lib/ddtrace/contrib/active_job/events/enqueue_retry.rb +47 -0
  29. data/lib/ddtrace/contrib/active_job/events/perform.rb +45 -0
  30. data/lib/ddtrace/contrib/active_job/events/retry_stopped.rb +46 -0
  31. data/lib/ddtrace/contrib/active_job/events.rb +39 -0
  32. data/lib/ddtrace/contrib/active_job/ext.rb +32 -0
  33. data/lib/ddtrace/contrib/active_job/integration.rb +46 -0
  34. data/lib/ddtrace/contrib/active_job/log_injection.rb +21 -0
  35. data/lib/ddtrace/contrib/active_job/patcher.rb +33 -0
  36. data/lib/ddtrace/contrib/auto_instrument.rb +0 -1
  37. data/lib/ddtrace/contrib/rails/auto_instrument_railtie.rb +0 -1
  38. data/lib/ddtrace/contrib/rails/framework.rb +22 -0
  39. data/lib/ddtrace/contrib/rails/patcher.rb +19 -10
  40. data/lib/ddtrace/contrib/registerable.rb +0 -1
  41. data/lib/ddtrace/contrib/sidekiq/ext.rb +3 -0
  42. data/lib/ddtrace/contrib/sidekiq/integration.rb +10 -0
  43. data/lib/ddtrace/contrib/sidekiq/patcher.rb +26 -0
  44. data/lib/ddtrace/contrib/sidekiq/server_internal_tracer/heartbeat.rb +30 -0
  45. data/lib/ddtrace/contrib/sidekiq/server_internal_tracer/job_fetch.rb +30 -0
  46. data/lib/ddtrace/contrib/sidekiq/server_internal_tracer/scheduled_push.rb +29 -0
  47. data/lib/ddtrace/contrib/sinatra/env.rb +2 -1
  48. data/lib/ddtrace/contrib/sinatra/tracer.rb +15 -2
  49. data/lib/ddtrace/ext/git.rb +12 -0
  50. data/lib/ddtrace/ext/profiling.rb +1 -0
  51. data/lib/ddtrace/ext/runtime.rb +3 -0
  52. data/lib/ddtrace/ext/transport.rb +11 -0
  53. data/lib/ddtrace/profiling/collectors/stack.rb +71 -27
  54. data/lib/ddtrace/profiling/encoding/profile.rb +9 -1
  55. data/lib/ddtrace/profiling/events/stack.rb +7 -7
  56. data/lib/ddtrace/profiling/pprof/converter.rb +22 -9
  57. data/lib/ddtrace/profiling/pprof/stack_sample.rb +28 -2
  58. data/lib/ddtrace/profiling/tasks/setup.rb +0 -1
  59. data/lib/ddtrace/profiling/trace_identifiers/ddtrace.rb +1 -1
  60. data/lib/ddtrace/profiling/trace_identifiers/helper.rb +3 -3
  61. data/lib/ddtrace/profiling/transport/http.rb +8 -17
  62. data/lib/ddtrace/runtime/metrics.rb +14 -0
  63. data/lib/ddtrace/span.rb +7 -19
  64. data/lib/ddtrace/tracer.rb +1 -1
  65. data/lib/ddtrace/transport/http/adapters/net.rb +13 -3
  66. data/lib/ddtrace/transport/http/adapters/test.rb +4 -2
  67. data/lib/ddtrace/transport/http/adapters/unix_socket.rb +23 -12
  68. data/lib/ddtrace/transport/http/builder.rb +13 -6
  69. data/lib/ddtrace/transport/http.rb +5 -11
  70. data/lib/ddtrace/utils/time.rb +5 -6
  71. data/lib/ddtrace/version.rb +1 -1
  72. metadata +27 -2
@@ -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(ssl, hostname, port, timeout_seconds, deprecated_for_removal_transport_configuration_proc, \
39
- deprecated_for_removal_transport_configuration_options)
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,27 +98,38 @@ module Datadog
72
98
  )
73
99
  end
74
100
 
75
- def hostname
76
- pick_from(
77
- configurations_in_priority_order: [
78
- DetectedConfiguration.new(
79
- friendly_name: "'c.tracer.hostname'",
80
- value: settings.tracer.hostname
81
- ),
82
- DetectedConfiguration.new(
83
- friendly_name: "#{Datadog::Ext::Transport::HTTP::ENV_DEFAULT_URL} environment variable",
84
- value: parsed_url && parsed_url.hostname
85
- ),
86
- DetectedConfiguration.new(
87
- friendly_name: "#{Datadog::Ext::Transport::HTTP::ENV_DEFAULT_HOST} environment variable",
88
- value: ENV[Datadog::Ext::Transport::HTTP::ENV_DEFAULT_HOST]
89
- )
90
- ],
91
- or_use_default: Datadog::Ext::Transport::HTTP::DEFAULT_HOST
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 port
130
+ def configured_port
131
+ return @configured_port if defined?(@configured_port)
132
+
96
133
  port_from_env = ENV[Datadog::Ext::Transport::HTTP::ENV_DEFAULT_PORT]
97
134
  parsed_port_from_env =
98
135
  if port_from_env
@@ -106,22 +143,19 @@ module Datadog
106
143
  end
107
144
  end
108
145
 
109
- pick_from(
110
- configurations_in_priority_order: [
111
- DetectedConfiguration.new(
112
- friendly_name: '"c.tracer.port"',
113
- value: settings.tracer.port
114
- ),
115
- DetectedConfiguration.new(
116
- friendly_name: "#{Datadog::Ext::Transport::HTTP::ENV_DEFAULT_URL} environment variable",
117
- value: parsed_url && parsed_url.port
118
- ),
119
- DetectedConfiguration.new(
120
- friendly_name: "#{Datadog::Ext::Transport::HTTP::ENV_DEFAULT_PORT} environment variable",
121
- value: parsed_port_from_env
122
- )
123
- ],
124
- or_use_default: Datadog::Ext::Transport::HTTP::DEFAULT_PORT
146
+ @configured_port = pick_from(
147
+ DetectedConfiguration.new(
148
+ friendly_name: '"c.tracer.port"',
149
+ value: settings.tracer.port
150
+ ),
151
+ DetectedConfiguration.new(
152
+ friendly_name: "#{Datadog::Ext::Transport::HTTP::ENV_DEFAULT_URL} environment variable",
153
+ value: parsed_url && parsed_url.port
154
+ ),
155
+ DetectedConfiguration.new(
156
+ friendly_name: "#{Datadog::Ext::Transport::HTTP::ENV_DEFAULT_PORT} environment variable",
157
+ value: parsed_port_from_env
158
+ )
125
159
  )
126
160
  end
127
161
 
@@ -129,8 +163,23 @@ module Datadog
129
163
  !parsed_url.nil? && parsed_url.scheme == 'https'
130
164
  end
131
165
 
166
+ def hostname
167
+ configured_hostname || (should_use_uds_fallback? ? nil : Datadog::Ext::Transport::HTTP::DEFAULT_HOST)
168
+ end
169
+
170
+ def port
171
+ configured_port || (should_use_uds_fallback? ? nil : Datadog::Ext::Transport::HTTP::DEFAULT_PORT)
172
+ end
173
+
174
+ # Unix socket path in the file system
175
+ def uds_path
176
+ uds_fallback
177
+ end
178
+
179
+ # Defaults to +nil+, letting the adapter choose what default
180
+ # works best in their case.
132
181
  def timeout_seconds
133
- Datadog::Ext::Transport::HTTP::DEFAULT_TIMEOUT_SECONDS
182
+ nil
134
183
  end
135
184
 
136
185
  def deprecated_for_removal_transport_configuration_proc
@@ -150,6 +199,26 @@ module Datadog
150
199
  end
151
200
  end
152
201
 
202
+ # We only use the default unix socket if it is already present.
203
+ # This is by design, as we still want to use the default host:port if no unix socket is present.
204
+ def uds_fallback
205
+ return @uds_fallback if defined?(@uds_fallback)
206
+
207
+ @uds_fallback =
208
+ if configured_hostname.nil? &&
209
+ configured_port.nil? &&
210
+ deprecated_for_removal_transport_configuration_proc.nil? &&
211
+ deprecated_for_removal_transport_configuration_options.nil? &&
212
+ File.exist?(Ext::Transport::UnixSocket::DEFAULT_PATH)
213
+
214
+ Ext::Transport::UnixSocket::DEFAULT_PATH
215
+ end
216
+ end
217
+
218
+ def should_use_uds_fallback?
219
+ uds_fallback != nil
220
+ end
221
+
153
222
  def parsed_url
154
223
  return @parsed_url if defined?(@parsed_url)
155
224
 
@@ -177,7 +246,7 @@ module Datadog
177
246
  @unparsed_url_from_env ||= ENV[Datadog::Ext::Transport::HTTP::ENV_DEFAULT_URL]
178
247
  end
179
248
 
180
- def pick_from(configurations_in_priority_order:, or_use_default:)
249
+ def pick_from(*configurations_in_priority_order)
181
250
  detected_configurations_in_priority_order = configurations_in_priority_order.select(&:value?)
182
251
 
183
252
  if detected_configurations_in_priority_order.any?
@@ -186,8 +255,6 @@ module Datadog
186
255
  # The configurations are listed in priority, so we only need to look at the first; if there's more than
187
256
  # one, we emit a warning above
188
257
  detected_configurations_in_priority_order.first.value
189
- else
190
- or_use_default
191
258
  end
192
259
  end
193
260
 
@@ -117,7 +117,7 @@ module Datadog
117
117
 
118
118
  trace_identifiers_helper = Datadog::Profiling::TraceIdentifiers::Helper.new(
119
119
  tracer: tracer,
120
- extract_trace_resource: settings.profiling.advanced.extract_trace_resource
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
- # When using profiling together with tracing, this controls if trace resources (usually the endpoint names)
174
- # are gathered and reported together with profiles.
175
- option :extract_trace_resource, default: true
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
@@ -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
@@ -21,6 +21,7 @@ module Datadog
21
21
  def patch
22
22
  Events.subscribe!
23
23
  ::ActionCable::Connection::Base.prepend(Instrumentation::ActionCableConnection)
24
+ ::ActionCable::Channel::Base.include(Instrumentation::ActionCableChannel)
24
25
  end
25
26
  end
26
27
  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
@@ -0,0 +1,41 @@
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 Process
11
+ include ActionMailer::Event
12
+
13
+ EVENT_NAME = 'process.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_PROCESS
23
+ end
24
+
25
+ def span_type
26
+ # process.action_mailer processes email and renders partial templates
27
+ Datadog::Ext::HTTP::TEMPLATE
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_ACTION, payload[:action])
35
+ span.set_tag(Ext::TAG_MAILER, payload[:mailer])
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,31 @@
1
+ # typed: false
2
+ require 'ddtrace/contrib/action_mailer/events/process'
3
+ require 'ddtrace/contrib/action_mailer/events/deliver'
4
+
5
+ module Datadog
6
+ module Contrib
7
+ module ActionMailer
8
+ # Defines collection of instrumented ActionMailer events
9
+ module Events
10
+ ALL = [
11
+ Events::Process,
12
+ Events::Deliver
13
+ ].freeze
14
+
15
+ module_function
16
+
17
+ def all
18
+ self::ALL
19
+ end
20
+
21
+ def subscriptions
22
+ all.collect(&:subscriptions).collect(&:to_a).flatten
23
+ end
24
+
25
+ def subscribe!
26
+ all.each(&:subscribe!)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ # typed: true
2
+ module Datadog
3
+ module Contrib
4
+ module ActionMailer
5
+ # ActionMailer integration constants
6
+ module Ext
7
+ APP = 'action_mailer'.freeze
8
+ ENV_ENABLED = 'DD_TRACE_ACTION_MAILER_ENABLED'.freeze
9
+ ENV_ANALYTICS_ENABLED = 'DD_TRACE_ACTION_MAILER_ANALYTICS_ENABLED'.freeze
10
+ ENV_ANALYTICS_SAMPLE_RATE = 'DD_TRACE_ACTION_MAILER_ANALYTICS_SAMPLE_RATE'.freeze
11
+
12
+ ENV_ANALYTICS_ENABLED_OLD = 'DD_ACTION_MAILER_ANALYTICS_ENABLED'.freeze
13
+
14
+ ENV_ANALYTICS_SAMPLE_RATE_OLD = 'DD_ACTION_MAILER_ANALYTICS_SAMPLE_RATE'.freeze
15
+ SERVICE_NAME = 'action_mailer'.freeze
16
+ SPAN_PROCESS = 'action_mailer.process'.freeze
17
+ SPAN_DELIVER = 'action_mailer.deliver'.freeze
18
+ TAG_ACTION = 'action_mailer.action'.freeze
19
+ TAG_MAILER = 'action_mailer.mailer'.freeze
20
+ TAG_MSG_ID = 'action_mailer.message_id'.freeze
21
+
22
+ TAG_SUBJECT = 'action_mailer.subject'.freeze
23
+ TAG_TO = 'action_mailer.to'.freeze
24
+ TAG_FROM = 'action_mailer.from'.freeze
25
+ TAG_BCC = 'action_mailer.bcc'.freeze
26
+ TAG_CC = 'action_mailer.cc'.freeze
27
+ TAG_DATE = 'action_mailer.date'.freeze
28
+ TAG_PERFORM_DELIVERIES = 'action_mailer.perform_deliveries'.freeze
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,45 @@
1
+ # typed: false
2
+ require 'ddtrace/contrib/integration'
3
+ require 'ddtrace/contrib/action_mailer/configuration/settings'
4
+ require 'ddtrace/contrib/action_mailer/patcher'
5
+
6
+ module Datadog
7
+ module Contrib
8
+ module ActionMailer
9
+ # Description of ActionMailer integration
10
+ class Integration
11
+ include Contrib::Integration
12
+
13
+ MINIMUM_VERSION = Gem::Version.new('5.0.0')
14
+
15
+ register_as :action_mailer, auto_patch: false
16
+
17
+ def self.version
18
+ Gem.loaded_specs['actionmailer'] && Gem.loaded_specs['actionmailer'].version
19
+ end
20
+
21
+ def self.loaded?
22
+ !defined?(::ActionMailer).nil?
23
+ end
24
+
25
+ def self.compatible?
26
+ super && version >= MINIMUM_VERSION && !defined?(::ActiveSupport::Notifications).nil?
27
+ end
28
+
29
+ # enabled by rails integration so should only auto instrument
30
+ # if detected that it is being used without rails
31
+ def auto_instrument?
32
+ !Datadog::Contrib::Rails::Utils.railtie_supported?
33
+ end
34
+
35
+ def default_configuration
36
+ Configuration::Settings.new
37
+ end
38
+
39
+ def patcher
40
+ ActionMailer::Patcher
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,27 @@
1
+ # typed: true
2
+ require 'ddtrace/contrib/patcher'
3
+ require 'ddtrace/ext/app_types'
4
+ require 'ddtrace/contrib/action_mailer/ext'
5
+ require 'ddtrace/contrib/action_mailer/events'
6
+
7
+ module Datadog
8
+ module Contrib
9
+ module ActionMailer
10
+ # Patcher enables patching of 'action_mailer' module.
11
+ module Patcher
12
+ include Contrib::Patcher
13
+
14
+ module_function
15
+
16
+ def target_version
17
+ Integration.version
18
+ end
19
+
20
+ def patch
21
+ # Subscribe to ActionMailer events
22
+ Events.subscribe!
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ # typed: false
2
+ require 'ddtrace/contrib/configuration/settings'
3
+ require 'ddtrace/contrib/active_job/ext'
4
+
5
+ module Datadog
6
+ module Contrib
7
+ module ActiveJob
8
+ module Configuration
9
+ # Custom settings for the DelayedJob 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 :error_handler, default: Datadog::Tracer::DEFAULT_ON_ERROR
28
+ option :log_injection, default: false
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end