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
@@ -0,0 +1,54 @@
1
+ # typed: true
2
+ require 'ddtrace/contrib/active_support/notifications/event'
3
+ require 'ddtrace/contrib/active_job/ext'
4
+
5
+ module Datadog
6
+ module Contrib
7
+ module ActiveJob
8
+ # Defines basic behaviors for an ActiveJob event.
9
+ module Event
10
+ def self.included(base)
11
+ base.include(ActiveSupport::Notifications::Event)
12
+ base.extend(ClassMethods)
13
+ end
14
+
15
+ # Class methods for ActiveJob events.
16
+ module ClassMethods
17
+ def span_options
18
+ { service: configuration[:service_name] }
19
+ end
20
+
21
+ def tracer
22
+ -> { configuration[:tracer] }
23
+ end
24
+
25
+ def configuration
26
+ Datadog.configuration[:active_job]
27
+ end
28
+
29
+ def set_common_tags(span, payload)
30
+ adapter_name = if payload[:adapter].is_a?(Class)
31
+ payload[:adapter].name
32
+ else
33
+ payload[:adapter].class.name
34
+ end
35
+ span.set_tag(Ext::TAG_ADAPTER, adapter_name)
36
+
37
+ job = payload[:job]
38
+ span.set_tag(Ext::TAG_JOB_ID, job.job_id)
39
+ span.set_tag(Ext::TAG_JOB_QUEUE, job.queue_name)
40
+ span.set_tag(Ext::TAG_JOB_PRIORITY, job.priority) if job.respond_to?(:priority)
41
+ span.set_tag(Ext::TAG_JOB_EXECUTIONS, job.executions) if job.respond_to?(:executions)
42
+
43
+ job_scheduled_at = if job.respond_to?(:scheduled_at)
44
+ job.scheduled_at
45
+ elsif job.respond_to?(:enqueued_at)
46
+ job.enqueued_at
47
+ end
48
+ span.set_tag(Ext::TAG_JOB_SCHEDULED_AT, Time.at(job_scheduled_at)) if job_scheduled_at
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,46 @@
1
+ # typed: false
2
+ require 'ddtrace/ext/integration'
3
+ require 'ddtrace/contrib/analytics'
4
+ require 'ddtrace/contrib/active_job/ext'
5
+ require 'ddtrace/contrib/active_job/event'
6
+
7
+ module Datadog
8
+ module Contrib
9
+ module ActiveJob
10
+ module Events
11
+ # Defines instrumentation for enqueue.active_job event
12
+ module Discard
13
+ include ActiveJob::Event
14
+
15
+ EVENT_NAME = 'discard.active_job'.freeze
16
+
17
+ module_function
18
+
19
+ def event_name
20
+ self::EVENT_NAME
21
+ end
22
+
23
+ def span_name
24
+ Ext::SPAN_DISCARD
25
+ end
26
+
27
+ def process(span, event, _id, payload)
28
+ span.name = span_name
29
+ span.service = configuration[:service_name]
30
+ span.resource = payload[:job].class.name
31
+
32
+ # Set analytics sample rate
33
+ if Contrib::Analytics.enabled?(configuration[:analytics_enabled])
34
+ Contrib::Analytics.set_sample_rate(span, configuration[:analytics_sample_rate])
35
+ end
36
+
37
+ set_common_tags(span, payload)
38
+ span.set_tag(Ext::TAG_JOB_ERROR, payload[:error])
39
+ rescue StandardError => e
40
+ Datadog.logger.debug(e.message)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,45 @@
1
+ # typed: false
2
+ require 'ddtrace/ext/integration'
3
+ require 'ddtrace/contrib/analytics'
4
+ require 'ddtrace/contrib/active_job/ext'
5
+ require 'ddtrace/contrib/active_job/event'
6
+
7
+ module Datadog
8
+ module Contrib
9
+ module ActiveJob
10
+ module Events
11
+ # Defines instrumentation for enqueue.active_job event
12
+ module Enqueue
13
+ include ActiveJob::Event
14
+
15
+ EVENT_NAME = 'enqueue.active_job'.freeze
16
+
17
+ module_function
18
+
19
+ def event_name
20
+ self::EVENT_NAME
21
+ end
22
+
23
+ def span_name
24
+ Ext::SPAN_ENQUEUE
25
+ end
26
+
27
+ def process(span, event, _id, payload)
28
+ span.name = span_name
29
+ span.service = configuration[:service_name]
30
+ span.resource = payload[:job].class.name
31
+
32
+ # Set analytics sample rate
33
+ if Contrib::Analytics.enabled?(configuration[:analytics_enabled])
34
+ Contrib::Analytics.set_sample_rate(span, configuration[:analytics_sample_rate])
35
+ end
36
+
37
+ set_common_tags(span, payload)
38
+ rescue StandardError => e
39
+ Datadog.logger.debug(e.message)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,45 @@
1
+ # typed: false
2
+ require 'ddtrace/ext/integration'
3
+ require 'ddtrace/contrib/analytics'
4
+ require 'ddtrace/contrib/active_job/ext'
5
+ require 'ddtrace/contrib/active_job/event'
6
+
7
+ module Datadog
8
+ module Contrib
9
+ module ActiveJob
10
+ module Events
11
+ # Defines instrumentation for enqueue.active_job event
12
+ module EnqueueAt
13
+ include ActiveJob::Event
14
+
15
+ EVENT_NAME = 'enqueue_at.active_job'.freeze
16
+
17
+ module_function
18
+
19
+ def event_name
20
+ self::EVENT_NAME
21
+ end
22
+
23
+ def span_name
24
+ Ext::SPAN_ENQUEUE
25
+ end
26
+
27
+ def process(span, event, _id, payload)
28
+ span.name = span_name
29
+ span.service = configuration[:service_name]
30
+ span.resource = payload[:job].class.name
31
+
32
+ # Set analytics sample rate
33
+ if Contrib::Analytics.enabled?(configuration[:analytics_enabled])
34
+ Contrib::Analytics.set_sample_rate(span, configuration[:analytics_sample_rate])
35
+ end
36
+
37
+ set_common_tags(span, payload)
38
+ rescue StandardError => e
39
+ Datadog.logger.debug(e.message)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,47 @@
1
+ # typed: false
2
+ require 'ddtrace/ext/integration'
3
+ require 'ddtrace/contrib/analytics'
4
+ require 'ddtrace/contrib/active_job/ext'
5
+ require 'ddtrace/contrib/active_job/event'
6
+
7
+ module Datadog
8
+ module Contrib
9
+ module ActiveJob
10
+ module Events
11
+ # Defines instrumentation for enqueue.active_job event
12
+ module EnqueueRetry
13
+ include ActiveJob::Event
14
+
15
+ EVENT_NAME = 'enqueue_retry.active_job'.freeze
16
+
17
+ module_function
18
+
19
+ def event_name
20
+ self::EVENT_NAME
21
+ end
22
+
23
+ def span_name
24
+ Ext::SPAN_ENQUEUE_RETRY
25
+ end
26
+
27
+ def process(span, event, _id, payload)
28
+ span.name = span_name
29
+ span.service = configuration[:service_name]
30
+ span.resource = payload[:job].class.name
31
+
32
+ # Set analytics sample rate
33
+ if Contrib::Analytics.enabled?(configuration[:analytics_enabled])
34
+ Contrib::Analytics.set_sample_rate(span, configuration[:analytics_sample_rate])
35
+ end
36
+
37
+ set_common_tags(span, payload)
38
+ span.set_tag(Ext::TAG_JOB_ERROR, payload[:error])
39
+ span.set_tag(Ext::TAG_JOB_RETRY_WAIT, payload[:wait])
40
+ rescue StandardError => e
41
+ Datadog.logger.debug(e.message)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,45 @@
1
+ # typed: false
2
+ require 'ddtrace/ext/integration'
3
+ require 'ddtrace/contrib/analytics'
4
+ require 'ddtrace/contrib/active_job/ext'
5
+ require 'ddtrace/contrib/active_job/event'
6
+
7
+ module Datadog
8
+ module Contrib
9
+ module ActiveJob
10
+ module Events
11
+ # Defines instrumentation for perform.active_job event
12
+ module Perform
13
+ include ActiveJob::Event
14
+
15
+ EVENT_NAME = 'perform.active_job'.freeze
16
+
17
+ module_function
18
+
19
+ def event_name
20
+ self::EVENT_NAME
21
+ end
22
+
23
+ def span_name
24
+ Ext::SPAN_PERFORM
25
+ end
26
+
27
+ def process(span, event, _id, payload)
28
+ span.name = span_name
29
+ span.service = configuration[:service_name]
30
+ span.resource = payload[:job].class.name
31
+
32
+ # Set analytics sample rate
33
+ if Contrib::Analytics.enabled?(configuration[:analytics_enabled])
34
+ Contrib::Analytics.set_sample_rate(span, configuration[:analytics_sample_rate])
35
+ end
36
+
37
+ set_common_tags(span, payload)
38
+ rescue StandardError => e
39
+ Datadog.logger.debug(e.message)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,46 @@
1
+ # typed: false
2
+ require 'ddtrace/ext/integration'
3
+ require 'ddtrace/contrib/analytics'
4
+ require 'ddtrace/contrib/active_job/ext'
5
+ require 'ddtrace/contrib/active_job/event'
6
+
7
+ module Datadog
8
+ module Contrib
9
+ module ActiveJob
10
+ module Events
11
+ # Defines instrumentation for enqueue.active_job event
12
+ module RetryStopped
13
+ include ActiveJob::Event
14
+
15
+ EVENT_NAME = 'retry_stopped.active_job'.freeze
16
+
17
+ module_function
18
+
19
+ def event_name
20
+ self::EVENT_NAME
21
+ end
22
+
23
+ def span_name
24
+ Ext::SPAN_RETRY_STOPPED
25
+ end
26
+
27
+ def process(span, event, _id, payload)
28
+ span.name = span_name
29
+ span.service = configuration[:service_name]
30
+ span.resource = payload[:job].class.name
31
+
32
+ # Set analytics sample rate
33
+ if Contrib::Analytics.enabled?(configuration[:analytics_enabled])
34
+ Contrib::Analytics.set_sample_rate(span, configuration[:analytics_sample_rate])
35
+ end
36
+
37
+ set_common_tags(span, payload)
38
+ span.set_tag(Ext::TAG_JOB_ERROR, payload[:error])
39
+ rescue StandardError => e
40
+ Datadog.logger.debug(e.message)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,39 @@
1
+ # typed: false
2
+ require 'ddtrace/contrib/active_job/events/discard'
3
+ require 'ddtrace/contrib/active_job/events/enqueue'
4
+ require 'ddtrace/contrib/active_job/events/enqueue_at'
5
+ require 'ddtrace/contrib/active_job/events/enqueue_retry'
6
+ require 'ddtrace/contrib/active_job/events/perform'
7
+ require 'ddtrace/contrib/active_job/events/retry_stopped'
8
+
9
+ module Datadog
10
+ module Contrib
11
+ module ActiveJob
12
+ # Defines collection of instrumented ActiveJob events
13
+ module Events
14
+ ALL = [
15
+ Events::Discard,
16
+ Events::Enqueue,
17
+ Events::EnqueueAt,
18
+ Events::EnqueueRetry,
19
+ Events::Perform,
20
+ Events::RetryStopped,
21
+ ].freeze
22
+
23
+ module_function
24
+
25
+ def all
26
+ self::ALL
27
+ end
28
+
29
+ def subscriptions
30
+ all.collect(&:subscriptions).collect(&:to_a).flatten
31
+ end
32
+
33
+ def subscribe!
34
+ all.each(&:subscribe!)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,32 @@
1
+ # typed: true
2
+ module Datadog
3
+ module Contrib
4
+ module ActiveJob
5
+ module Ext
6
+ APP = 'active_job'.freeze
7
+ SERVICE_NAME = 'active_job'.freeze
8
+
9
+ ENV_ENABLED = 'DD_TRACE_ACTIVE_JOB_ENABLED'.freeze
10
+ ENV_ANALYTICS_ENABLED = 'DD_TRACE_ACTIVE_JOB_ANALYTICS_ENABLED'.freeze
11
+ ENV_ANALYTICS_ENABLED_OLD = 'DD_ACTIVE_JOB_ANALYTICS_ENABLED'.freeze
12
+ ENV_ANALYTICS_SAMPLE_RATE = 'DD_TRACE_ACTIVE_JOB_ANALYTICS_SAMPLE_RATE'.freeze
13
+ ENV_ANALYTICS_SAMPLE_RATE_OLD = 'DD_ACTIVE_JOB_ANALYTICS_SAMPLE_RATE'.freeze
14
+
15
+ SPAN_DISCARD = 'active_job.discard'.freeze
16
+ SPAN_ENQUEUE = 'active_job.enqueue'.freeze
17
+ SPAN_ENQUEUE_RETRY = 'active_job.enqueue_retry'.freeze
18
+ SPAN_PERFORM = 'active_job.perform'.freeze
19
+ SPAN_RETRY_STOPPED = 'active_job.retry_stopped'.freeze
20
+
21
+ TAG_ADAPTER = 'active_job.adapter'.freeze
22
+ TAG_JOB_ERROR = 'active_job.job.error'.freeze
23
+ TAG_JOB_EXECUTIONS = 'active_job.job.executions'.freeze
24
+ TAG_JOB_ID = 'active_job.job.id'.freeze
25
+ TAG_JOB_PRIORITY = 'active_job.job.priority'.freeze
26
+ TAG_JOB_QUEUE = 'active_job.job.queue'.freeze
27
+ TAG_JOB_RETRY_WAIT = 'active_job.job.retry_wait'.freeze
28
+ TAG_JOB_SCHEDULED_AT = 'active_job.job.scheduled_at'.freeze
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,46 @@
1
+ # typed: false
2
+ require 'ddtrace/contrib/integration'
3
+ require 'ddtrace/contrib/active_job/configuration/settings'
4
+ require 'ddtrace/contrib/active_job/patcher'
5
+ require 'ddtrace/contrib/rails/utils'
6
+
7
+ module Datadog
8
+ module Contrib
9
+ module ActiveJob
10
+ # Describes the ActiveJob integration
11
+ class Integration
12
+ include Contrib::Integration
13
+
14
+ MINIMUM_VERSION = Gem::Version.new('4.2')
15
+
16
+ register_as :active_job, auto_patch: false
17
+
18
+ def self.version
19
+ Gem.loaded_specs['activejob'] && Gem.loaded_specs['activejob'].version
20
+ end
21
+
22
+ def self.loaded?
23
+ !defined?(::ActiveJob).nil?
24
+ end
25
+
26
+ def self.compatible?
27
+ super && version >= MINIMUM_VERSION
28
+ end
29
+
30
+ # enabled by rails integration so should only auto instrument
31
+ # if detected that it is being used without rails
32
+ def auto_instrument?
33
+ !Datadog::Contrib::Rails::Utils.railtie_supported?
34
+ end
35
+
36
+ def default_configuration
37
+ Configuration::Settings.new
38
+ end
39
+
40
+ def patcher
41
+ ActiveJob::Patcher
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,21 @@
1
+ # typed: false
2
+ module Datadog
3
+ module Contrib
4
+ module ActiveJob
5
+ # Active Job log injection wrapped around job execution
6
+ module LogInjection
7
+ def self.included(base)
8
+ base.class_eval do
9
+ around_perform do |_, block|
10
+ if logger.respond_to?(:tagged)
11
+ logger.tagged(Datadog.tracer.active_correlation.to_s, &block)
12
+ else
13
+ block.call
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,33 @@
1
+ # typed: false
2
+ require 'ddtrace/contrib/patcher'
3
+ require 'ddtrace/contrib/active_job/ext'
4
+ require 'ddtrace/contrib/active_job/events'
5
+ require 'ddtrace/contrib/active_job/log_injection'
6
+
7
+ module Datadog
8
+ module Contrib
9
+ module ActiveJob
10
+ # Patcher enables patching of 'active_job' 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
+ Events.subscribe!
22
+ inject_log_correlation if Datadog.configuration[:active_job][:log_injection]
23
+ end
24
+
25
+ def inject_log_correlation
26
+ ::ActiveSupport.on_load(:active_job) do
27
+ include LogInjection
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,5 +1,4 @@
1
1
  # typed: false
2
- require 'ddtrace'
3
2
 
4
3
  module Datadog
5
4
  module Contrib
@@ -1,5 +1,4 @@
1
1
  # typed: ignore
2
- require 'ddtrace'
3
2
 
4
3
  # Railtie to include AutoInstrumentation in rails loading
5
4
  class DatadogAutoInstrumentRailtie < Rails::Railtie
@@ -5,6 +5,7 @@ require 'ddtrace/ext/app_types'
5
5
  require 'ddtrace/contrib/active_record/integration'
6
6
  require 'ddtrace/contrib/active_support/integration'
7
7
  require 'ddtrace/contrib/action_cable/integration'
8
+ require 'ddtrace/contrib/action_mailer/integration'
8
9
  require 'ddtrace/contrib/action_pack/integration'
9
10
  require 'ddtrace/contrib/action_view/integration'
10
11
  require 'ddtrace/contrib/grape/endpoint'
@@ -45,9 +46,11 @@ module Datadog
45
46
 
46
47
  activate_rack!(datadog_config, rails_config)
47
48
  activate_action_cable!(datadog_config, rails_config)
49
+ activate_action_mailer!(datadog_config, rails_config)
48
50
  activate_active_support!(datadog_config, rails_config)
49
51
  activate_action_pack!(datadog_config, rails_config)
50
52
  activate_action_view!(datadog_config, rails_config)
53
+ activate_active_job!(datadog_config, rails_config)
51
54
  activate_active_record!(datadog_config, rails_config)
52
55
  activate_lograge!(datadog_config, rails_config)
53
56
  activate_semantic_logger!(datadog_config, rails_config)
@@ -93,6 +96,15 @@ module Datadog
93
96
  )
94
97
  end
95
98
 
99
+ def self.activate_action_mailer!(datadog_config, rails_config)
100
+ return unless defined?(::ActionMailer)
101
+
102
+ datadog_config.use(
103
+ :action_mailer,
104
+ service_name: "#{rails_config[:service_name]}-#{Contrib::ActionMailer::Ext::SERVICE_NAME}"
105
+ )
106
+ end
107
+
96
108
  def self.activate_action_pack!(datadog_config, rails_config)
97
109
  return unless defined?(::ActionPack)
98
110
 
@@ -115,6 +127,16 @@ module Datadog
115
127
  )
116
128
  end
117
129
 
130
+ def self.activate_active_job!(datadog_config, rails_config)
131
+ return unless defined?(::ActiveJob)
132
+
133
+ datadog_config.use(
134
+ :active_job,
135
+ service_name: "#{rails_config[:service_name]}-#{Contrib::ActiveJob::Ext::SERVICE_NAME}",
136
+ log_injection: rails_config[:log_injection]
137
+ )
138
+ end
139
+
118
140
  def self.activate_active_record!(datadog_config, rails_config)
119
141
  return unless defined?(::ActiveRecord)
120
142
 
@@ -1,4 +1,4 @@
1
- # typed: false
1
+ # typed: ignore
2
2
  require 'ddtrace/contrib/rails/utils'
3
3
  require 'ddtrace/contrib/rails/framework'
4
4
  require 'ddtrace/contrib/rails/middlewares'
@@ -45,17 +45,26 @@ module Datadog
45
45
  end
46
46
 
47
47
  def add_middleware(app)
48
- # Add trace middleware
48
+ # Add trace middleware at the top of the middleware stack,
49
+ # to ensure we capture the complete execution time.
49
50
  app.middleware.insert_before(0, Datadog::Contrib::Rack::TraceMiddleware)
50
51
 
51
- # Insert right after Rails exception handling middleware, because if it's before,
52
- # it catches and swallows the error. If it's too far after, custom middleware can find itself
53
- # between, and raise exceptions that don't end up getting tagged on the request properly.
54
- # e.g lost stack trace.
55
- app.middleware.insert_after(
56
- ActionDispatch::ShowExceptions,
57
- Datadog::Contrib::Rails::ExceptionMiddleware
58
- )
52
+ # Some Rails middleware can swallow an application error, preventing
53
+ # the error propagation to the encompassing Rack span.
54
+ #
55
+ # We insert our own middleware right before these Rails middleware
56
+ # have a chance to swallow the error.
57
+ #
58
+ # Note: because the middleware stack is push/pop, "before" and "after" are reversed
59
+ # for our use case: we insert ourselves with "after" a middleware to ensure we are
60
+ # able to pop the request "before" it.
61
+ if defined?(::ActionDispatch::DebugExceptions)
62
+ # Rails >= 3.2
63
+ app.middleware.insert_after(::ActionDispatch::DebugExceptions, Datadog::Contrib::Rails::ExceptionMiddleware)
64
+ else
65
+ # Rails < 3.2
66
+ app.middleware.insert_after(::ActionDispatch::ShowExceptions, Datadog::Contrib::Rails::ExceptionMiddleware)
67
+ end
59
68
  end
60
69
 
61
70
  def add_logger(app)
@@ -1,5 +1,4 @@
1
1
  # typed: false
2
- require 'datadog/contrib'
3
2
 
4
3
  module Datadog
5
4
  module Contrib
@@ -15,6 +15,9 @@ module Datadog
15
15
  SERVICE_NAME = 'sidekiq'.freeze
16
16
  SPAN_PUSH = 'sidekiq.push'.freeze
17
17
  SPAN_JOB = 'sidekiq.job'.freeze
18
+ SPAN_JOB_FETCH = 'sidekiq.job_fetch'.freeze
19
+ SPAN_HEARTBEAT = 'sidekiq.heartbeat'.freeze
20
+ SPAN_SCHEDULED_PUSH = 'sidekiq.scheduled_push'.freeze
18
21
  TAG_JOB_DELAY = 'sidekiq.job.delay'.freeze
19
22
  TAG_JOB_ID = 'sidekiq.job.id'.freeze
20
23
  TAG_JOB_QUEUE = 'sidekiq.job.queue'.freeze
@@ -11,6 +11,7 @@ module Datadog
11
11
  include Contrib::Integration
12
12
 
13
13
  MINIMUM_VERSION = Gem::Version.new('3.5.4')
14
+ MINIMUM_SERVER_INTERNAL_TRACING_VERSION = Gem::Version.new('5.2.4')
14
15
 
15
16
  register_as :sidekiq
16
17
 
@@ -26,6 +27,15 @@ module Datadog
26
27
  super && version >= MINIMUM_VERSION
27
28
  end
28
29
 
30
+ # Only patch server internals on v5.2.4+ because that's when loading of
31
+ # `Sidekiq::Launcher` stabilized. Sidekiq 4+ technically can support our
32
+ # patches (with minor adjustments), but in order to avoid explicitly
33
+ # requiring `sidekiq/launcher` ourselves (which could affect gem
34
+ # initialization order), we are limiting this tracing to v5.2.4+.
35
+ def self.compatible_with_server_internal_tracing?
36
+ version >= MINIMUM_SERVER_INTERNAL_TRACING_VERSION
37
+ end
38
+
29
39
  def default_configuration
30
40
  Configuration::Settings.new
31
41
  end