datadog 2.7.1 → 2.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +69 -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 +64 -54
  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_thread_context.c +259 -132
  10. data/ext/datadog_profiling_native_extension/extconf.rb +0 -8
  11. data/ext/datadog_profiling_native_extension/heap_recorder.c +11 -89
  12. data/ext/datadog_profiling_native_extension/heap_recorder.h +1 -1
  13. data/ext/datadog_profiling_native_extension/http_transport.c +4 -4
  14. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +4 -1
  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 +54 -88
  19. data/ext/datadog_profiling_native_extension/stack_recorder.h +1 -1
  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/ext/libdatadog_extconf_helpers.rb +1 -1
  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 +1 -8
  28. data/lib/datadog/appsec/context.rb +54 -0
  29. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +73 -0
  30. data/lib/datadog/appsec/contrib/active_record/integration.rb +41 -0
  31. data/lib/datadog/appsec/contrib/active_record/patcher.rb +53 -0
  32. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +6 -6
  33. data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +4 -4
  34. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +19 -28
  35. data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +5 -5
  36. data/lib/datadog/appsec/contrib/rack/gateway/response.rb +3 -3
  37. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +64 -96
  38. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +10 -10
  39. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +5 -5
  40. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +6 -6
  41. data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +10 -11
  42. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +43 -49
  43. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +21 -32
  44. data/lib/datadog/appsec/contrib/rails/patcher.rb +1 -1
  45. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +6 -6
  46. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +41 -63
  47. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +2 -2
  48. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +5 -5
  49. data/lib/datadog/appsec/event.rb +6 -6
  50. data/lib/datadog/appsec/ext.rb +3 -1
  51. data/lib/datadog/appsec/monitor/gateway/watcher.rb +22 -32
  52. data/lib/datadog/appsec/monitor/reactive/set_user.rb +5 -5
  53. data/lib/datadog/appsec/processor/context.rb +2 -2
  54. data/lib/datadog/appsec/processor/rule_loader.rb +0 -3
  55. data/lib/datadog/appsec/remote.rb +1 -3
  56. data/lib/datadog/appsec/response.rb +7 -11
  57. data/lib/datadog/appsec.rb +6 -5
  58. data/lib/datadog/auto_instrument.rb +3 -0
  59. data/lib/datadog/core/configuration/agent_settings_resolver.rb +39 -11
  60. data/lib/datadog/core/configuration/components.rb +20 -2
  61. data/lib/datadog/core/configuration/settings.rb +10 -0
  62. data/lib/datadog/core/configuration.rb +10 -2
  63. data/lib/datadog/{tracing → core}/contrib/rails/utils.rb +1 -3
  64. data/lib/datadog/core/crashtracking/component.rb +1 -3
  65. data/lib/datadog/core/remote/client/capabilities.rb +6 -0
  66. data/lib/datadog/core/remote/client.rb +65 -59
  67. data/lib/datadog/core/telemetry/component.rb +9 -3
  68. data/lib/datadog/core/telemetry/event.rb +87 -3
  69. data/lib/datadog/core/telemetry/ext.rb +1 -0
  70. data/lib/datadog/core/telemetry/logging.rb +2 -2
  71. data/lib/datadog/core/telemetry/metric.rb +22 -0
  72. data/lib/datadog/core/telemetry/worker.rb +33 -0
  73. data/lib/datadog/di/base.rb +115 -0
  74. data/lib/datadog/di/code_tracker.rb +11 -7
  75. data/lib/datadog/di/component.rb +21 -11
  76. data/lib/datadog/di/configuration/settings.rb +11 -1
  77. data/lib/datadog/di/contrib/active_record.rb +1 -0
  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 +111 -20
  82. data/lib/datadog/di/preload.rb +18 -0
  83. data/lib/datadog/di/probe.rb +11 -1
  84. data/lib/datadog/di/probe_builder.rb +1 -0
  85. data/lib/datadog/di/probe_manager.rb +8 -5
  86. data/lib/datadog/di/probe_notification_builder.rb +27 -7
  87. data/lib/datadog/di/probe_notifier_worker.rb +5 -6
  88. data/lib/datadog/di/remote.rb +124 -0
  89. data/lib/datadog/di/serializer.rb +14 -7
  90. data/lib/datadog/di/transport.rb +3 -5
  91. data/lib/datadog/di/utils.rb +7 -0
  92. data/lib/datadog/di.rb +23 -62
  93. data/lib/datadog/kit/appsec/events.rb +3 -3
  94. data/lib/datadog/kit/identity.rb +4 -4
  95. data/lib/datadog/profiling/component.rb +59 -69
  96. data/lib/datadog/profiling/http_transport.rb +1 -26
  97. data/lib/datadog/tracing/configuration/settings.rb +4 -8
  98. data/lib/datadog/tracing/contrib/action_cable/integration.rb +5 -2
  99. data/lib/datadog/tracing/contrib/action_mailer/integration.rb +6 -2
  100. data/lib/datadog/tracing/contrib/action_pack/integration.rb +5 -2
  101. data/lib/datadog/tracing/contrib/action_view/integration.rb +5 -2
  102. data/lib/datadog/tracing/contrib/active_job/integration.rb +5 -2
  103. data/lib/datadog/tracing/contrib/active_record/integration.rb +6 -2
  104. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +3 -1
  105. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +3 -1
  106. data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +16 -4
  107. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +10 -0
  108. data/lib/datadog/tracing/contrib/active_support/integration.rb +5 -2
  109. data/lib/datadog/tracing/contrib/auto_instrument.rb +2 -2
  110. data/lib/datadog/tracing/contrib/aws/integration.rb +3 -0
  111. data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +3 -0
  112. data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +4 -0
  113. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
  114. data/lib/datadog/tracing/contrib/httprb/integration.rb +3 -0
  115. data/lib/datadog/tracing/contrib/kafka/integration.rb +3 -0
  116. data/lib/datadog/tracing/contrib/mongodb/integration.rb +3 -0
  117. data/lib/datadog/tracing/contrib/opensearch/integration.rb +3 -0
  118. data/lib/datadog/tracing/contrib/presto/integration.rb +3 -0
  119. data/lib/datadog/tracing/contrib/rack/integration.rb +2 -2
  120. data/lib/datadog/tracing/contrib/rails/framework.rb +2 -2
  121. data/lib/datadog/tracing/contrib/rails/patcher.rb +1 -1
  122. data/lib/datadog/tracing/contrib/rest_client/integration.rb +3 -0
  123. data/lib/datadog/tracing/span.rb +12 -4
  124. data/lib/datadog/tracing/span_event.rb +123 -3
  125. data/lib/datadog/tracing/span_operation.rb +6 -0
  126. data/lib/datadog/tracing/transport/serializable_trace.rb +24 -6
  127. data/lib/datadog/version.rb +2 -2
  128. data/lib/datadog.rb +3 -0
  129. metadata +30 -17
  130. data/lib/datadog/appsec/processor/actions.rb +0 -49
  131. data/lib/datadog/appsec/reactive/operation.rb +0 -68
  132. data/lib/datadog/appsec/scope.rb +0 -58
  133. data/lib/datadog/core/crashtracking/agent_base_url.rb +0 -21
@@ -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-core'
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
@@ -49,6 +49,10 @@ module Datadog
49
49
  o.type :string, nilable: true
50
50
  o.env Ext::ENV_PEER_SERVICE
51
51
  end
52
+
53
+ option :on_error do |o|
54
+ o.type :proc, nilable: true
55
+ end
52
56
  end
53
57
  end
54
58
  end
@@ -40,6 +40,7 @@ module Datadog
40
40
  # `Client#transport` is the most convenient object both for this integration and the library
41
41
  # as users have shared access to it across all `elasticsearch` versions.
42
42
  service ||= Datadog.configuration_for(transport, :service_name) || datadog_configuration[:service_name]
43
+ on_error = Datadog.configuration_for(transport, :on_error) || datadog_configuration[:on_error]
43
44
 
44
45
  method = args[0]
45
46
  path = args[1]
@@ -49,7 +50,11 @@ module Datadog
49
50
  url = full_url.path
50
51
  response = nil
51
52
 
52
- Tracing.trace(Datadog::Tracing::Contrib::Elasticsearch::Ext::SPAN_QUERY, service: service) do |span|
53
+ Tracing.trace(
54
+ Datadog::Tracing::Contrib::Elasticsearch::Ext::SPAN_QUERY,
55
+ service: service,
56
+ on_error: on_error
57
+ ) do |span|
53
58
  begin
54
59
  connection = transport.connections.first
55
60
  host = connection.host[:host] if connection
@@ -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?
@@ -12,8 +12,11 @@ module Datadog
12
12
  attr_reader \
13
13
  :trace
14
14
 
15
- def initialize(trace)
15
+ # @param trace [Datadog::Trace] the trace to serialize
16
+ # @param native_events_supported [Boolean] whether the agent supports span events as a top-level field
17
+ def initialize(trace, native_events_supported = false)
16
18
  @trace = trace
19
+ @native_events_supported = native_events_supported
17
20
  end
18
21
 
19
22
  # MessagePack serializer interface. Making this object
@@ -26,13 +29,13 @@ module Datadog
26
29
  # @param packer [MessagePack::Packer] serialization buffer, can be +nil+ with JRuby
27
30
  def to_msgpack(packer = nil)
28
31
  # As of 1.3.3, JRuby implementation doesn't pass an existing packer
29
- trace.spans.map { |s| SerializableSpan.new(s) }.to_msgpack(packer)
32
+ trace.spans.map { |s| SerializableSpan.new(s, @native_events_supported) }.to_msgpack(packer)
30
33
  end
31
34
 
32
35
  # JSON serializer interface.
33
36
  # Used by older version of the transport.
34
37
  def to_json(*args)
35
- trace.spans.map { |s| SerializableSpan.new(s).to_hash }.to_json(*args)
38
+ trace.spans.map { |s| SerializableSpan.new(s, @native_events_supported).to_hash }.to_json(*args)
36
39
  end
37
40
  end
38
41
 
@@ -41,9 +44,12 @@ module Datadog
41
44
  attr_reader \
42
45
  :span
43
46
 
44
- def initialize(span)
47
+ # @param span [Datadog::Span] the span to serialize
48
+ # @param native_events_supported [Boolean] whether the agent supports span events as a top-level field
49
+ def initialize(span, native_events_supported)
45
50
  @span = span
46
51
  @trace_id = Tracing::Utils::TraceId.to_low_order(span.trace_id)
52
+ @native_events_supported = native_events_supported
47
53
  end
48
54
 
49
55
  # MessagePack serializer interface. Making this object
@@ -55,11 +61,14 @@ module Datadog
55
61
  #
56
62
  # @param packer [MessagePack::Packer] serialization buffer, can be +nil+ with JRuby
57
63
  # rubocop:disable Metrics/AbcSize
64
+ # rubocop:disable Metrics/MethodLength
58
65
  def to_msgpack(packer = nil)
59
66
  packer ||= MessagePack::Packer.new
60
67
 
61
68
  number_of_elements_to_write = 11
62
69
 
70
+ number_of_elements_to_write += 1 if span.events.any? && @native_events_supported
71
+
63
72
  if span.stopped?
64
73
  packer.write_map_header(number_of_elements_to_write + 2) # Set header with how many elements in the map
65
74
 
@@ -72,8 +81,16 @@ module Datadog
72
81
  packer.write_map_header(number_of_elements_to_write) # Set header with how many elements in the map
73
82
  end
74
83
 
75
- # serialize span events as meta tags
76
- span.set_tag('events', span.events.map(&:to_hash).to_json) if span.events.any?
84
+ if span.events.any?
85
+ if @native_events_supported
86
+ # Use top-level field for native events
87
+ packer.write('span_events')
88
+ packer.write(span.events.map(&:to_native_format))
89
+ else
90
+ # Serialize span events as meta tags
91
+ span.set_tag('events', span.events.map(&:to_hash).to_json)
92
+ end
93
+ end
77
94
 
78
95
  # DEV: We use strings as keys here, instead of symbols, as
79
96
  # DEV: MessagePack will ultimately convert them to strings.
@@ -103,6 +120,7 @@ module Datadog
103
120
  packer
104
121
  end
105
122
  # rubocop:enable Metrics/AbcSize
123
+ # rubocop:enable Metrics/MethodLength
106
124
 
107
125
  # JSON serializer interface.
108
126
  # Used by older version of the transport.
@@ -3,8 +3,8 @@
3
3
  module Datadog
4
4
  module VERSION
5
5
  MAJOR = 2
6
- MINOR = 7
7
- PATCH = 1
6
+ MINOR = 9
7
+ PATCH = 0
8
8
  PRE = nil
9
9
  BUILD = nil
10
10
  # PRE and BUILD above are modified for dev gems during gem build GHA workflow
data/lib/datadog.rb CHANGED
@@ -7,4 +7,7 @@ require_relative 'datadog/tracing/contrib'
7
7
  # Load other products (must follow tracing)
8
8
  require_relative 'datadog/profiling'
9
9
  require_relative 'datadog/appsec'
10
+ # Line probes will not work on Ruby < 2.6 because of lack of :script_compiled
11
+ # trace point. Only load DI on supported Ruby versions.
12
+ require_relative 'datadog/di' if RUBY_VERSION >= '2.6'
10
13
  require_relative 'datadog/kit'