ddtrace 0.52.0 → 0.53.0

Sign up to get free protection for your applications and to get access to all the features.
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