ddtrace 1.11.1 → 1.12.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 (110) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +49 -1
  3. data/ext/ddtrace_profiling_native_extension/NativeExtensionDesign.md +6 -4
  4. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +34 -16
  5. data/ext/ddtrace_profiling_native_extension/extconf.rb +17 -3
  6. data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +2 -2
  7. data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +38 -4
  8. data/lib/datadog/appsec/assets/waf_rules/recommended.json +489 -133
  9. data/lib/datadog/appsec/assets/waf_rules/strict.json +2 -47
  10. data/lib/datadog/appsec/configuration/settings.rb +2 -10
  11. data/lib/datadog/appsec/configuration.rb +3 -9
  12. data/lib/datadog/appsec/contrib/rack/ext.rb +0 -1
  13. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +12 -0
  14. data/lib/datadog/appsec/contrib/rack/gateway/response.rb +3 -3
  15. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +9 -9
  16. data/lib/datadog/appsec/contrib/rack/integration.rb +0 -5
  17. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +7 -1
  18. data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +1 -1
  19. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +33 -25
  20. data/lib/datadog/appsec/contrib/rails/ext.rb +0 -1
  21. data/lib/datadog/appsec/contrib/rails/framework.rb +1 -13
  22. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +3 -3
  23. data/lib/datadog/appsec/contrib/rails/integration.rb +0 -5
  24. data/lib/datadog/appsec/contrib/rails/patcher.rb +1 -1
  25. data/lib/datadog/appsec/contrib/sinatra/ext.rb +0 -1
  26. data/lib/datadog/appsec/contrib/sinatra/framework.rb +1 -13
  27. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +6 -6
  28. data/lib/datadog/appsec/contrib/sinatra/integration.rb +0 -5
  29. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +5 -4
  30. data/lib/datadog/appsec/event.rb +5 -5
  31. data/lib/datadog/appsec/ext.rb +1 -0
  32. data/lib/datadog/appsec/extensions.rb +2 -6
  33. data/lib/datadog/appsec/monitor/gateway/watcher.rb +3 -4
  34. data/lib/datadog/appsec/processor/rule_merger.rb +13 -7
  35. data/lib/datadog/appsec/processor.rb +0 -45
  36. data/lib/datadog/appsec/remote.rb +6 -0
  37. data/lib/datadog/appsec/scope.rb +61 -0
  38. data/lib/datadog/appsec.rb +6 -0
  39. data/lib/datadog/ci/ext/environment.rb +40 -4
  40. data/lib/datadog/core/configuration/settings.rb +66 -14
  41. data/lib/datadog/core/configuration.rb +5 -1
  42. data/lib/datadog/core/remote/client/capabilities.rb +1 -1
  43. data/lib/datadog/core/telemetry/collector.rb +2 -1
  44. data/lib/datadog/core/telemetry/v1/dependency.rb +2 -1
  45. data/lib/datadog/kit/appsec/events.rb +58 -13
  46. data/lib/datadog/kit/identity.rb +29 -10
  47. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +2 -0
  48. data/lib/datadog/profiling/component.rb +54 -29
  49. data/lib/datadog/tracing/buffer.rb +0 -1
  50. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +9 -1
  51. data/lib/datadog/tracing/contrib/aws/ext.rb +11 -1
  52. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +7 -0
  53. data/lib/datadog/tracing/contrib/aws/parsed_context.rb +4 -0
  54. data/lib/datadog/tracing/contrib/aws/service/base.rb +16 -0
  55. data/lib/datadog/tracing/contrib/aws/service/dynamodb.rb +19 -0
  56. data/lib/datadog/tracing/contrib/aws/service/eventbridge.rb +19 -0
  57. data/lib/datadog/tracing/contrib/aws/service/kinesis.rb +29 -0
  58. data/lib/datadog/tracing/contrib/aws/service/s3.rb +19 -0
  59. data/lib/datadog/tracing/contrib/aws/service/sns.rb +27 -0
  60. data/lib/datadog/tracing/contrib/aws/service/sqs.rb +24 -0
  61. data/lib/datadog/tracing/contrib/aws/service/stepfunctions.rb +37 -0
  62. data/lib/datadog/tracing/contrib/aws/services.rb +10 -0
  63. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +6 -1
  64. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +5 -2
  65. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +6 -1
  66. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +4 -2
  67. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +6 -1
  68. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +5 -2
  69. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +6 -1
  70. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +5 -2
  71. data/lib/datadog/tracing/contrib/patcher.rb +0 -1
  72. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +6 -1
  73. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +5 -2
  74. data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +6 -1
  75. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +4 -2
  76. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +10 -2
  77. data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +9 -1
  78. data/lib/datadog/tracing/contrib/racecar/event.rb +3 -1
  79. data/lib/datadog/tracing/contrib/rack/middlewares.rb +3 -1
  80. data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +6 -1
  81. data/lib/datadog/tracing/contrib/redis/tags.rb +4 -1
  82. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +6 -1
  83. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +4 -1
  84. data/lib/datadog/tracing/contrib/roda/patcher.rb +1 -1
  85. data/lib/datadog/tracing/contrib/sequel/database.rb +4 -1
  86. data/lib/datadog/tracing/contrib/sequel/dataset.rb +4 -1
  87. data/lib/datadog/tracing/contrib/sequel/utils.rb +4 -1
  88. data/lib/datadog/tracing/contrib/status_code_matcher.rb +0 -1
  89. data/lib/datadog/tracing/correlation.rb +0 -1
  90. data/lib/datadog/tracing/distributed/headers/ext.rb +1 -1
  91. data/lib/datadog/tracing/event.rb +0 -2
  92. data/lib/datadog/tracing/pipeline.rb +0 -2
  93. data/lib/datadog/tracing/runtime/metrics.rb +0 -2
  94. data/lib/datadog/tracing/sampling/rate_by_service_sampler.rb +0 -1
  95. data/lib/datadog/tracing/sampling/rate_sampler.rb +0 -2
  96. data/lib/datadog/tracing/sampling/rule.rb +0 -2
  97. data/lib/datadog/tracing/sampling/rule_sampler.rb +0 -2
  98. data/lib/datadog/tracing/span_operation.rb +0 -1
  99. data/lib/datadog/tracing/sync_writer.rb +0 -2
  100. data/lib/datadog/tracing/trace_operation.rb +0 -1
  101. data/lib/datadog/tracing/tracer.rb +0 -1
  102. data/lib/datadog/tracing/workers/trace_writer.rb +0 -1
  103. data/lib/datadog/tracing/workers.rb +0 -2
  104. data/lib/datadog/tracing/writer.rb +0 -2
  105. data/lib/ddtrace/version.rb +2 -2
  106. metadata +18 -19
  107. data/lib/datadog/appsec/contrib/configuration/settings.rb +0 -20
  108. data/lib/datadog/appsec/contrib/rack/configuration/settings.rb +0 -22
  109. data/lib/datadog/appsec/contrib/rails/configuration/settings.rb +0 -22
  110. data/lib/datadog/appsec/contrib/sinatra/configuration/settings.rb +0 -22
@@ -208,7 +208,11 @@ module Datadog
208
208
  # Used internally to ensure a clean environment between test runs.
209
209
  def reset!
210
210
  safely_synchronize do |write_components|
211
- @components.shutdown! if components?
211
+ if components?
212
+ @components.shutdown!
213
+ @temp_logger = nil # Reset to ensure instance and log level are reset for next run
214
+ end
215
+
212
216
  write_components.call(nil)
213
217
  configuration.reset!
214
218
  end
@@ -23,7 +23,7 @@ module Datadog
23
23
  private
24
24
 
25
25
  def register(settings)
26
- if settings.appsec.enabled
26
+ if settings.respond_to?(:appsec) && settings.appsec.enabled
27
27
  register_capabilities(Datadog::AppSec::Remote.capabilities)
28
28
  register_products(Datadog::AppSec::Remote.products)
29
29
  register_receivers(Datadog::AppSec::Remote.receivers)
@@ -56,7 +56,8 @@ module Datadog
56
56
  def dependencies
57
57
  Gem.loaded_specs.collect do |name, loaded_gem|
58
58
  Datadog::Core::Telemetry::V1::Dependency.new(
59
- name: name, version: loaded_gem.version.to_s, hash: loaded_gem.hash.to_s
59
+ # `hash` should be used when `version` is not available
60
+ name: name, version: loaded_gem.version.to_s, hash: nil
60
61
  )
61
62
  end
62
63
  end
@@ -17,9 +17,10 @@ module Datadog
17
17
 
18
18
  # @param name [String] Module name
19
19
  # @param version [String] Version of resolved module
20
- # @param hash [String] Dependency hash
20
+ # @param hash [String] Dependency hash, in case `version` is not available
21
21
  def initialize(name:, version: nil, hash: nil)
22
22
  raise ArgumentError, ERROR_NIL_NAME_MESSAGE if name.nil?
23
+ raise ArgumentError, 'if both :version and :hash exist, use :version only' if version && hash
23
24
 
24
25
  @hash = hash
25
26
  @name = name
@@ -14,38 +14,68 @@ module Datadog
14
14
  #
15
15
  # This method is experimental and may change in the future.
16
16
  #
17
- # @param trace [TraceOperation] Trace to attach data to.
17
+ # @param trace [TraceOperation] Trace to attach data to. Defaults to
18
+ # active trace.
19
+ # @param span [SpanOperation] Span to attach data to. Defaults to
20
+ # active span on trace. Note that this should be a service entry span.
21
+ # When AppSec is enabled, the expected span and trace are automatically
22
+ # used as defaults.
18
23
  # @param user [Hash<Symbol, String>] User information to pass to
19
24
  # Datadog::Kit::Identity.set_user. Must contain at least :id as key.
20
25
  # @param others [Hash<String || Symbol, String>] Additional free-form
21
26
  # event information to attach to the trace.
22
- def self.track_login_success(trace, user:, **others)
23
- track(LOGIN_SUCCESS_EVENT, trace, **others)
27
+ def self.track_login_success(trace = nil, span = nil, user:, **others)
28
+ if (appsec_scope = Datadog::AppSec.active_scope)
29
+ trace = appsec_scope.trace
30
+ span = appsec_scope.service_entry_span
31
+ end
32
+
33
+ trace ||= Datadog::Tracing.active_trace
34
+ span ||= trace.active_span || Datadog::Tracing.active_span
35
+
36
+ raise ArgumentError, "span #{span.span_id} does not belong to trace #{trace.id}" if trace.id != span.trace_id
37
+
38
+ track(LOGIN_SUCCESS_EVENT, trace, span, **others)
24
39
 
25
40
  user_options = user.dup
26
41
  user_id = user_options.delete(:id)
27
42
 
28
43
  raise ArgumentError, 'missing required key: :user => { :id }' if user_id.nil?
29
44
 
30
- Kit::Identity.set_user(trace, id: user_id, **user_options)
45
+ Kit::Identity.set_user(trace, span, id: user_id, **user_options)
31
46
  end
32
47
 
33
48
  # Attach login failure event information to the trace
34
49
  #
35
50
  # This method is experimental and may change in the future.
36
51
  #
37
- # @param trace [TraceOperation] Trace to attach data to.
52
+ # @param trace [TraceOperation] Trace to attach data to. Defaults to
53
+ # active trace.
54
+ # @param span [SpanOperation] Span to attach data to. Defaults to
55
+ # active span on trace. Note that this should be a service entry span.
56
+ # When AppSec is enabled, the expected span and trace are automatically
57
+ # used as defaults.
38
58
  # @param user_id [String] User id that attempted login
39
59
  # @param user_exists [bool] Whether the user id that did a login attempt exists.
40
60
  # @param others [Hash<String || Symbol, String>] Additional free-form
41
61
  # event information to attach to the trace.
42
- def self.track_login_failure(trace, user_id:, user_exists:, **others)
43
- track(LOGIN_FAILURE_EVENT, trace, **others)
62
+ def self.track_login_failure(trace = nil, span = nil, user_id:, user_exists:, **others)
63
+ if (appsec_scope = Datadog::AppSec.active_scope)
64
+ trace = appsec_scope.trace
65
+ span = appsec_scope.service_entry_span
66
+ end
67
+
68
+ trace ||= Datadog::Tracing.active_trace
69
+ span ||= trace.active_span || Datadog::Tracing.active_span
70
+
71
+ raise ArgumentError, "span #{span.span_id} does not belong to trace #{trace.id}" if trace.id != span.trace_id
72
+
73
+ track(LOGIN_FAILURE_EVENT, trace, span, **others)
44
74
 
45
75
  raise ArgumentError, 'user_id cannot be nil' if user_id.nil?
46
76
 
47
- trace.set_tag('appsec.events.users.login.failure.usr.id', user_id)
48
- trace.set_tag('appsec.events.users.login.failure.usr.exists', user_exists)
77
+ span.set_tag('appsec.events.users.login.failure.usr.id', user_id)
78
+ span.set_tag('appsec.events.users.login.failure.usr.exists', user_exists)
49
79
  end
50
80
 
51
81
  # Attach custom event information to the trace
@@ -53,17 +83,32 @@ module Datadog
53
83
  # This method is experimental and may change in the future.
54
84
  #
55
85
  # @param event [String] Mandatory. Event code.
56
- # @param trace [TraceOperation] Trace to attach data to.
86
+ # @param trace [TraceOperation] Trace to attach data to. Defaults to
87
+ # active trace.
88
+ # @param span [SpanOperation] Span to attach data to. Defaults to
89
+ # active span on trace. Note that this should be a service entry span.
90
+ # When AppSec is enabled, the expected span and trace are automatically
91
+ # used as defaults.
57
92
  # @param others [Hash<Symbol, String>] Additional free-form
58
93
  # event information to attach to the trace. Key must not
59
94
  # be :track.
60
- def self.track(event, trace, **others)
61
- trace.set_tag("appsec.events.#{event}.track", 'true')
95
+ def self.track(event, trace = nil, span = nil, **others)
96
+ if (appsec_scope = Datadog::AppSec.active_scope)
97
+ trace = appsec_scope.trace
98
+ span = appsec_scope.service_entry_span
99
+ end
100
+
101
+ trace ||= Datadog::Tracing.active_trace
102
+ span ||= trace.active_span || Datadog::Tracing.active_span
103
+
104
+ raise ArgumentError, "span #{span.span_id} does not belong to trace #{trace.id}" if trace.id != span.trace_id
105
+
106
+ span.set_tag("appsec.events.#{event}.track", 'true')
62
107
 
63
108
  others.each do |k, v|
64
109
  raise ArgumentError, 'key cannot be :track' if k.to_sym == :track
65
110
 
66
- trace.set_tag("appsec.events.#{event}.#{k}", v) unless v.nil?
111
+ span.set_tag("appsec.events.#{event}.#{k}", v) unless v.nil?
67
112
  end
68
113
 
69
114
  trace.keep!
@@ -8,7 +8,12 @@ module Datadog
8
8
  module Identity
9
9
  # Attach user information to the trace
10
10
  #
11
- # @param trace [TraceOperation] Trace to attach data to.
11
+ # @param trace [TraceOperation] Trace to attach data to. Defaults to
12
+ # active trace.
13
+ # @param span [SpanOperation] Span to attach data to. Defaults to
14
+ # active span on trace. Note that this should be a service entry span.
15
+ # When AppSec is enabled, the expected span and trace are automatically
16
+ # used as defaults.
12
17
  # @param id [String] Mandatory. Username or client id extracted
13
18
  # from the access token or Authorization header in the inbound request
14
19
  # from outside the system.
@@ -29,7 +34,10 @@ module Datadog
29
34
  #
30
35
  # rubocop:disable Metrics/CyclomaticComplexity
31
36
  # rubocop:disable Metrics/PerceivedComplexity
32
- def self.set_user(trace, id:, email: nil, name: nil, session_id: nil, role: nil, scope: nil, **others)
37
+ # rubocop:disable Metrics/AbcSize
38
+ def self.set_user(
39
+ trace = nil, span = nil, id:, email: nil, name: nil, session_id: nil, role: nil, scope: nil, **others
40
+ )
33
41
  raise ArgumentError, 'missing required key: :id' if id.nil?
34
42
 
35
43
  # enforce types
@@ -45,24 +53,35 @@ module Datadog
45
53
  raise TypeError, "#{k.inspect} must be a String" unless v.nil? || v.is_a?(String)
46
54
  end
47
55
 
56
+ if (appsec_scope = Datadog::AppSec.active_scope)
57
+ trace = appsec_scope.trace
58
+ span = appsec_scope.service_entry_span
59
+ end
60
+
61
+ trace ||= Datadog::Tracing.active_trace
62
+ span ||= trace.active_span || Datadog::Tracing.active_span
63
+
64
+ raise ArgumentError, "span #{span.span_id} does not belong to trace #{trace.id}" if trace.id != span.trace_id
65
+
48
66
  # set tags once data is known consistent
49
67
 
50
- trace.set_tag('usr.id', id)
51
- trace.set_tag('usr.email', email) unless email.nil?
52
- trace.set_tag('usr.name', name) unless name.nil?
53
- trace.set_tag('usr.session_id', session_id) unless session_id.nil?
54
- trace.set_tag('usr.role', role) unless role.nil?
55
- trace.set_tag('usr.scope', scope) unless scope.nil?
68
+ span.set_tag('usr.id', id)
69
+ span.set_tag('usr.email', email) unless email.nil?
70
+ span.set_tag('usr.name', name) unless name.nil?
71
+ span.set_tag('usr.session_id', session_id) unless session_id.nil?
72
+ span.set_tag('usr.role', role) unless role.nil?
73
+ span.set_tag('usr.scope', scope) unless scope.nil?
56
74
 
57
75
  others.each do |k, v|
58
- trace.set_tag("usr.#{k}", v) unless v.nil?
76
+ span.set_tag("usr.#{k}", v) unless v.nil?
59
77
  end
60
78
 
61
- if Datadog.configuration.appsec.enabled
79
+ if appsec_scope
62
80
  user = ::Datadog::AppSec::Instrumentation::Gateway::User.new(id)
63
81
  ::Datadog::AppSec::Instrumentation.gateway.push('identity.set_user', user)
64
82
  end
65
83
  end
84
+ # rubocop:enable Metrics/AbcSize
66
85
  # rubocop:enable Metrics/PerceivedComplexity
67
86
  # rubocop:enable Metrics/CyclomaticComplexity
68
87
  end
@@ -20,6 +20,7 @@ module Datadog
20
20
  endpoint_collection_enabled:,
21
21
  gc_profiling_enabled:,
22
22
  allocation_counting_enabled:,
23
+ no_signals_workaround_enabled:,
23
24
  thread_context_collector: ThreadContext.new(
24
25
  recorder: recorder,
25
26
  max_frames: max_frames,
@@ -43,6 +44,7 @@ module Datadog
43
44
  gc_profiling_enabled,
44
45
  idle_sampling_helper,
45
46
  allocation_counting_enabled,
47
+ no_signals_workaround_enabled,
46
48
  dynamic_sampling_rate_enabled,
47
49
  )
48
50
  @worker_thread = nil
@@ -65,8 +65,6 @@ module Datadog
65
65
  # NOTE: Please update the Initialization section of ProfilingDevelopment.md with any changes to this method
66
66
 
67
67
  if enable_new_profiler?(settings)
68
- print_new_profiler_warnings
69
-
70
68
  recorder = Datadog::Profiling::StackRecorder.new(
71
69
  cpu_time_enabled: RUBY_PLATFORM.include?('linux'), # Only supported on Linux currently
72
70
  alloc_samples_enabled: false, # Always disabled for now -- work in progress
@@ -78,6 +76,7 @@ module Datadog
78
76
  endpoint_collection_enabled: settings.profiling.advanced.endpoint.collection.enabled,
79
77
  gc_profiling_enabled: enable_gc_profiling?(settings),
80
78
  allocation_counting_enabled: settings.profiling.advanced.allocation_counting_enabled,
79
+ no_signals_workaround_enabled: no_signals_workaround_enabled?(settings),
81
80
  )
82
81
  else
83
82
  recorder = build_profiler_old_recorder(settings)
@@ -141,19 +140,6 @@ module Datadog
141
140
  end
142
141
  end
143
142
 
144
- private_class_method def self.print_new_profiler_warnings
145
- return if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.6')
146
-
147
- # For more details on the issue, see the "BIG Issue" comment on `gvl_owner` function in
148
- # `private_vm_api_access.c`.
149
- Datadog.logger.warn(
150
- 'The new CPU Profiling 2.0 profiler has been force-enabled on a legacy Ruby version (< 2.6). This is not ' \
151
- 'recommended in production environments, as due to limitations in Ruby APIs, we suspect it may lead to crashes ' \
152
- 'in very rare situations. Please report any issues you run into to Datadog support or ' \
153
- 'via <https://github.com/datadog/dd-trace-rb/issues/new>!'
154
- )
155
- end
156
-
157
143
  private_class_method def self.enable_new_profiler?(settings)
158
144
  if settings.profiling.advanced.force_enable_legacy_profiler
159
145
  Datadog.logger.warn(
@@ -162,32 +148,71 @@ module Datadog
162
148
  return false
163
149
  end
164
150
 
165
- return true if settings.profiling.advanced.force_enable_new_profiler
151
+ true
152
+ end
153
+
154
+ private_class_method def self.no_signals_workaround_enabled?(settings) # rubocop:disable Metrics/MethodLength
155
+ setting_value = settings.profiling.advanced.no_signals_workaround_enabled
156
+ legacy_ruby_that_should_use_workaround = RUBY_VERSION.start_with?('2.3.', '2.4.', '2.5.')
157
+
158
+ unless [true, false, :auto].include?(setting_value)
159
+ Datadog.logger.error(
160
+ "Ignoring invalid value for profiling no_signals_workaround_enabled setting: #{setting_value.inspect}. " \
161
+ 'Valid options are `true`, `false` or (default) `:auto`.'
162
+ )
163
+
164
+ setting_value = :auto
165
+ end
166
+
167
+ if setting_value == false
168
+ if legacy_ruby_that_should_use_workaround
169
+ Datadog.logger.warn(
170
+ 'The profiling "no signals" workaround has been disabled via configuration on a legacy Ruby version ' \
171
+ '(< 2.6). This is not recommended ' \
172
+ 'in production environments, as due to limitations in Ruby APIs, we suspect it may lead to crashes ' \
173
+ 'in very rare situations. Please report any issues you run into to Datadog support or ' \
174
+ 'via <https://github.com/datadog/dd-trace-rb/issues/new>!'
175
+ )
176
+ else
177
+ Datadog.logger.warn('Profiling "no signals" workaround disabled via configuration')
178
+ end
179
+
180
+ return false
181
+ end
182
+
183
+ if setting_value == true
184
+ Datadog.logger.warn(
185
+ 'Profiling "no signals" workaround enabled via configuration. Profiling data will have lower quality.'
186
+ )
187
+
188
+ return true
189
+ end
190
+
191
+ # Setting is in auto mode. Let's probe to see if we should enable it:
166
192
 
167
- return false if RUBY_VERSION.start_with?('2.3.', '2.4.', '2.5.')
193
+ # We don't warn users in this situation because "upgrade your Ruby" is not a great warning
194
+ return true if legacy_ruby_that_should_use_workaround
168
195
 
169
196
  if Gem.loaded_specs['mysql2'] && incompatible_libmysqlclient_version?(settings)
170
197
  Datadog.logger.warn(
171
- 'Falling back to legacy profiler because an incompatible version of the mysql2 gem is installed. ' \
172
- 'Older versions of libmysqlclient (the C ' \
173
- 'library used by the mysql2 gem) have a bug in their signal handling code that the new profiler can trigger. ' \
174
- 'This bug (https://bugs.mysql.com/bug.php?id=83109) is fixed in libmysqlclient versions 8.0.0 and above. '
198
+ 'Enabling the profiling "no signals" workaround because an incompatible version of the mysql2 gem is ' \
199
+ 'installed. Profiling data will have lower quality.' \
200
+ 'To fix this, upgrade the libmysqlclient in your OS image to version 8.0.0 or above.'
175
201
  )
176
- return false
202
+ return true
177
203
  end
178
204
 
179
205
  if Gem.loaded_specs['rugged']
180
206
  Datadog.logger.warn(
181
- 'Falling back to legacy profiler because rugged gem is installed. Some operations on this gem are ' \
182
- 'currently incompatible with the new CPU Profiling 2.0 profiler, as detailed in ' \
183
- '<https://github.com/datadog/dd-trace-rb/issues/2721>. If you still want to try out the new profiler, you ' \
184
- 'can force-enable it by using the `DD_PROFILING_FORCE_ENABLE_NEW` environment variable or the ' \
185
- '`c.profiling.advanced.force_enable_new_profiler` setting.'
207
+ 'Enabling the profiling "no signals" workaround because the rugged gem is installed. ' \
208
+ 'This is needed because some operations on this gem are currently incompatible with the normal working mode ' \
209
+ 'of the profiler, as detailed in <https://github.com/datadog/dd-trace-rb/issues/2721>. ' \
210
+ 'Profiling data will have lower quality.'
186
211
  )
187
- return false
212
+ return true
188
213
  end
189
214
 
190
- true
215
+ false
191
216
  end
192
217
 
193
218
  # Versions of libmysqlclient prior to 8.0.0 are known to have buggy handling of system call interruptions.
@@ -1,4 +1,3 @@
1
- require_relative '../core'
2
1
  require_relative '../core/environment/ext'
3
2
  require_relative '../core/buffer/thread_safe'
4
3
  require_relative '../core/buffer/cruby'
@@ -26,7 +26,15 @@ module Datadog
26
26
  o.lazy
27
27
  end
28
28
 
29
- option :cache_service, default: Ext::SERVICE_CACHE
29
+ option :cache_service do |o|
30
+ o.default do
31
+ Contrib::SpanAttributeSchema.fetch_service_name(
32
+ '',
33
+ Ext::SERVICE_CACHE
34
+ )
35
+ end
36
+ o.lazy
37
+ end
30
38
  end
31
39
  end
32
40
  end
@@ -18,7 +18,17 @@ module Datadog
18
18
  TAG_OPERATION = 'aws.operation'.freeze
19
19
  TAG_OPERATION_COMMAND = 'command'.freeze
20
20
  TAG_PATH = 'path'.freeze
21
- TAG_REGION = 'aws.region'.freeze
21
+ TAG_AWS_REGION = 'aws.region'.freeze
22
+ TAG_REGION = 'region'.freeze
23
+ TAG_AWS_SERVICE = 'aws_service'.freeze
24
+ TAG_AWS_ACCOUNT = 'aws_account'.freeze
25
+ TAG_QUEUE_NAME = 'queuename'.freeze
26
+ TAG_TOPIC_NAME = 'topicname'.freeze
27
+ TAG_TABLE_NAME = 'tablename'.freeze
28
+ TAG_STREAM_NAME = 'streamname'.freeze
29
+ TAG_RULE_NAME = 'rulename'.freeze
30
+ TAG_STATE_MACHINE_NAME = 'statemachinename'.freeze
31
+ TAG_BUCKET_NAME = 'bucketname'.freeze
22
32
  end
23
33
  end
24
34
  end
@@ -33,6 +33,12 @@ module Datadog
33
33
  span.span_type = Tracing::Metadata::Ext::HTTP::TYPE_OUTBOUND
34
34
  span.name = Ext::SPAN_COMMAND
35
35
  span.resource = context.safely(:resource)
36
+ aws_service = span.resource.split('.')[0]
37
+ span.set_tag(Ext::TAG_AWS_SERVICE, aws_service)
38
+ params = context.safely(:params)
39
+ if (handler = Datadog::Tracing::Contrib::Aws::SERVICE_HANDLERS[aws_service])
40
+ handler.add_tags(span, params)
41
+ end
36
42
 
37
43
  span.set_tag(Tracing::Metadata::Ext::TAG_KIND, Tracing::Metadata::Ext::SpanKind::TAG_CLIENT)
38
44
 
@@ -55,6 +61,7 @@ module Datadog
55
61
  span.set_tag(Ext::TAG_AGENT, Ext::TAG_DEFAULT_AGENT)
56
62
  span.set_tag(Ext::TAG_OPERATION, context.safely(:operation))
57
63
  span.set_tag(Ext::TAG_REGION, context.safely(:region))
64
+ span.set_tag(Ext::TAG_AWS_REGION, context.safely(:region))
58
65
  span.set_tag(Ext::TAG_PATH, context.safely(:path))
59
66
  span.set_tag(Ext::TAG_HOST, context.safely(:host))
60
67
  span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_METHOD, context.safely(:http_method))
@@ -20,6 +20,10 @@ module Datadog
20
20
  context.operation_name
21
21
  end
22
22
 
23
+ def params
24
+ context.params
25
+ end
26
+
23
27
  def status_code
24
28
  context.http_response.status_code
25
29
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Tracing
5
+ module Contrib
6
+ module Aws
7
+ module Service
8
+ # Base class for all AWS service-specific tag handlers.
9
+ class Base
10
+ def add_tags(span, params); end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Tracing
5
+ module Contrib
6
+ module Aws
7
+ module Service
8
+ # DynamoDB tag handlers.
9
+ class DynamoDB < Base
10
+ def add_tags(span, params)
11
+ table_name = params[:table_name]
12
+ span.set_tag(Aws::Ext::TAG_TABLE_NAME, table_name)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Tracing
5
+ module Contrib
6
+ module Aws
7
+ module Service
8
+ # EventBridge tag handlers.
9
+ class EventBridge < Base
10
+ def add_tags(span, params)
11
+ rule_name = params[:name] || params[:rule]
12
+ span.set_tag(Aws::Ext::TAG_RULE_NAME, rule_name)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Tracing
5
+ module Contrib
6
+ module Aws
7
+ module Service
8
+ # Kinesis tag handlers.
9
+ class Kinesis < Base
10
+ def add_tags(span, params)
11
+ stream_arn = params[:stream_arn]
12
+ stream_name = params[:stream_name]
13
+
14
+ if stream_arn
15
+ # example stream_arn: arn:aws:kinesis:us-east-1:123456789012:stream/my-stream
16
+ parts = stream_arn.split(':')
17
+ stream_name = parts[-1].split('/')[-1]
18
+ aws_account = parts[-2]
19
+ span.set_tag(Aws::Ext::TAG_AWS_ACCOUNT, aws_account)
20
+ end
21
+
22
+ span.set_tag(Aws::Ext::TAG_STREAM_NAME, stream_name)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Tracing
5
+ module Contrib
6
+ module Aws
7
+ module Service
8
+ # S3 tag handlers.
9
+ class S3 < Base
10
+ def add_tags(span, params)
11
+ bucket_name = params[:bucket]
12
+ span.set_tag(Aws::Ext::TAG_BUCKET_NAME, bucket_name)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Tracing
5
+ module Contrib
6
+ module Aws
7
+ module Service
8
+ # SNS tag handlers.
9
+ class SNS < Base
10
+ def add_tags(span, params)
11
+ topic_arn = params[:topic_arn]
12
+ topic_name = params[:name]
13
+ if topic_arn
14
+ # example topic_arn: arn:aws:sns:us-west-2:123456789012:my-topic-name
15
+ parts = topic_arn.split(':')
16
+ topic_name = parts[-1]
17
+ aws_account = parts[-2]
18
+ span.set_tag(Aws::Ext::TAG_AWS_ACCOUNT, aws_account)
19
+ end
20
+ span.set_tag(Aws::Ext::TAG_TOPIC_NAME, topic_name)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Tracing
5
+ module Contrib
6
+ module Aws
7
+ module Service
8
+ # SQS tag handlers.
9
+ class SQS < Base
10
+ def add_tags(span, params)
11
+ queue_url = params[:queue_url]
12
+ queue_name = params[:queue_name]
13
+ if queue_url
14
+ _, _, _, aws_account, queue_name = queue_url.split('/')
15
+ span.set_tag(Aws::Ext::TAG_AWS_ACCOUNT, aws_account)
16
+ end
17
+ span.set_tag(Aws::Ext::TAG_QUEUE_NAME, queue_name)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Tracing
5
+ module Contrib
6
+ module Aws
7
+ module Service
8
+ # States tag handlers.
9
+ class States < Base
10
+ def add_tags(span, params)
11
+ state_machine_name = params[:name]
12
+ state_machine_arn = params[:state_machine_arn]
13
+ execution_arn = params[:execution_arn]
14
+ state_machine_account_id = ''
15
+
16
+ if execution_arn
17
+ # 'arn:aws:states:us-east-1:123456789012:execution:example-state-machine:example-execution'
18
+ parts = execution_arn.split(':')
19
+ state_machine_name = parts[-2]
20
+ state_machine_account_id = parts[4]
21
+ end
22
+
23
+ if state_machine_arn
24
+ # example statemachinearn: arn:aws:states:us-east-1:123456789012:stateMachine:MyStateMachine
25
+ parts = state_machine_arn.split(':')
26
+ state_machine_name ||= parts[-1]
27
+ state_machine_account_id = parts[-3]
28
+ end
29
+ span.set_tag(Aws::Ext::TAG_AWS_ACCOUNT, state_machine_account_id)
30
+ span.set_tag(Aws::Ext::TAG_STATE_MACHINE_NAME, state_machine_name)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end