datadog 2.8.0 → 2.10.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 (128) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +62 -1
  3. data/ext/datadog_profiling_native_extension/clock_id.h +2 -2
  4. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +66 -56
  5. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
  6. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +1 -1
  7. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +16 -16
  8. data/ext/datadog_profiling_native_extension/collectors_stack.c +7 -7
  9. data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
  10. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +221 -127
  11. data/ext/datadog_profiling_native_extension/heap_recorder.c +50 -92
  12. data/ext/datadog_profiling_native_extension/heap_recorder.h +2 -2
  13. data/ext/datadog_profiling_native_extension/http_transport.c +4 -4
  14. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +3 -0
  15. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +3 -1
  16. data/ext/datadog_profiling_native_extension/profiling.c +10 -8
  17. data/ext/datadog_profiling_native_extension/ruby_helpers.c +8 -8
  18. data/ext/datadog_profiling_native_extension/stack_recorder.c +63 -76
  19. data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -2
  20. data/ext/datadog_profiling_native_extension/time_helpers.h +1 -1
  21. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +47 -0
  22. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +31 -0
  23. data/ext/libdatadog_api/crashtracker.c +3 -0
  24. data/lib/datadog/appsec/actions_handler.rb +27 -0
  25. data/lib/datadog/appsec/assets/waf_rules/recommended.json +355 -157
  26. data/lib/datadog/appsec/assets/waf_rules/strict.json +62 -32
  27. data/lib/datadog/appsec/component.rb +14 -8
  28. data/lib/datadog/appsec/configuration/settings.rb +9 -0
  29. data/lib/datadog/appsec/context.rb +74 -0
  30. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +12 -8
  31. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +6 -6
  32. data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +4 -4
  33. data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +1 -7
  34. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +20 -30
  35. data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +6 -6
  36. data/lib/datadog/appsec/contrib/rack/gateway/response.rb +3 -3
  37. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +67 -96
  38. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +11 -11
  39. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +6 -6
  40. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +7 -7
  41. data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +10 -11
  42. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +43 -60
  43. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +23 -33
  44. data/lib/datadog/appsec/contrib/rails/patcher.rb +4 -14
  45. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +7 -7
  46. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +45 -65
  47. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +5 -28
  48. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +6 -6
  49. data/lib/datadog/appsec/event.rb +6 -6
  50. data/lib/datadog/appsec/ext.rb +8 -1
  51. data/lib/datadog/appsec/metrics/collector.rb +38 -0
  52. data/lib/datadog/appsec/metrics/exporter.rb +35 -0
  53. data/lib/datadog/appsec/metrics/telemetry.rb +23 -0
  54. data/lib/datadog/appsec/metrics.rb +13 -0
  55. data/lib/datadog/appsec/monitor/gateway/watcher.rb +23 -32
  56. data/lib/datadog/appsec/monitor/reactive/set_user.rb +6 -6
  57. data/lib/datadog/appsec/processor/rule_loader.rb +0 -3
  58. data/lib/datadog/appsec/processor.rb +4 -3
  59. data/lib/datadog/appsec/response.rb +18 -80
  60. data/lib/datadog/appsec/security_engine/result.rb +67 -0
  61. data/lib/datadog/appsec/security_engine/runner.rb +88 -0
  62. data/lib/datadog/appsec/security_engine.rb +9 -0
  63. data/lib/datadog/appsec.rb +17 -8
  64. data/lib/datadog/auto_instrument.rb +3 -0
  65. data/lib/datadog/core/configuration/agent_settings_resolver.rb +39 -11
  66. data/lib/datadog/core/configuration/components.rb +4 -2
  67. data/lib/datadog/core/configuration.rb +1 -1
  68. data/lib/datadog/{tracing → core}/contrib/rails/utils.rb +1 -3
  69. data/lib/datadog/core/crashtracking/component.rb +1 -3
  70. data/lib/datadog/core/telemetry/event.rb +87 -3
  71. data/lib/datadog/core/telemetry/logging.rb +2 -2
  72. data/lib/datadog/core/telemetry/metric.rb +22 -0
  73. data/lib/datadog/core/telemetry/worker.rb +33 -0
  74. data/lib/datadog/di/base.rb +115 -0
  75. data/lib/datadog/di/code_tracker.rb +7 -4
  76. data/lib/datadog/di/component.rb +19 -11
  77. data/lib/datadog/di/configuration/settings.rb +11 -1
  78. data/lib/datadog/di/contrib/railtie.rb +15 -0
  79. data/lib/datadog/di/contrib.rb +26 -0
  80. data/lib/datadog/di/error.rb +5 -0
  81. data/lib/datadog/di/instrumenter.rb +39 -18
  82. data/lib/datadog/di/{init.rb → preload.rb} +2 -4
  83. data/lib/datadog/di/probe_manager.rb +4 -4
  84. data/lib/datadog/di/probe_notification_builder.rb +22 -2
  85. data/lib/datadog/di/probe_notifier_worker.rb +5 -6
  86. data/lib/datadog/di/redactor.rb +0 -1
  87. data/lib/datadog/di/remote.rb +30 -9
  88. data/lib/datadog/di/transport.rb +2 -4
  89. data/lib/datadog/di.rb +5 -108
  90. data/lib/datadog/kit/appsec/events.rb +3 -3
  91. data/lib/datadog/kit/identity.rb +4 -4
  92. data/lib/datadog/profiling/component.rb +55 -53
  93. data/lib/datadog/profiling/http_transport.rb +1 -26
  94. data/lib/datadog/tracing/contrib/action_cable/integration.rb +5 -2
  95. data/lib/datadog/tracing/contrib/action_mailer/integration.rb +6 -2
  96. data/lib/datadog/tracing/contrib/action_pack/integration.rb +5 -2
  97. data/lib/datadog/tracing/contrib/action_view/integration.rb +5 -2
  98. data/lib/datadog/tracing/contrib/active_job/integration.rb +5 -2
  99. data/lib/datadog/tracing/contrib/active_record/integration.rb +6 -2
  100. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +3 -1
  101. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +3 -1
  102. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +10 -0
  103. data/lib/datadog/tracing/contrib/active_support/integration.rb +5 -2
  104. data/lib/datadog/tracing/contrib/auto_instrument.rb +2 -2
  105. data/lib/datadog/tracing/contrib/aws/integration.rb +3 -0
  106. data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +3 -0
  107. data/lib/datadog/tracing/contrib/extensions.rb +15 -3
  108. data/lib/datadog/tracing/contrib/http/integration.rb +3 -0
  109. data/lib/datadog/tracing/contrib/httprb/integration.rb +3 -0
  110. data/lib/datadog/tracing/contrib/kafka/integration.rb +3 -0
  111. data/lib/datadog/tracing/contrib/mongodb/integration.rb +3 -0
  112. data/lib/datadog/tracing/contrib/opensearch/integration.rb +3 -0
  113. data/lib/datadog/tracing/contrib/presto/integration.rb +3 -0
  114. data/lib/datadog/tracing/contrib/rack/integration.rb +2 -2
  115. data/lib/datadog/tracing/contrib/rails/framework.rb +2 -2
  116. data/lib/datadog/tracing/contrib/rails/patcher.rb +1 -1
  117. data/lib/datadog/tracing/contrib/rest_client/integration.rb +3 -0
  118. data/lib/datadog/tracing/span.rb +12 -4
  119. data/lib/datadog/tracing/span_event.rb +123 -3
  120. data/lib/datadog/tracing/span_operation.rb +6 -0
  121. data/lib/datadog/tracing/transport/serializable_trace.rb +24 -6
  122. data/lib/datadog/version.rb +1 -1
  123. metadata +40 -17
  124. data/lib/datadog/appsec/contrib/sinatra/ext.rb +0 -14
  125. data/lib/datadog/appsec/processor/context.rb +0 -107
  126. data/lib/datadog/appsec/reactive/operation.rb +0 -68
  127. data/lib/datadog/appsec/scope.rb +0 -58
  128. data/lib/datadog/core/crashtracking/agent_base_url.rb +0 -21
@@ -3,7 +3,7 @@
3
3
  require_relative 'configuration/settings'
4
4
  require_relative 'patcher'
5
5
  require_relative '../integration'
6
- require_relative '../rails/utils'
6
+ require_relative '../../../core/contrib/rails/utils'
7
7
 
8
8
  module Datadog
9
9
  module Tracing
@@ -18,6 +18,10 @@ module Datadog
18
18
  # @public_api Changing the integration name or integration options can cause breaking changes
19
19
  register_as :action_mailer, auto_patch: false
20
20
 
21
+ def self.gem_name
22
+ 'actionmailer'
23
+ end
24
+
21
25
  def self.version
22
26
  Gem.loaded_specs['actionmailer'] && Gem.loaded_specs['actionmailer'].version
23
27
  end
@@ -33,7 +37,7 @@ module Datadog
33
37
  # enabled by rails integration so should only auto instrument
34
38
  # if detected that it is being used without rails
35
39
  def auto_instrument?
36
- !Contrib::Rails::Utils.railtie_supported?
40
+ !Core::Contrib::Rails::Utils.railtie_supported?
37
41
  end
38
42
 
39
43
  def new_configuration
@@ -4,7 +4,7 @@ require_relative 'configuration/settings'
4
4
  require_relative 'patcher'
5
5
  require_relative '../integration'
6
6
  require_relative '../rails/ext'
7
- require_relative '../rails/utils'
7
+ require_relative '../../../core/contrib/rails/utils'
8
8
 
9
9
  module Datadog
10
10
  module Tracing
@@ -18,6 +18,9 @@ module Datadog
18
18
 
19
19
  # @public_api Changing the integration name or integration options can cause breaking changes
20
20
  register_as :action_pack, auto_patch: false
21
+ def self.gem_name
22
+ 'actionpack'
23
+ end
21
24
 
22
25
  def self.version
23
26
  Gem.loaded_specs['actionpack'] && Gem.loaded_specs['actionpack'].version
@@ -34,7 +37,7 @@ module Datadog
34
37
  # enabled by rails integration so should only auto instrument
35
38
  # if detected that it is being used without rails
36
39
  def auto_instrument?
37
- !Contrib::Rails::Utils.railtie_supported?
40
+ !Core::Contrib::Rails::Utils.railtie_supported?
38
41
  end
39
42
 
40
43
  def new_configuration
@@ -4,7 +4,7 @@ require_relative 'configuration/settings'
4
4
  require_relative 'patcher'
5
5
  require_relative '../integration'
6
6
  require_relative '../rails/ext'
7
- require_relative '../rails/utils'
7
+ require_relative '../../../core/contrib/rails/utils'
8
8
 
9
9
  module Datadog
10
10
  module Tracing
@@ -18,6 +18,9 @@ module Datadog
18
18
 
19
19
  # @public_api Changing the integration name or integration options can cause breaking changes
20
20
  register_as :action_view, auto_patch: false
21
+ def self.gem_name
22
+ 'actionview'
23
+ end
21
24
 
22
25
  def self.version
23
26
  # ActionView is its own gem in Rails 4.1+
@@ -41,7 +44,7 @@ module Datadog
41
44
  # enabled by rails integration so should only auto instrument
42
45
  # if detected that it is being used without rails
43
46
  def auto_instrument?
44
- !Contrib::Rails::Utils.railtie_supported?
47
+ !Core::Contrib::Rails::Utils.railtie_supported?
45
48
  end
46
49
 
47
50
  def new_configuration
@@ -3,7 +3,7 @@
3
3
  require_relative 'configuration/settings'
4
4
  require_relative 'patcher'
5
5
  require_relative '../integration'
6
- require_relative '../rails/utils'
6
+ require_relative '../../../core/contrib/rails/utils'
7
7
 
8
8
  module Datadog
9
9
  module Tracing
@@ -17,6 +17,9 @@ module Datadog
17
17
 
18
18
  # @public_api Changing the integration name or integration options can cause breaking changes
19
19
  register_as :active_job, auto_patch: false
20
+ def self.gem_name
21
+ 'activejob'
22
+ end
20
23
 
21
24
  def self.version
22
25
  Gem.loaded_specs['activejob'] && Gem.loaded_specs['activejob'].version
@@ -33,7 +36,7 @@ module Datadog
33
36
  # enabled by rails integration so should only auto instrument
34
37
  # if detected that it is being used without rails
35
38
  def auto_instrument?
36
- !Contrib::Rails::Utils.railtie_supported?
39
+ !Core::Contrib::Rails::Utils.railtie_supported?
37
40
  end
38
41
 
39
42
  def new_configuration
@@ -7,7 +7,7 @@ require_relative 'patcher'
7
7
  require_relative '../component'
8
8
  require_relative '../integration'
9
9
  require_relative '../rails/ext'
10
- require_relative '../rails/utils'
10
+ require_relative '../../../core/contrib/rails/utils'
11
11
 
12
12
  module Datadog
13
13
  module Tracing
@@ -22,6 +22,10 @@ module Datadog
22
22
  # @public_api Changing the integration name or integration options can cause breaking changes
23
23
  register_as :active_record, auto_patch: false
24
24
 
25
+ def self.gem_name
26
+ 'activerecord'
27
+ end
28
+
25
29
  def self.version
26
30
  Gem.loaded_specs['activerecord'] && Gem.loaded_specs['activerecord'].version
27
31
  end
@@ -37,7 +41,7 @@ module Datadog
37
41
  # enabled by rails integration so should only auto instrument
38
42
  # if detected that it is being used without rails
39
43
  def auto_instrument?
40
- !Contrib::Rails::Utils.railtie_supported?
44
+ !Core::Contrib::Rails::Utils.railtie_supported?
41
45
  end
42
46
 
43
47
  def new_configuration
@@ -81,7 +81,9 @@ module Datadog
81
81
 
82
82
  span.set_tag('EVENT', event)
83
83
 
84
- set_cache_key(span, key, mapping[:multi_key])
84
+ if Datadog.configuration.tracing[:active_support][:cache_key].enabled
85
+ set_cache_key(span, key, mapping[:multi_key])
86
+ end
85
87
  rescue StandardError => e
86
88
  Datadog.logger.error(e.message)
87
89
  Datadog::Core::Telemetry::Logger.report(e)
@@ -3,6 +3,7 @@
3
3
  require_relative '../../../../core/utils'
4
4
  require_relative '../../../metadata/ext'
5
5
  require_relative '../ext'
6
+ require_relative 'event'
6
7
 
7
8
  module Datadog
8
9
  module Tracing
@@ -58,7 +59,8 @@ module Datadog
58
59
  end
59
60
 
60
61
  span.set_tag(Ext::TAG_CACHE_BACKEND, store) if store
61
- set_cache_key(span, key, multi_key)
62
+
63
+ set_cache_key(span, key, multi_key) if Datadog.configuration.tracing[:active_support][:cache_key].enabled
62
64
 
63
65
  yield
64
66
  end
@@ -39,6 +39,16 @@ module Datadog
39
39
  )
40
40
  end
41
41
  end
42
+
43
+ # grouped "cache_key.*" settings
44
+ settings :cache_key do
45
+ # enable or disabling the inclusion of the cache_key in the span
46
+ option :enabled do |o|
47
+ # cache_key.enabled
48
+ o.type :bool
49
+ o.default true
50
+ end
51
+ end
42
52
  end
43
53
  end
44
54
  end
@@ -5,7 +5,7 @@ require_relative 'configuration/settings'
5
5
  require_relative 'patcher'
6
6
  require_relative 'cache/redis'
7
7
  require_relative '../rails/ext'
8
- require_relative '../rails/utils'
8
+ require_relative '../../../core/contrib/rails/utils'
9
9
 
10
10
  module Datadog
11
11
  module Tracing
@@ -19,6 +19,9 @@ module Datadog
19
19
 
20
20
  # @public_api Changing the integration name or integration options can cause breaking changes
21
21
  register_as :active_support, auto_patch: false
22
+ def self.gem_name
23
+ 'activesupport'
24
+ end
22
25
 
23
26
  def self.version
24
27
  Gem.loaded_specs['activesupport'] && Gem.loaded_specs['activesupport'].version
@@ -35,7 +38,7 @@ module Datadog
35
38
  # enabled by rails integration so should only auto instrument
36
39
  # if detected that it is being used without rails
37
40
  def auto_instrument?
38
- !Contrib::Rails::Utils.railtie_supported?
41
+ !Core::Contrib::Rails::Utils.railtie_supported?
39
42
  end
40
43
 
41
44
  def new_configuration
@@ -9,10 +9,10 @@ module Datadog
9
9
  module Contrib
10
10
  # Auto-activate instrumentation
11
11
  def self.auto_instrument!
12
- require_relative 'rails/utils'
12
+ require_relative '../../core/contrib/rails/utils'
13
13
 
14
14
  # Defer to Rails if this is a Rails application
15
- if Datadog::Tracing::Contrib::Rails::Utils.railtie_supported?
15
+ if Datadog::Core::Contrib::Rails::Utils.railtie_supported?
16
16
  require_relative 'rails/auto_instrument_railtie'
17
17
  else
18
18
  AutoInstrument.patch_all!
@@ -16,6 +16,9 @@ module Datadog
16
16
 
17
17
  # @public_api Changing the integration name or integration options can cause breaking changes
18
18
  register_as :aws, auto_patch: true
19
+ def self.gem_name
20
+ 'aws-sdk'
21
+ end
19
22
 
20
23
  def self.version
21
24
  if Gem.loaded_specs['aws-sdk']
@@ -16,6 +16,9 @@ module Datadog
16
16
 
17
17
  # @public_api Changing the integration name or integration options can cause breaking changes
18
18
  register_as :concurrent_ruby
19
+ def self.gem_name
20
+ 'concurrent-ruby'
21
+ end
19
22
 
20
23
  def self.version
21
24
  Gem.loaded_specs['concurrent-ruby'] && Gem.loaded_specs['concurrent-ruby'].version
@@ -110,6 +110,13 @@ module Datadog
110
110
  module Settings
111
111
  InvalidIntegrationError = Class.new(StandardError)
112
112
 
113
+ # Used to avoid concurrency issues between registering integrations (e.g. mutation) and reporting the
114
+ # current integrations for logging/debugging/telemetry purposes (e.g. iteration) in the
115
+ # `@instrumented_integrations` hash.
116
+ #
117
+ # See https://github.com/DataDog/dd-trace-rb/issues/2851 for details on the original issue.
118
+ INSTRUMENTED_INTEGRATIONS_LOCK = Mutex.new
119
+
113
120
  def self.included(base)
114
121
  base.class_eval do
115
122
  settings :contrib do
@@ -161,7 +168,10 @@ module Datadog
161
168
  configuration_name = options[:describes] || :default
162
169
  filtered_options = options.reject { |k, _v| k == :describes }
163
170
  integration.configure(configuration_name, filtered_options, &block)
164
- instrumented_integrations[integration_name] = integration
171
+ INSTRUMENTED_INTEGRATIONS_LOCK.synchronize do
172
+ @instrumented_integrations ||= {}
173
+ @instrumented_integrations[integration_name] = integration
174
+ end
165
175
 
166
176
  # Add to activation list
167
177
  integrations_pending_activation << integration
@@ -192,14 +202,16 @@ module Datadog
192
202
  @integrations_pending_activation ||= Set.new
193
203
  end
194
204
 
205
+ # This method is only for logging/debugging/telemetry purposes (e.g. iteration) in the
206
+ # `@instrumented_integrations` hash.
195
207
  # @!visibility private
196
208
  def instrumented_integrations
197
- @instrumented_integrations ||= {}
209
+ INSTRUMENTED_INTEGRATIONS_LOCK.synchronize { (@instrumented_integrations&.dup || {}).freeze }
198
210
  end
199
211
 
200
212
  # @!visibility private
201
213
  def reset!
202
- instrumented_integrations.clear
214
+ INSTRUMENTED_INTEGRATIONS_LOCK.synchronize { @instrumented_integrations&.clear }
203
215
  super
204
216
  end
205
217
 
@@ -22,6 +22,9 @@ module Datadog
22
22
 
23
23
  # @public_api Changing the integration name or integration options can cause breaking changes
24
24
  register_as :http, auto_patch: true
25
+ def self.gem_name
26
+ 'net-http'
27
+ end
25
28
 
26
29
  def self.version
27
30
  Gem::Version.new(RUBY_VERSION)
@@ -17,6 +17,9 @@ module Datadog
17
17
 
18
18
  # @public_api Changing the integration name or integration options can cause breaking changes
19
19
  register_as :httprb
20
+ def self.gem_name
21
+ 'http'
22
+ end
20
23
 
21
24
  def self.version
22
25
  Gem.loaded_specs['http'] && Gem.loaded_specs['http'].version
@@ -16,6 +16,9 @@ module Datadog
16
16
 
17
17
  # @public_api Changing the integration name or integration options can cause breaking changes
18
18
  register_as :kafka, auto_patch: false
19
+ def self.gem_name
20
+ 'ruby-kafka'
21
+ end
19
22
 
20
23
  def self.version
21
24
  Gem.loaded_specs['ruby-kafka'] && Gem.loaded_specs['ruby-kafka'].version
@@ -17,6 +17,9 @@ module Datadog
17
17
 
18
18
  # @public_api Changing the integration name or integration options can cause breaking changes
19
19
  register_as :mongo, auto_patch: true
20
+ def self.gem_name
21
+ 'mongo'
22
+ end
20
23
 
21
24
  def self.version
22
25
  Gem.loaded_specs['mongo'] && Gem.loaded_specs['mongo'].version
@@ -16,6 +16,9 @@ module Datadog
16
16
 
17
17
  # @public_api Changing the integration name or integration options can cause breaking changes
18
18
  register_as :opensearch, auto_patch: true
19
+ def self.gem_name
20
+ 'opensearch-ruby'
21
+ end
19
22
 
20
23
  def self.version
21
24
  Gem.loaded_specs['opensearch-ruby'] \
@@ -16,6 +16,9 @@ module Datadog
16
16
 
17
17
  # @public_api Changing the integration name or integration options can cause breaking changes
18
18
  register_as :presto
19
+ def self.gem_name
20
+ 'presto-client'
21
+ end
19
22
 
20
23
  def self.version
21
24
  Gem.loaded_specs['presto-client'] && Gem.loaded_specs['presto-client'].version
@@ -3,7 +3,7 @@
3
3
  require_relative '../integration'
4
4
  require_relative 'configuration/settings'
5
5
  require_relative 'patcher'
6
- require_relative '../rails/utils'
6
+ require_relative '../../../core/contrib/rails/utils'
7
7
 
8
8
  module Datadog
9
9
  module Tracing
@@ -33,7 +33,7 @@ module Datadog
33
33
  # enabled by rails integration so should only auto instrument
34
34
  # if detected that it is being used without rails
35
35
  def auto_instrument?
36
- !Contrib::Rails::Utils.railtie_supported?
36
+ !Core::Contrib::Rails::Utils.railtie_supported?
37
37
  end
38
38
 
39
39
  def new_configuration
@@ -9,7 +9,7 @@ require_relative '../active_support/integration'
9
9
  require_relative '../grape/endpoint'
10
10
  require_relative '../lograge/integration'
11
11
  require_relative 'ext'
12
- require_relative 'utils'
12
+ require_relative '../../../core/contrib/rails/utils'
13
13
  require_relative '../semantic_logger/integration'
14
14
 
15
15
  module Datadog
@@ -41,7 +41,7 @@ module Datadog
41
41
  # being executed, but here we know better, get it from Rails config.
42
42
  # Don't set this if service has been explicitly provided by the user.
43
43
  if datadog_config.service_without_fallback.nil?
44
- datadog_config.service = rails_config[:service_name] || Utils.app_name
44
+ datadog_config.service = rails_config[:service_name] || Core::Contrib::Rails::Utils.app_name
45
45
  end
46
46
 
47
47
  activate_rack!(datadog_config, rails_config)
@@ -6,7 +6,7 @@ require_relative 'framework'
6
6
  require_relative 'log_injection'
7
7
  require_relative 'middlewares'
8
8
  require_relative 'runner'
9
- require_relative 'utils'
9
+ require_relative '../../../core/contrib/rails/utils'
10
10
  require_relative '../semantic_logger/patcher'
11
11
 
12
12
  module Datadog
@@ -16,6 +16,9 @@ module Datadog
16
16
 
17
17
  # @public_api Changing the integration name or integration options can cause breaking changes
18
18
  register_as :rest_client
19
+ def self.gem_name
20
+ 'rest-client'
21
+ end
19
22
 
20
23
  def self.version
21
24
  Gem.loaded_specs['rest-client'] && Gem.loaded_specs['rest-client'].version
@@ -112,7 +112,10 @@ module Datadog
112
112
 
113
113
  def duration
114
114
  return @duration if @duration
115
- return @end_time - @start_time if @start_time && @end_time
115
+
116
+ start_time = @start_time
117
+ end_time = @end_time
118
+ end_time - start_time if start_time && end_time
116
119
  end
117
120
 
118
121
  def set_error(e)
@@ -135,6 +138,8 @@ module Datadog
135
138
  # TODO: Change this to reflect attributes when serialization
136
139
  # isn't handled by this method.
137
140
  def to_hash
141
+ @meta['events'] = @events.map(&:to_hash).to_json unless @events.empty?
142
+
138
143
  h = {
139
144
  error: @status,
140
145
  meta: @meta,
@@ -154,8 +159,6 @@ module Datadog
154
159
  h[:duration] = duration_nano
155
160
  end
156
161
 
157
- h[:meta]['events'] = @events.map(&:to_hash).to_json unless @events.empty?
158
-
159
162
  h
160
163
  end
161
164
 
@@ -196,12 +199,17 @@ module Datadog
196
199
  # Used for serialization
197
200
  # @return [Integer] in nanoseconds since Epoch
198
201
  def start_time_nano
199
- @start_time.to_i * 1000000000 + @start_time.nsec
202
+ return unless (start_time = @start_time)
203
+
204
+ start_time.to_i * 1000000000 + start_time.nsec
200
205
  end
201
206
 
202
207
  # Used for serialization
203
208
  # @return [Integer] in nanoseconds since Epoch
204
209
  def duration_nano
210
+ duration = self.duration
211
+ return unless duration
212
+
205
213
  (duration * 1e9).to_i
206
214
  end
207
215
 
@@ -19,23 +19,143 @@ module Datadog
19
19
  # @return [Integer]
20
20
  attr_reader :time_unix_nano
21
21
 
22
+ # TODO: Accept {Time} as the time_unix_nano parameter, possibly in addition to the current nano integer.
22
23
  def initialize(
23
24
  name,
24
25
  attributes: nil,
25
26
  time_unix_nano: nil
26
27
  )
27
28
  @name = name
28
- @attributes = attributes || {}
29
+
30
+ @attributes = attributes.dup || {}
31
+ validate_attributes!(@attributes)
32
+ @attributes.transform_keys!(&:to_s)
33
+
29
34
  # OpenTelemetry SDK stores span event timestamps in nanoseconds (not seconds).
30
35
  # We will do the same here to avoid unnecessary conversions and inconsistencies.
31
36
  @time_unix_nano = time_unix_nano || (Time.now.to_r * 1_000_000_000).to_i
32
37
  end
33
38
 
39
+ # Converts the span event into a hash to be used by with the span tag serialization
40
+ # (`span.set_tag('events) = [event.to_hash]`). This serialization format has the drawback
41
+ # of being limiting span events to the size limit of a span tag.
42
+ # All Datadog agents support this format.
34
43
  def to_hash
35
- h = { name: @name, time_unix_nano: @time_unix_nano }
36
- h[:attributes] = attributes unless @attributes.empty?
44
+ h = { 'name' => @name, 'time_unix_nano' => @time_unix_nano }
45
+ h['attributes'] = @attributes unless @attributes.empty?
46
+ h
47
+ end
48
+
49
+ # Converts the span event into a hash to be used by the MessagePack serialization as a
50
+ # top-level span field (span.span_events = [event.to_native_format]).
51
+ # This serialization format removes the serialization limitations of the `span.set_tag('events)` approach,
52
+ # but is only supported by newer version of the Datadog agent.
53
+ def to_native_format
54
+ h = { 'name' => @name, 'time_unix_nano' => @time_unix_nano }
55
+
56
+ attr = {}
57
+ @attributes.each do |key, value|
58
+ attr[key] = if value.is_a?(Array)
59
+ { type: ARRAY_TYPE, array_value: value.map { |v| serialize_native_attribute(v) } }
60
+ else
61
+ serialize_native_attribute(value)
62
+ end
63
+ end
64
+
65
+ h['attributes'] = attr unless @attributes.empty?
66
+
37
67
  h
38
68
  end
69
+
70
+ private
71
+
72
+ MIN_INT64_SIGNED = -2**63
73
+ MAX_INT64_SIGNED = 2 << 63 - 1
74
+
75
+ # Checks the attributes hash to ensure it only contains serializable values.
76
+ # Invalid values are removed from the hash.
77
+ def validate_attributes!(attributes)
78
+ attributes.select! do |key, value|
79
+ case value
80
+ when Array
81
+ next true if value.empty?
82
+
83
+ first = value.first
84
+ case first
85
+ when String, Integer, Float
86
+ first_type = first.class
87
+ if value.all? { |v| v.is_a?(first_type) }
88
+ value.all? { |v| validate_scalar_attribute!(key, v) }
89
+ else
90
+ Datadog.logger.warn("Attribute #{key} array must be homogenous: #{value}.")
91
+ false
92
+ end
93
+ when TrueClass, FalseClass
94
+ if value.all? { |v| v.is_a?(TrueClass) || v.is_a?(FalseClass) }
95
+ value.all? { |v| validate_scalar_attribute!(key, v) }
96
+ else
97
+ Datadog.logger.warn("Attribute #{key} array must be homogenous: #{value}.")
98
+ false
99
+ end
100
+ else
101
+ Datadog.logger.warn("Attribute #{key} must be a string, number, or boolean: #{value}.")
102
+ false
103
+ end
104
+ when String, Numeric, TrueClass, FalseClass
105
+ validate_scalar_attribute!(key, value)
106
+ else
107
+ Datadog.logger.warn("Attribute #{key} must be a string, number, boolean, or array: #{value}.")
108
+ false
109
+ end
110
+ end
111
+ end
112
+
113
+ def validate_scalar_attribute!(key, value)
114
+ case value
115
+ when String, TrueClass, FalseClass
116
+ true
117
+ when Integer
118
+ # Cannot be larger than signed 64-bit integer
119
+ if value < MIN_INT64_SIGNED || value > MAX_INT64_SIGNED
120
+ Datadog.logger.warn("Attribute #{key} must be within the range of a signed 64-bit integer: #{value}.")
121
+ false
122
+ else
123
+ true
124
+ end
125
+ when Float
126
+ # Has to be finite
127
+ return true if value.finite?
128
+
129
+ Datadog.logger.warn("Attribute #{key} must be a finite number: #{value}.")
130
+ false
131
+ else
132
+ Datadog.logger.warn("Attribute #{key} must be a string, number, or boolean: #{value}.")
133
+ false
134
+ end
135
+ end
136
+
137
+ STRING_TYPE = 0
138
+ BOOLEAN_TYPE = 1
139
+ INTEGER_TYPE = 2
140
+ DOUBLE_TYPE = 3
141
+ ARRAY_TYPE = 4
142
+
143
+ # Serializes individual scalar attributes into the native format.
144
+ def serialize_native_attribute(value)
145
+ case value
146
+ when String
147
+ { type: STRING_TYPE, string_value: value }
148
+ when TrueClass, FalseClass
149
+ { type: BOOLEAN_TYPE, bool_value: value }
150
+ when Integer
151
+ { type: INTEGER_TYPE, int_value: value }
152
+ when Float
153
+ { type: DOUBLE_TYPE, double_value: value }
154
+ else
155
+ # This is technically unreachable due to the validation in #initialize.
156
+ raise ArgumentError, "Attribute must be a string, number, or boolean: #{value}."
157
+ end
158
+ end
39
159
  end
40
160
  end
41
161
  end
@@ -11,6 +11,8 @@ require_relative 'event'
11
11
  require_relative 'metadata'
12
12
  require_relative 'metadata/ext'
13
13
  require_relative 'span'
14
+ require_relative 'span_event'
15
+ require_relative 'span_link'
14
16
  require_relative 'utils'
15
17
 
16
18
  module Datadog
@@ -197,6 +199,9 @@ module Datadog
197
199
  end
198
200
 
199
201
  # Mark the span stopped at the current time
202
+ #
203
+ # steep:ignore:start
204
+ # Steep issue fixed in https://github.com/soutaro/steep/pull/1467
200
205
  def stop(stop_time = nil)
201
206
  # A span should not be stopped twice. Note that this is not thread-safe,
202
207
  # stop is called from multiple threads, a given span might be stopped
@@ -219,6 +224,7 @@ module Datadog
219
224
 
220
225
  self
221
226
  end
227
+ # steep:ignore:end
222
228
 
223
229
  # Return whether the duration is started or not
224
230
  def started?