datadog 2.15.0 → 2.17.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 (194) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +74 -2
  3. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +1 -4
  4. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +7 -0
  5. data/ext/datadog_profiling_native_extension/encoded_profile.c +22 -12
  6. data/ext/datadog_profiling_native_extension/encoded_profile.h +1 -0
  7. data/ext/datadog_profiling_native_extension/extconf.rb +3 -0
  8. data/ext/datadog_profiling_native_extension/heap_recorder.c +8 -1
  9. data/ext/datadog_profiling_native_extension/http_transport.c +45 -72
  10. data/ext/datadog_profiling_native_extension/stack_recorder.c +4 -5
  11. data/ext/libdatadog_api/crashtracker.c +11 -12
  12. data/ext/libdatadog_api/crashtracker.h +5 -0
  13. data/ext/libdatadog_api/datadog_ruby_common.c +1 -4
  14. data/ext/libdatadog_api/datadog_ruby_common.h +7 -0
  15. data/ext/libdatadog_api/init.c +15 -0
  16. data/ext/libdatadog_api/library_config.c +122 -0
  17. data/ext/libdatadog_api/library_config.h +19 -0
  18. data/ext/libdatadog_api/macos_development.md +3 -3
  19. data/ext/libdatadog_api/process_discovery.c +117 -0
  20. data/ext/libdatadog_api/process_discovery.h +5 -0
  21. data/ext/libdatadog_extconf_helpers.rb +1 -1
  22. data/lib/datadog/appsec/actions_handler.rb +3 -2
  23. data/lib/datadog/appsec/api_security/lru_cache.rb +49 -0
  24. data/lib/datadog/appsec/api_security.rb +9 -0
  25. data/lib/datadog/appsec/assets/waf_rules/recommended.json +1344 -0
  26. data/lib/datadog/appsec/assets/waf_rules/strict.json +1344 -0
  27. data/lib/datadog/appsec/autoload.rb +1 -1
  28. data/lib/datadog/appsec/component.rb +11 -4
  29. data/lib/datadog/appsec/configuration/settings.rb +31 -18
  30. data/lib/datadog/appsec/context.rb +1 -1
  31. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +10 -12
  32. data/lib/datadog/appsec/contrib/active_record/integration.rb +1 -1
  33. data/lib/datadog/appsec/contrib/active_record/patcher.rb +22 -22
  34. data/lib/datadog/appsec/contrib/devise/data_extractor.rb +2 -3
  35. data/lib/datadog/appsec/contrib/devise/ext.rb +1 -0
  36. data/lib/datadog/appsec/contrib/devise/integration.rb +1 -1
  37. data/lib/datadog/appsec/contrib/devise/patcher.rb +3 -5
  38. data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +17 -4
  39. data/lib/datadog/appsec/contrib/excon/integration.rb +1 -1
  40. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +9 -10
  41. data/lib/datadog/appsec/contrib/faraday/integration.rb +1 -1
  42. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +8 -9
  43. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +8 -9
  44. data/lib/datadog/appsec/contrib/graphql/integration.rb +1 -1
  45. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +22 -32
  46. data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
  47. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +16 -16
  48. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +11 -13
  49. data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
  50. data/lib/datadog/appsec/contrib/rails/patcher.rb +21 -21
  51. data/lib/datadog/appsec/contrib/rest_client/integration.rb +1 -1
  52. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +10 -11
  53. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +17 -23
  54. data/lib/datadog/appsec/contrib/sinatra/integration.rb +1 -1
  55. data/lib/datadog/appsec/event.rb +85 -95
  56. data/lib/datadog/appsec/instrumentation/gateway/argument.rb +5 -2
  57. data/lib/datadog/appsec/metrics/telemetry.rb +1 -1
  58. data/lib/datadog/appsec/monitor/gateway/watcher.rb +42 -12
  59. data/lib/datadog/appsec/processor/rule_loader.rb +26 -28
  60. data/lib/datadog/appsec/processor/rule_merger.rb +5 -5
  61. data/lib/datadog/appsec/processor.rb +1 -1
  62. data/lib/datadog/appsec/remote.rb +14 -13
  63. data/lib/datadog/appsec/response.rb +6 -6
  64. data/lib/datadog/appsec/security_engine/runner.rb +1 -1
  65. data/lib/datadog/appsec/security_event.rb +39 -0
  66. data/lib/datadog/appsec.rb +1 -1
  67. data/lib/datadog/core/buffer/random.rb +18 -2
  68. data/lib/datadog/core/configuration/agent_settings_resolver.rb +5 -5
  69. data/lib/datadog/core/configuration/agentless_settings_resolver.rb +176 -0
  70. data/lib/datadog/core/configuration/components.rb +48 -30
  71. data/lib/datadog/core/configuration/components_state.rb +23 -0
  72. data/lib/datadog/core/configuration/option.rb +79 -43
  73. data/lib/datadog/core/configuration/option_definition.rb +4 -4
  74. data/lib/datadog/core/configuration/options.rb +1 -1
  75. data/lib/datadog/core/configuration/settings.rb +20 -10
  76. data/lib/datadog/core/configuration/stable_config.rb +23 -0
  77. data/lib/datadog/core/configuration.rb +40 -16
  78. data/lib/datadog/core/crashtracking/component.rb +3 -10
  79. data/lib/datadog/core/encoding.rb +1 -1
  80. data/lib/datadog/core/environment/cgroup.rb +10 -12
  81. data/lib/datadog/core/environment/container.rb +38 -40
  82. data/lib/datadog/core/environment/ext.rb +6 -6
  83. data/lib/datadog/core/environment/git.rb +1 -0
  84. data/lib/datadog/core/environment/identity.rb +3 -3
  85. data/lib/datadog/core/environment/platform.rb +3 -3
  86. data/lib/datadog/core/environment/variable_helpers.rb +1 -1
  87. data/lib/datadog/core/error.rb +11 -9
  88. data/lib/datadog/core/logger.rb +2 -2
  89. data/lib/datadog/core/metrics/client.rb +20 -21
  90. data/lib/datadog/core/metrics/logging.rb +5 -5
  91. data/lib/datadog/core/process_discovery.rb +32 -0
  92. data/lib/datadog/core/rate_limiter.rb +4 -2
  93. data/lib/datadog/core/remote/client.rb +39 -31
  94. data/lib/datadog/core/remote/component.rb +3 -3
  95. data/lib/datadog/core/remote/configuration/digest.rb +7 -7
  96. data/lib/datadog/core/remote/configuration/path.rb +1 -1
  97. data/lib/datadog/core/remote/transport/http/client.rb +1 -1
  98. data/lib/datadog/core/remote/transport/http/config.rb +21 -5
  99. data/lib/datadog/core/remote/transport/http/negotiation.rb +1 -1
  100. data/lib/datadog/core/runtime/metrics.rb +4 -4
  101. data/lib/datadog/core/telemetry/component.rb +78 -53
  102. data/lib/datadog/core/telemetry/emitter.rb +23 -11
  103. data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +65 -0
  104. data/lib/datadog/core/telemetry/event/app_closing.rb +18 -0
  105. data/lib/datadog/core/telemetry/event/app_dependencies_loaded.rb +33 -0
  106. data/lib/datadog/core/telemetry/event/app_heartbeat.rb +18 -0
  107. data/lib/datadog/core/telemetry/event/app_integrations_change.rb +58 -0
  108. data/lib/datadog/core/telemetry/event/app_started.rb +179 -0
  109. data/lib/datadog/core/telemetry/event/base.rb +40 -0
  110. data/lib/datadog/core/telemetry/event/distributions.rb +18 -0
  111. data/lib/datadog/core/telemetry/event/generate_metrics.rb +43 -0
  112. data/lib/datadog/core/telemetry/event/log.rb +76 -0
  113. data/lib/datadog/core/telemetry/event/message_batch.rb +42 -0
  114. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +43 -0
  115. data/lib/datadog/core/telemetry/event.rb +17 -472
  116. data/lib/datadog/core/telemetry/http/adapters/net.rb +12 -97
  117. data/lib/datadog/core/telemetry/logger.rb +1 -1
  118. data/lib/datadog/core/telemetry/metric.rb +3 -3
  119. data/lib/datadog/core/telemetry/request.rb +3 -3
  120. data/lib/datadog/core/telemetry/transport/http/api.rb +43 -0
  121. data/lib/datadog/core/telemetry/transport/http/client.rb +49 -0
  122. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +92 -0
  123. data/lib/datadog/core/telemetry/transport/http.rb +63 -0
  124. data/lib/datadog/core/telemetry/transport/telemetry.rb +51 -0
  125. data/lib/datadog/core/telemetry/worker.rb +90 -24
  126. data/lib/datadog/core/transport/http/adapters/test.rb +2 -1
  127. data/lib/datadog/core/transport/http/builder.rb +13 -13
  128. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +6 -6
  129. data/lib/datadog/core/utils/duration.rb +32 -32
  130. data/lib/datadog/core/utils/forking.rb +2 -2
  131. data/lib/datadog/core/utils/network.rb +6 -6
  132. data/lib/datadog/core/utils/only_once_successful.rb +16 -5
  133. data/lib/datadog/core/utils/time.rb +20 -0
  134. data/lib/datadog/core/utils/truncation.rb +21 -0
  135. data/lib/datadog/core/vendor/multipart-post/multipart/post/composite_read_io.rb +1 -1
  136. data/lib/datadog/core/vendor/multipart-post/multipart/post/multipartable.rb +8 -8
  137. data/lib/datadog/core/vendor/multipart-post/multipart/post/parts.rb +7 -7
  138. data/lib/datadog/core/worker.rb +1 -1
  139. data/lib/datadog/core/workers/async.rb +29 -12
  140. data/lib/datadog/core/workers/interval_loop.rb +12 -1
  141. data/lib/datadog/core/workers/runtime_metrics.rb +2 -2
  142. data/lib/datadog/core.rb +8 -0
  143. data/lib/datadog/di/boot.rb +34 -0
  144. data/lib/datadog/di/remote.rb +2 -0
  145. data/lib/datadog/di.rb +5 -32
  146. data/lib/datadog/error_tracking/collector.rb +87 -0
  147. data/lib/datadog/error_tracking/component.rb +167 -0
  148. data/lib/datadog/error_tracking/configuration/settings.rb +63 -0
  149. data/lib/datadog/error_tracking/configuration.rb +11 -0
  150. data/lib/datadog/error_tracking/ext.rb +18 -0
  151. data/lib/datadog/error_tracking/extensions.rb +16 -0
  152. data/lib/datadog/error_tracking/filters.rb +77 -0
  153. data/lib/datadog/error_tracking.rb +18 -0
  154. data/lib/datadog/kit/identity.rb +1 -1
  155. data/lib/datadog/profiling/collectors/code_provenance.rb +1 -1
  156. data/lib/datadog/profiling/exporter.rb +1 -1
  157. data/lib/datadog/profiling/ext.rb +0 -1
  158. data/lib/datadog/profiling/flush.rb +1 -1
  159. data/lib/datadog/profiling/http_transport.rb +1 -6
  160. data/lib/datadog/profiling/scheduler.rb +8 -1
  161. data/lib/datadog/profiling/tag_builder.rb +1 -5
  162. data/lib/datadog/tracing/analytics.rb +1 -1
  163. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +4 -1
  164. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +33 -0
  165. data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +4 -0
  166. data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +2 -4
  167. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +10 -0
  168. data/lib/datadog/tracing/contrib/aws/parsed_context.rb +5 -1
  169. data/lib/datadog/tracing/contrib/http/instrumentation.rb +1 -5
  170. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +1 -5
  171. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +1 -5
  172. data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +2 -0
  173. data/lib/datadog/tracing/contrib/karafka/monitor.rb +1 -1
  174. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +8 -0
  175. data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -0
  176. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +18 -1
  177. data/lib/datadog/tracing/contrib/patcher.rb +5 -2
  178. data/lib/datadog/tracing/contrib/support.rb +28 -0
  179. data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
  180. data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
  181. data/lib/datadog/tracing/distributed/datadog.rb +2 -2
  182. data/lib/datadog/tracing/metadata/errors.rb +4 -4
  183. data/lib/datadog/tracing/sampling/rate_sampler.rb +2 -1
  184. data/lib/datadog/tracing/span_operation.rb +38 -14
  185. data/lib/datadog/tracing/trace_operation.rb +15 -7
  186. data/lib/datadog/tracing/tracer.rb +7 -3
  187. data/lib/datadog/tracing/utils.rb +1 -1
  188. data/lib/datadog/version.rb +1 -1
  189. data/lib/datadog.rb +2 -3
  190. metadata +53 -10
  191. data/lib/datadog/core/telemetry/http/env.rb +0 -20
  192. data/lib/datadog/core/telemetry/http/ext.rb +0 -28
  193. data/lib/datadog/core/telemetry/http/response.rb +0 -70
  194. data/lib/datadog/core/telemetry/http/transport.rb +0 -90
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../ext'
4
+
5
+ module Datadog
6
+ module ErrorTracking
7
+ module Configuration
8
+ # Settings
9
+ module Settings
10
+ def self.extended(base)
11
+ base = base.singleton_class unless base.is_a?(Class)
12
+ add_settings!(base)
13
+ end
14
+
15
+ def self.add_settings!(base)
16
+ base.class_eval do
17
+ # Error Tracking specific configurations.
18
+ # @public_api
19
+ settings :error_tracking do
20
+ # Enable automatic reporting of handled errors and defines the scope
21
+ # for which to report errors: user code, gems, or both. Possible
22
+ # values are: all | user | third_party.
23
+ #
24
+ # @default 'DD_ERROR_TRACKING_HANDLED_ERRORS' environment variable, otherwise `nil`
25
+ # @return [String, nil]
26
+ option :handled_errors do |o|
27
+ o.type :string, nilable: true
28
+ o.default Ext::DEFAULT_HANDLED_ERRORS
29
+ o.env Ext::ENV_HANDLED_ERRORS
30
+ o.setter do |value|
31
+ next value if Ext::VALID_HANDLED_ERRORS.include?(value)
32
+
33
+ unless value.nil?
34
+ Datadog.logger.warn(
35
+ "Invalid handled errors scope: #{value}. " \
36
+ "Supported values are: #{Ext::VALID_HANDLED_ERRORS.join(" | ")}. " \
37
+ 'Deactivating the feature.'
38
+ )
39
+ end
40
+
41
+ Ext::DEFAULT_HANDLED_ERRORS
42
+ end
43
+ end
44
+
45
+ # Enable automatic reporting of handled errors and specify what files should be
46
+ # instrumented. The value is a list of comma separated paths, filenames or gem names.
47
+ # The paths can be absolute, starting with '/' or relative to directory in which the program
48
+ # is launched, starting with './'.
49
+ #
50
+ # @default 'DD_ERROR_TRACKING_HANDLED_ERRORS_MODULES' environment variable, otherwise `nil`
51
+ # @return [String, nil]
52
+ option :handled_errors_include do |o|
53
+ o.type :array
54
+ o.default []
55
+ o.env Ext::ENV_HANDLED_ERRORS_INCLUDE
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module ErrorTracking
5
+ # Configuration for ErrorTracking
6
+ module Configuration
7
+ end
8
+ end
9
+ end
10
+
11
+ require_relative 'configuration/settings'
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module ErrorTracking
5
+ # Error Tracking constants
6
+ module Ext
7
+ ENV_HANDLED_ERRORS = 'DD_ERROR_TRACKING_HANDLED_ERRORS'
8
+ ENV_HANDLED_ERRORS_INCLUDE = 'DD_ERROR_TRACKING_HANDLED_ERRORS_INCLUDE'
9
+ HANDLED_ERRORS_ALL = 'all'
10
+ HANDLED_ERRORS_USER = 'user'
11
+ HANDLED_ERRORS_THIRD_PARTY = 'third_party'
12
+ DEFAULT_HANDLED_ERRORS = nil
13
+ VALID_HANDLED_ERRORS = [HANDLED_ERRORS_ALL, HANDLED_ERRORS_USER, HANDLED_ERRORS_THIRD_PARTY].freeze
14
+ SPAN_EVENTS_HAS_EXCEPTION = '_dd.span_events.has_exception'
15
+ RUBY_VERSION_WITH_RESCUE_EVENT = '3.3'
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'configuration'
4
+ require_relative '../core/configuration'
5
+
6
+ module Datadog
7
+ module ErrorTracking
8
+ # Extends Datadog tracing with ErrorTracking features
9
+ module Extensions
10
+ # Inject Error Tracking into global objects.
11
+ def self.activate!
12
+ Core::Configuration::Settings.extend(Configuration::Settings)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module ErrorTracking
5
+ # Based on configuration, the TracePoint listening to :rescue or :raise
6
+ # may report more handled errors than we want to report. Therefore we need
7
+ # a function to filter the events. As the filter function both depends
8
+ # on configuration and is called numerous time, we generate it during
9
+ # during the initialization of the feature to have the best performance
10
+ # possible.
11
+ #
12
+ # @api private
13
+ module Filters
14
+ module_function
15
+
16
+ def get_gem_name(file_path)
17
+ regex = %r{gems/([^/]+)-\d}
18
+ regex_match = regex.match(file_path)
19
+ return unless regex_match
20
+
21
+ gem_name = regex_match[1]
22
+
23
+ begin
24
+ Gem::Specification.find_by_name(gem_name) # steep:ignore
25
+ rescue Gem::MissingSpecError
26
+ nil
27
+ end
28
+ end
29
+
30
+ def user_code?(file_path)
31
+ !get_gem_name(file_path)
32
+ end
33
+
34
+ def datadog_code?(file_path)
35
+ file_path.include?('lib/datadog/')
36
+ end
37
+
38
+ def third_party_code?(file_path)
39
+ gem_name = get_gem_name(file_path)
40
+ gem_name && gem_name != "datadog"
41
+ end
42
+
43
+ def file_included?(file_path, instrumented_files)
44
+ instrumented_files.include?(file_path)
45
+ end
46
+
47
+ # Generate the proc used in the TracePoint
48
+ def generate_filter(to_instrument_scope, handled_errors_include = nil)
49
+ case to_instrument_scope
50
+ # If DD_ERROR_TRACKING_HANDLED_ERRORS is set
51
+ when 'all'
52
+ proc { |file_path| !datadog_code?(file_path) }
53
+ when 'user'
54
+ # If DD_ERROR_TRACKING_HANDLED_ERRORS_INCLUDE is set
55
+ if handled_errors_include
56
+ proc { |file_path|
57
+ user_code?(file_path) || file_included?(file_path, handled_errors_include)
58
+ }
59
+ else
60
+ proc { |file_path| user_code?(file_path) }
61
+ end
62
+ when 'third_party'
63
+ if handled_errors_include
64
+ proc { |file_path|
65
+ third_party_code?(file_path) || file_included?(file_path, handled_errors_include)
66
+ }
67
+ else
68
+ proc { |file_path| third_party_code?(file_path) }
69
+ end
70
+ else
71
+ # If only DD_ERROR_TRACKING_HANDLED_ERRORS_INCLUDE is set
72
+ proc { |file_path| file_included?(file_path, handled_errors_include) }
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'error_tracking/collector'
4
+ require_relative 'error_tracking/component'
5
+ require_relative 'error_tracking/configuration'
6
+ require_relative 'error_tracking/ext'
7
+ require_relative 'error_tracking/extensions'
8
+ require_relative 'error_tracking/filters'
9
+
10
+ module Datadog
11
+ # Namespace for Datadog ErrorTracking.
12
+ #
13
+ # @api private
14
+ module ErrorTracking
15
+ # Expose ErrorTracking to global shared objects
16
+ Extensions.activate!
17
+ end
18
+ end
@@ -70,7 +70,7 @@ module Datadog
70
70
  if Datadog::AppSec.active_context
71
71
  active_span.set_tag('_dd.appsec.user.collection_mode', 'sdk')
72
72
 
73
- user = ::Datadog::AppSec::Instrumentation::Gateway::User.new(id, others[:login])
73
+ user = ::Datadog::AppSec::Instrumentation::Gateway::User.new(id, others[:login], session_id)
74
74
  ::Datadog::AppSec::Instrumentation.gateway.push('identity.set_user', user)
75
75
  end
76
76
  end
@@ -42,7 +42,7 @@ module Datadog
42
42
  end
43
43
 
44
44
  def generate_json
45
- JSON.fast_generate(v1: seen_libraries.to_a)
45
+ JSON.generate(v1: seen_libraries.to_a)
46
46
  end
47
47
 
48
48
  private
@@ -49,7 +49,7 @@ module Datadog
49
49
  @internal_metadata = internal_metadata
50
50
  # NOTE: At the time of this comment collected info does not change over time so we'll hardcode
51
51
  # it on startup to prevent serializing the same info on every flush.
52
- @info_json = JSON.fast_generate(info_collector.info).freeze
52
+ @info_json = JSON.generate(info_collector.info).freeze
53
53
  end
54
54
 
55
55
  def flush
@@ -19,7 +19,6 @@ module Datadog
19
19
  FORM_FIELD_TAG_RUNTIME = "runtime"
20
20
  FORM_FIELD_TAG_RUNTIME_ENGINE = "runtime_engine"
21
21
  FORM_FIELD_TAG_RUNTIME_ID = "runtime-id"
22
- FORM_FIELD_TAG_RUNTIME_PLATFORM = "runtime_platform"
23
22
  FORM_FIELD_TAG_RUNTIME_VERSION = "runtime_version"
24
23
  FORM_FIELD_TAG_SERVICE = "service"
25
24
  FORM_FIELD_TAG_VERSION = "version"
@@ -32,7 +32,7 @@ module Datadog
32
32
  @code_provenance_file_name = code_provenance_file_name
33
33
  @code_provenance_data = code_provenance_data
34
34
  @tags_as_array = tags_as_array
35
- @internal_metadata_json = JSON.fast_generate(internal_metadata)
35
+ @internal_metadata_json = JSON.generate(internal_metadata)
36
36
  @info_json = info_json
37
37
  end
38
38
  end
@@ -29,12 +29,7 @@ module Datadog
29
29
  status, result = self.class._native_do_export(
30
30
  exporter_configuration,
31
31
  @upload_timeout_milliseconds,
32
- flush,
33
- # TODO: This is going to be removed once we move to libdatadog 17
34
- flush.start.tv_sec,
35
- flush.start.tv_nsec,
36
- flush.finish.tv_sec,
37
- flush.finish.tv_nsec,
32
+ flush
38
33
  )
39
34
 
40
35
  if status == :ok
@@ -37,6 +37,7 @@ module Datadog
37
37
  @exporter = exporter
38
38
  @transport = transport
39
39
  @profiler_failed = false
40
+ @stop_requested = false
40
41
 
41
42
  # Workers::Async::Thread settings
42
43
  self.fork_policy = fork_policy
@@ -88,7 +89,7 @@ module Datadog
88
89
  end
89
90
 
90
91
  def work_pending?
91
- !profiler_failed && exporter.can_flush?
92
+ !profiler_failed && exporter.can_flush? && (run_loop? || !stop_requested?)
92
93
  end
93
94
 
94
95
  def reset_after_fork
@@ -138,8 +139,14 @@ module Datadog
138
139
  Datadog::Core::Telemetry::Logger.report(e, description: "Unable to report profile")
139
140
  end
140
141
 
142
+ @stop_requested = !run_loop?
143
+
141
144
  true
142
145
  end
146
+
147
+ def stop_requested?
148
+ @stop_requested
149
+ end
143
150
  end
144
151
  end
145
152
  end
@@ -19,12 +19,9 @@ module Datadog
19
19
  host: Core::Environment::Socket.hostname,
20
20
  language: Core::Environment::Identity.lang,
21
21
  pid: Process.pid.to_s,
22
- # TODO: If profiling is extracted and its version diverges from the datadog gem, this is inaccurate.
23
- # Update if this ever occurs.
24
22
  profiler_version: Core::Environment::Identity.gem_datadog_version,
25
23
  runtime_engine: Core::Environment::Identity.lang_engine,
26
24
  runtime_id: Core::Environment::Identity.id,
27
- runtime_platform: Core::Environment::Identity.lang_platform,
28
25
  runtime_version: Core::Environment::Identity.lang_version,
29
26
  git_repository_url: Core::Environment::Git.git_repository_url,
30
27
  git_commit_sha: Core::Environment::Git.git_commit_sha,
@@ -41,7 +38,6 @@ module Datadog
41
38
  FORM_FIELD_TAG_RUNTIME => language, # This is known to be repeated from language, above
42
39
  FORM_FIELD_TAG_RUNTIME_ENGINE => runtime_engine,
43
40
  FORM_FIELD_TAG_RUNTIME_ID => runtime_id,
44
- FORM_FIELD_TAG_RUNTIME_PLATFORM => runtime_platform,
45
41
  FORM_FIELD_TAG_RUNTIME_VERSION => runtime_version,
46
42
  }
47
43
  tags[FORM_FIELD_TAG_ENV] = env if env
@@ -50,7 +46,7 @@ module Datadog
50
46
  tags[TAG_GIT_REPOSITORY_URL] = git_repository_url if git_repository_url
51
47
  tags[TAG_GIT_COMMIT_SHA] = git_commit_sha if git_commit_sha
52
48
 
53
- # Make sure everything is an utf-8 string, to avoid encoding issues in native code/libddprof/further downstream
49
+ # Make sure everything is an utf-8 string, to avoid encoding issues in native code/further downstream
54
50
  user_tags.merge(tags).map do |key, value|
55
51
  [Datadog::Core::Utils.utf8_encode(key), Datadog::Core::Utils.utf8_encode(value)]
56
52
  end.to_h
@@ -16,7 +16,7 @@ module Datadog
16
16
  def set_measured(span_op, value = true)
17
17
  return if span_op.nil?
18
18
 
19
- value = value == true || value == 1 ? 1 : 0 # rubocop:disable Style/MultipleComparison
19
+ value = value == true || value == 1 ? 1 : 0
20
20
  span_op.set_metric(Metadata::Ext::Analytics::TAG_MEASURED, value)
21
21
  end
22
22
  end
@@ -62,7 +62,10 @@ module Datadog
62
62
  end
63
63
 
64
64
  def on_start(span, event, _id, payload)
65
- key = payload[:key]
65
+ # Since Rails 8, `dd_original_keys` contains the denormalized key provided by the user.
66
+ # In previous versions, the denormalized key is stored in the official `key` attribute.
67
+ # We fall back to `key`, even in Rails 8, as a defensive measure.
68
+ key = payload[:dd_original_keys] || payload[:key]
66
69
  store = payload[:store]
67
70
 
68
71
  mapping = MAPPING.fetch(event)
@@ -184,6 +184,39 @@ module Datadog
184
184
  super(operation, key, polyfill_options)
185
185
  end
186
186
  end
187
+
188
+ # Save the original, user-supplied cache key, before it gets normalized.
189
+ #
190
+ # Normalized keys can include internal implementation detail,
191
+ # for example FileStore keys include temp directory names, which
192
+ # changes on every run, making it impossible to group by the cache key afterward.
193
+ # Also, the user is never exposed to the normalized key, and only sets/gets using the
194
+ # original key.
195
+ module PreserveOriginalKey
196
+ # Stores the original keys in the options hash, as an array of keys.
197
+ # It's important to keep all the keys for multi-key operations.
198
+ # For single-key operations, the key is stored as an array of a single element.
199
+ def normalize_key(key, options)
200
+ orig_keys = options[:dd_original_keys] || []
201
+ orig_keys << key
202
+ options[:dd_original_keys] = orig_keys
203
+
204
+ super
205
+ end
206
+
207
+ # Ensure we don't pollute the default Store instance `options` in {PreserveOriginalKey#normalize_key}.
208
+ # In most cases, `merged_options` returns a new hash,
209
+ # but we check for cases where it reuses the instance hash.
210
+ def merged_options(call_options)
211
+ ret = super
212
+
213
+ if ret.equal?(options)
214
+ ret.dup
215
+ else
216
+ ret
217
+ end
218
+ end
219
+ end
187
220
  end
188
221
  end
189
222
  end
@@ -22,6 +22,10 @@ module Datadog
22
22
  def patch
23
23
  Events.subscribe!
24
24
 
25
+ if Integration.version >= Gem::Version.new('8.0.0')
26
+ ::ActiveSupport::Cache::Store.prepend(Cache::Instrumentation::PreserveOriginalKey)
27
+ end
28
+
25
29
  # Backfill the `:store` key in the ActiveSupport event payload for older Rails.
26
30
  if Integration.version < Gem::Version.new('6.1.0')
27
31
  ::ActiveSupport::Cache::Store.prepend(Cache::Instrumentation::Store)
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../../support'
3
4
  require_relative 'patcher'
4
5
 
5
6
  module Datadog
@@ -34,10 +35,7 @@ module Datadog
34
35
  # @see https://github.com/rails/rails/blob/d0dcb8fa6073a0c4d42600c15e82e3bb386b27d3/activesupport/lib/active_support/cache/redis_cache_store.rb#L4
35
36
  def patch_redis_cache_store?(meth)
36
37
  Gem.loaded_specs['redis'] &&
37
- # Autoload constants return `constant` for `defined?`, but that doesn't mean they are loaded...
38
- defined?(::ActiveSupport::Cache::RedisCacheStore) &&
39
- # ... to check that we need to call `autoload?` and check if it returns `nil`, meaning it's loaded.
40
- ::ActiveSupport::Cache.autoload?(:RedisCacheStore).nil? &&
38
+ Support.fully_loaded?(::ActiveSupport::Cache, :RedisCacheStore) &&
41
39
  ::ActiveSupport::Cache::RedisCacheStore.instance_methods(false).include?(meth)
42
40
  end
43
41
 
@@ -35,6 +35,16 @@ module Datadog
35
35
  span.type = Tracing::Metadata::Ext::HTTP::TYPE_OUTBOUND
36
36
  span.name = Ext::SPAN_COMMAND
37
37
  span.resource = context.safely(:resource)
38
+
39
+ # Set error on the span if the Response Status Code is in error range
40
+ if Tracing::Metadata::Ext::HTTP::ERROR_RANGE.cover?(context.safely(:status_code))
41
+ # At this point we do not have any additional diagnostics
42
+ # besides the HTTP status code which is recorded in the span tags
43
+ # later in this method.
44
+ # Just set the span as errored.
45
+ span.set_error(nil)
46
+ end
47
+
38
48
  aws_service = span.resource.split('.')[0]
39
49
  span.set_tag(Ext::TAG_AWS_SERVICE, aws_service)
40
50
  params = context.safely(:params)
@@ -26,8 +26,12 @@ module Datadog
26
26
  context.params
27
27
  end
28
28
 
29
+ def http_response
30
+ context.http_response
31
+ end
32
+
29
33
  def status_code
30
- context.http_response.status_code
34
+ http_response.status_code
31
35
  end
32
36
 
33
37
  def http_method
@@ -30,7 +30,7 @@ module Datadog
30
30
 
31
31
  return super(req, body, &block) if Contrib::HTTP.should_skip_tracing?(req)
32
32
 
33
- Tracing.trace(Ext::SPAN_REQUEST, on_error: method(:annotate_span_with_error!)) do |span, trace|
33
+ Tracing.trace(Ext::SPAN_REQUEST) do |span, trace|
34
34
  span.service = service_name(host, request_options, client_config)
35
35
  span.type = Tracing::Metadata::Ext::HTTP::TYPE_OUTBOUND
36
36
  span.resource = req.method
@@ -112,10 +112,6 @@ module Datadog
112
112
  Datadog::Core::Telemetry::Logger.report(e)
113
113
  end
114
114
 
115
- def annotate_span_with_error!(span, error)
116
- span.set_error(error)
117
- end
118
-
119
115
  def set_analytics_sample_rate(span, request_options)
120
116
  return unless analytics_enabled?(request_options)
121
117
 
@@ -25,7 +25,7 @@ module Datadog
25
25
  request_options = datadog_configuration(host)
26
26
  client_config = Datadog.configuration_for(self)
27
27
 
28
- Tracing.trace(Ext::SPAN_REQUEST, on_error: method(:annotate_span_with_error!)) do |span, trace|
28
+ Tracing.trace(Ext::SPAN_REQUEST) do |span, trace|
29
29
  begin
30
30
  span.service = service_name(host, request_options, client_config)
31
31
  span.type = Tracing::Metadata::Ext::HTTP::TYPE_OUTBOUND
@@ -111,10 +111,6 @@ module Datadog
111
111
  Datadog::Core::Telemetry::Logger.report(e)
112
112
  end
113
113
 
114
- def annotate_span_with_error!(span, error)
115
- span.set_error(error)
116
- end
117
-
118
114
  def datadog_configuration(host = :default)
119
115
  Datadog.configuration.tracing[:httpclient, host]
120
116
  end
@@ -25,7 +25,7 @@ module Datadog
25
25
  request_options = datadog_configuration(host)
26
26
  client_config = Datadog.configuration_for(self)
27
27
 
28
- Tracing.trace(Ext::SPAN_REQUEST, on_error: method(:annotate_span_with_error!)) do |span, trace|
28
+ Tracing.trace(Ext::SPAN_REQUEST) do |span, trace|
29
29
  begin
30
30
  span.service = service_name(host, request_options, client_config)
31
31
  span.type = Tracing::Metadata::Ext::HTTP::TYPE_OUTBOUND
@@ -121,10 +121,6 @@ module Datadog
121
121
  Datadog::Core::Telemetry::Logger.report(e)
122
122
  end
123
123
 
124
- def annotate_span_with_error!(span, error)
125
- span.set_error(error)
126
- end
127
-
128
124
  def datadog_configuration(host = :default)
129
125
  Datadog.configuration.tracing[:httprb, host]
130
126
  end
@@ -31,6 +31,8 @@ module Datadog
31
31
  Tracing::Distributed::Datadog.new(fetcher: Tracing::Distributed::Fetcher),
32
32
  Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_TRACE_CONTEXT =>
33
33
  Tracing::Distributed::TraceContext.new(fetcher: Tracing::Distributed::Fetcher),
34
+ Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_BAGGAGE =>
35
+ Tracing::Distributed::Baggage.new(fetcher: Tracing::Distributed::Fetcher),
34
36
  Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_NONE => Tracing::Distributed::None.new
35
37
  },
36
38
  propagation_style_inject: propagation_style_inject,
@@ -15,7 +15,7 @@ module Datadog
15
15
  worker.processed
16
16
  ].freeze
17
17
 
18
- def instrument(event_id, payload = EMPTY_HASH, &block)
18
+ def instrument(event_id, payload = {}, &block)
19
19
  return super unless TRACEABLE_EVENTS.include?(event_id)
20
20
 
21
21
  Datadog::Tracing.trace(Ext::SPAN_WORKER_PROCESS) do |span|
@@ -48,6 +48,14 @@ module Datadog
48
48
  o.type :string, nilable: true
49
49
  o.env Ext::ENV_PEER_SERVICE
50
50
  end
51
+
52
+ # Serializes the command to JSON format, which is the desired format for the agent and Datadog UI.
53
+ # Setting this to false is deprecated and does not have any advantages.
54
+ option :json_command do |o|
55
+ o.type :bool
56
+ o.env Ext::ENV_JSON_COMMAND
57
+ o.default false
58
+ end
51
59
  end
52
60
  end
53
61
  end
@@ -13,6 +13,7 @@ module Datadog
13
13
  # @!visibility private
14
14
  ENV_ANALYTICS_ENABLED = 'DD_TRACE_MONGO_ANALYTICS_ENABLED'
15
15
  ENV_ANALYTICS_SAMPLE_RATE = 'DD_TRACE_MONGO_ANALYTICS_SAMPLE_RATE'
16
+ ENV_JSON_COMMAND = 'DD_TRACE_MONGO_JSON_COMMAND'
16
17
  DEFAULT_PEER_SERVICE_NAME = 'mongodb'
17
18
  SPAN_COMMAND = 'mongo.cmd'
18
19
  SPAN_TYPE_COMMAND = 'mongodb'
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'json'
4
+
3
5
  require_relative '../analytics'
4
6
  require_relative 'ext'
5
7
  require_relative '../ext'
@@ -30,7 +32,7 @@ module Datadog
30
32
 
31
33
  # build a quantized Query using the Parser module
32
34
  query = MongoDB.query_builder(event.command_name, event.database_name, event.command)
33
- serialized_query = query.to_s
35
+ serialized_query = serialize_query(query)
34
36
 
35
37
  if datadog_configuration[:peer_service]
36
38
  span.set_tag(
@@ -109,6 +111,21 @@ module Datadog
109
111
 
110
112
  private
111
113
 
114
+ def serialize_query(query)
115
+ if datadog_configuration[:json_command]
116
+ query.to_json
117
+ else
118
+ # Incorrect Hash#to_s serialization. The Mongo command should only be encoded as JSON.
119
+ # This code path should be removed, and is only kept to avoid a breaking change.
120
+ Datadog::Core.log_deprecation(key: :mongo_json_command) do
121
+ 'MongoDB integration: `json_command: false` causes invalid command serialization. '\
122
+ 'Use `json_command: true` or `DD_TRACE_MONGO_JSON_COMMAND=1` instead.'
123
+ end
124
+
125
+ query.to_s
126
+ end
127
+ end
128
+
112
129
  def get_span(event)
113
130
  Thread.current[:datadog_mongo_span] \
114
131
  && Thread.current[:datadog_mongo_span][event.request_id]
@@ -20,8 +20,11 @@ module Datadog
20
20
  # @public_api
21
21
  module CommonMethods
22
22
  attr_accessor \
23
- :patch_error_result,
24
- :patch_successful
23
+ :patch_error_result
24
+
25
+ def patch_successful
26
+ !!@patch_successful
27
+ end
25
28
 
26
29
  def patch_name
27
30
  self.class != Class && self.class != Module ? self.class.name : name
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Tracing
5
+ module Contrib
6
+ # Miscellaneous support methods to aid in the creation of integrations.
7
+ module Support
8
+ module_function
9
+
10
+ # Checks if a constant is loaded in a module, handling autoloaded constants correctly.
11
+ #
12
+ # This method is particularly useful when you need to check if a constant is fully loaded,
13
+ # not just defined. It handles the special case of autoloaded constants, which return
14
+ # non-nil for `defined?` even when they haven't been loaded yet.
15
+ #
16
+ # @param base_module [Module] the module to check for the constant
17
+ # @param constant [Symbol] the name of the constant to check
18
+ # @return [Boolean] true if the constant has been loaded, false otherwise
19
+ def fully_loaded?(base_module, constant)
20
+ # Autoload constants return `constant` for `defined?`, but that doesn't mean they are loaded...
21
+ base_module.const_defined?(constant) &&
22
+ # ... to check that we need to call `autoload?`. If it returns `nil`, it's loaded.
23
+ base_module.autoload?(constant).nil?
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end