datadog 2.12.2 → 2.15.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 (159) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +74 -2
  3. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +16 -14
  4. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +3 -0
  5. data/ext/datadog_profiling_native_extension/encoded_profile.c +69 -0
  6. data/ext/datadog_profiling_native_extension/encoded_profile.h +7 -0
  7. data/ext/datadog_profiling_native_extension/http_transport.c +25 -32
  8. data/ext/datadog_profiling_native_extension/profiling.c +2 -0
  9. data/ext/datadog_profiling_native_extension/stack_recorder.c +22 -21
  10. data/ext/libdatadog_api/datadog_ruby_common.h +3 -0
  11. data/lib/datadog/appsec/actions_handler/serializable_backtrace.rb +89 -0
  12. data/lib/datadog/appsec/actions_handler.rb +22 -1
  13. data/lib/datadog/appsec/anonymizer.rb +16 -0
  14. data/lib/datadog/appsec/assets/waf_rules/README.md +50 -5
  15. data/lib/datadog/appsec/assets/waf_rules/processors.json +239 -10
  16. data/lib/datadog/appsec/assets/waf_rules/recommended.json +0 -1344
  17. data/lib/datadog/appsec/assets/waf_rules/scanners.json +926 -17
  18. data/lib/datadog/appsec/assets/waf_rules/strict.json +0 -1344
  19. data/lib/datadog/appsec/component.rb +19 -17
  20. data/lib/datadog/appsec/compressed_json.rb +40 -0
  21. data/lib/datadog/appsec/configuration/settings.rb +62 -10
  22. data/lib/datadog/appsec/contrib/active_record/integration.rb +1 -1
  23. data/lib/datadog/appsec/contrib/auto_instrument.rb +1 -1
  24. data/lib/datadog/appsec/contrib/devise/configuration.rb +7 -31
  25. data/lib/datadog/appsec/contrib/devise/data_extractor.rb +79 -0
  26. data/lib/datadog/appsec/contrib/devise/ext.rb +21 -0
  27. data/lib/datadog/appsec/contrib/devise/integration.rb +0 -1
  28. data/lib/datadog/appsec/contrib/devise/patcher.rb +36 -23
  29. data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +102 -0
  30. data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +69 -0
  31. data/lib/datadog/appsec/contrib/devise/{patcher/rememberable_patch.rb → patches/skip_signin_tracking_patch.rb} +2 -2
  32. data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +93 -0
  33. data/lib/datadog/appsec/contrib/rack/ext.rb +14 -0
  34. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +10 -3
  35. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +0 -2
  36. data/lib/datadog/appsec/event.rb +22 -51
  37. data/lib/datadog/appsec/ext.rb +4 -2
  38. data/lib/datadog/appsec/instrumentation/gateway/argument.rb +4 -2
  39. data/lib/datadog/appsec/monitor/gateway/watcher.rb +8 -3
  40. data/lib/datadog/appsec/remote.rb +4 -0
  41. data/lib/datadog/appsec/security_engine/runner.rb +2 -2
  42. data/lib/datadog/appsec/utils.rb +0 -2
  43. data/lib/datadog/core/configuration/components.rb +2 -1
  44. data/lib/datadog/core/configuration/ext.rb +4 -0
  45. data/lib/datadog/core/configuration/options.rb +2 -2
  46. data/lib/datadog/core/configuration/settings.rb +53 -30
  47. data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
  48. data/lib/datadog/core/environment/agent_info.rb +4 -3
  49. data/lib/datadog/core/metrics/client.rb +1 -1
  50. data/lib/datadog/core/remote/client.rb +1 -1
  51. data/lib/datadog/core/remote/component.rb +3 -6
  52. data/lib/datadog/core/remote/configuration/repository.rb +2 -1
  53. data/lib/datadog/core/remote/negotiation.rb +9 -9
  54. data/lib/datadog/core/remote/transport/config.rb +4 -3
  55. data/lib/datadog/core/remote/transport/http/client.rb +4 -3
  56. data/lib/datadog/core/remote/transport/http/config.rb +6 -32
  57. data/lib/datadog/core/remote/transport/http/negotiation.rb +6 -32
  58. data/lib/datadog/core/remote/transport/http.rb +22 -57
  59. data/lib/datadog/core/remote/transport/negotiation.rb +4 -3
  60. data/lib/datadog/core/runtime/metrics.rb +8 -1
  61. data/lib/datadog/core/telemetry/http/adapters/net.rb +1 -1
  62. data/lib/datadog/core/telemetry/metric.rb +5 -5
  63. data/lib/datadog/core/telemetry/request.rb +1 -1
  64. data/lib/datadog/core/transport/http/api/instance.rb +17 -0
  65. data/lib/datadog/core/transport/http/api/spec.rb +17 -0
  66. data/lib/datadog/core/transport/http/builder.rb +5 -3
  67. data/lib/datadog/core/transport/http.rb +39 -2
  68. data/lib/datadog/di/component.rb +0 -2
  69. data/lib/datadog/di/probe_notification_builder.rb +1 -1
  70. data/lib/datadog/di/probe_notifier_worker.rb +16 -16
  71. data/lib/datadog/di/transport/diagnostics.rb +4 -3
  72. data/lib/datadog/di/transport/http/api.rb +2 -12
  73. data/lib/datadog/di/transport/http/client.rb +4 -3
  74. data/lib/datadog/di/transport/http/diagnostics.rb +7 -34
  75. data/lib/datadog/di/transport/http/input.rb +7 -34
  76. data/lib/datadog/di/transport/http.rb +14 -62
  77. data/lib/datadog/di/transport/input.rb +4 -3
  78. data/lib/datadog/di/utils.rb +5 -0
  79. data/lib/datadog/kit/appsec/events.rb +12 -0
  80. data/lib/datadog/kit/identity.rb +5 -1
  81. data/lib/datadog/opentelemetry/api/baggage.rb +90 -0
  82. data/lib/datadog/opentelemetry/api/baggage.rbs +26 -0
  83. data/lib/datadog/opentelemetry/api/context.rb +16 -2
  84. data/lib/datadog/opentelemetry/sdk/trace/span.rb +1 -1
  85. data/lib/datadog/opentelemetry.rb +2 -1
  86. data/lib/datadog/profiling/collectors/info.rb +3 -0
  87. data/lib/datadog/profiling/collectors/thread_context.rb +1 -1
  88. data/lib/datadog/profiling/encoded_profile.rb +11 -0
  89. data/lib/datadog/profiling/exporter.rb +2 -3
  90. data/lib/datadog/profiling/ext.rb +0 -1
  91. data/lib/datadog/profiling/flush.rb +4 -7
  92. data/lib/datadog/profiling/http_transport.rb +10 -59
  93. data/lib/datadog/profiling/stack_recorder.rb +4 -4
  94. data/lib/datadog/profiling.rb +6 -2
  95. data/lib/datadog/tracing/component.rb +15 -12
  96. data/lib/datadog/tracing/configuration/ext.rb +7 -1
  97. data/lib/datadog/tracing/configuration/settings.rb +18 -2
  98. data/lib/datadog/tracing/context_provider.rb +1 -1
  99. data/lib/datadog/tracing/contrib/active_record/integration.rb +1 -1
  100. data/lib/datadog/tracing/contrib/configuration/settings.rb +1 -1
  101. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -5
  102. data/lib/datadog/tracing/contrib/excon/middleware.rb +5 -3
  103. data/lib/datadog/tracing/contrib/ext.rb +1 -0
  104. data/lib/datadog/tracing/contrib/faraday/middleware.rb +5 -3
  105. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +7 -1
  106. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +3 -0
  107. data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +0 -15
  108. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +4 -1
  109. data/lib/datadog/tracing/contrib/http/instrumentation.rb +5 -5
  110. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +5 -11
  111. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +6 -10
  112. data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +27 -0
  113. data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +46 -0
  114. data/lib/datadog/tracing/contrib/karafka/ext.rb +27 -0
  115. data/lib/datadog/tracing/contrib/karafka/integration.rb +45 -0
  116. data/lib/datadog/tracing/contrib/karafka/monitor.rb +66 -0
  117. data/lib/datadog/tracing/contrib/karafka/patcher.rb +71 -0
  118. data/lib/datadog/tracing/contrib/karafka.rb +37 -0
  119. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +17 -0
  120. data/lib/datadog/tracing/contrib/opensearch/ext.rb +9 -0
  121. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +5 -1
  122. data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
  123. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +5 -3
  124. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +6 -1
  125. data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +3 -0
  126. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +1 -1
  127. data/lib/datadog/tracing/contrib.rb +1 -0
  128. data/lib/datadog/tracing/correlation.rb +9 -2
  129. data/lib/datadog/tracing/distributed/baggage.rb +131 -0
  130. data/lib/datadog/tracing/distributed/datadog.rb +2 -0
  131. data/lib/datadog/tracing/distributed/propagation.rb +25 -4
  132. data/lib/datadog/tracing/distributed/propagation_policy.rb +42 -0
  133. data/lib/datadog/tracing/metadata/ext.rb +5 -0
  134. data/lib/datadog/tracing/sampling/span/rule.rb +0 -1
  135. data/lib/datadog/tracing/span_event.rb +1 -1
  136. data/lib/datadog/tracing/span_operation.rb +2 -1
  137. data/lib/datadog/tracing/sync_writer.rb +1 -2
  138. data/lib/datadog/tracing/trace_digest.rb +9 -2
  139. data/lib/datadog/tracing/trace_operation.rb +29 -17
  140. data/lib/datadog/tracing/trace_segment.rb +6 -4
  141. data/lib/datadog/tracing/tracer.rb +38 -2
  142. data/lib/datadog/tracing/transport/http/api.rb +2 -10
  143. data/lib/datadog/tracing/transport/http/client.rb +5 -4
  144. data/lib/datadog/tracing/transport/http/traces.rb +13 -41
  145. data/lib/datadog/tracing/transport/http.rb +11 -44
  146. data/lib/datadog/tracing/transport/trace_formatter.rb +7 -0
  147. data/lib/datadog/tracing/transport/traces.rb +26 -9
  148. data/lib/datadog/tracing/workers/trace_writer.rb +2 -6
  149. data/lib/datadog/tracing/writer.rb +2 -6
  150. data/lib/datadog/tracing.rb +16 -3
  151. data/lib/datadog/version.rb +2 -2
  152. data/lib/datadog.rb +1 -1
  153. metadata +28 -13
  154. data/lib/datadog/appsec/contrib/devise/event.rb +0 -54
  155. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +0 -72
  156. data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +0 -47
  157. data/lib/datadog/appsec/contrib/devise/resource.rb +0 -35
  158. data/lib/datadog/appsec/contrib/devise/tracking.rb +0 -57
  159. data/lib/datadog/appsec/utils/trace_operation.rb +0 -15
@@ -21,13 +21,13 @@ module Datadog
21
21
 
22
22
  def defaults
23
23
  Datadog::Core::Transport::HTTP::API::Map[
24
- DIAGNOSTICS => Spec.new do |s|
24
+ DIAGNOSTICS => Diagnostics::API::Spec.new do |s|
25
25
  s.diagnostics = Diagnostics::API::Endpoint.new(
26
26
  '/debugger/v1/diagnostics',
27
27
  Core::Encoding::JSONEncoder,
28
28
  )
29
29
  end,
30
- INPUT => Spec.new do |s|
30
+ INPUT => Input::API::Spec.new do |s|
31
31
  s.input = Input::API::Endpoint.new(
32
32
  '/debugger/v1/input',
33
33
  Core::Encoding::JSONEncoder,
@@ -35,16 +35,6 @@ module Datadog
35
35
  end,
36
36
  ]
37
37
  end
38
-
39
- class Instance < Core::Transport::HTTP::API::Instance
40
- include Diagnostics::API::Instance
41
- include Input::API::Instance
42
- end
43
-
44
- class Spec < Core::Transport::HTTP::API::Spec
45
- include Diagnostics::API::Spec
46
- include Input::API::Spec
47
- end
48
38
  end
49
39
  end
50
40
  end
@@ -14,10 +14,11 @@ module Datadog
14
14
  module HTTP
15
15
  # Routes, encodes, and sends DI data to the trace agent via HTTP.
16
16
  class Client
17
- attr_reader :api
17
+ attr_reader :api, :logger
18
18
 
19
- def initialize(api)
19
+ def initialize(api, logger:)
20
20
  @api = api
21
+ @logger = logger
21
22
  end
22
23
 
23
24
  def send_request(request, &block)
@@ -31,7 +32,7 @@ module Datadog
31
32
  "Internal error during #{self.class.name} request. Cause: #{e.class.name} #{e.message} " \
32
33
  "Location: #{Array(e.backtrace).first}"
33
34
 
34
- Datadog.logger.debug(message)
35
+ logger.debug(message)
35
36
 
36
37
  Datadog::Core::Transport::InternalErrorResponse.new(e)
37
38
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../../../core/transport/http/api/instance'
4
+ require_relative '../../../core/transport/http/api/spec'
3
5
  require_relative 'client'
4
6
 
5
7
  module Datadog
@@ -16,55 +18,26 @@ module Datadog
16
18
  end
17
19
 
18
20
  module API
19
- module Instance
21
+ class Instance < Core::Transport::HTTP::API::Instance
20
22
  def send_diagnostics(env)
21
- raise DiagnosticsNotSupportedError, spec unless spec.is_a?(Diagnostics::API::Spec)
23
+ raise Core::Transport::HTTP::API::Instance::EndpointNotSupportedError.new('diagnostics', self) unless spec.is_a?(Diagnostics::API::Spec)
22
24
 
23
25
  spec.send_diagnostics(env) do |request_env|
24
26
  call(request_env)
25
27
  end
26
28
  end
27
-
28
- class DiagnosticsNotSupportedError < StandardError
29
- attr_reader :spec
30
-
31
- def initialize(spec)
32
- super
33
-
34
- @spec = spec
35
- end
36
-
37
- def message
38
- 'Diagnostics not supported for this API!'
39
- end
40
- end
41
29
  end
42
30
 
43
- module Spec
31
+ class Spec < Core::Transport::HTTP::API::Spec
44
32
  attr_accessor :diagnostics
45
33
 
46
34
  def send_diagnostics(env, &block)
47
- raise NoDiagnosticsEndpointDefinedError, self if diagnostics.nil?
35
+ raise Core::Transport::HTTP::API::Spec::EndpointNotDefinedError.new('diagnostics', self) if diagnostics.nil?
48
36
 
49
37
  diagnostics.call(env, &block)
50
38
  end
51
-
52
- class NoDiagnosticsEndpointDefinedError < StandardError
53
- attr_reader :spec
54
-
55
- def initialize(spec)
56
- super
57
-
58
- @spec = spec
59
- end
60
-
61
- def message
62
- 'No diagnostics endpoint is defined for API specification!'
63
- end
64
- end
65
39
  end
66
40
 
67
- # Endpoint for negotiation
68
41
  class Endpoint < Datadog::Core::Transport::HTTP::API::Endpoint
69
42
  attr_reader :encoder
70
43
 
@@ -79,7 +52,7 @@ module Datadog
79
52
  )
80
53
  env.form = {'event' => event_payload}
81
54
 
82
- super(env, &block)
55
+ super
83
56
  end
84
57
  end
85
58
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../../../core/transport/http/api/instance'
4
+ require_relative '../../../core/transport/http/api/spec'
3
5
  require_relative 'client'
4
6
 
5
7
  module Datadog
@@ -16,55 +18,26 @@ module Datadog
16
18
  end
17
19
 
18
20
  module API
19
- module Instance
21
+ class Instance < Core::Transport::HTTP::API::Instance
20
22
  def send_input(env)
21
- raise InputNotSupportedError, spec unless spec.is_a?(Input::API::Spec)
23
+ raise Core::Transport::HTTP::API::Instance::EndpointNotSupportedError.new('input', self) unless spec.is_a?(Input::API::Spec)
22
24
 
23
25
  spec.send_input(env) do |request_env|
24
26
  call(request_env)
25
27
  end
26
28
  end
27
-
28
- class InputNotSupportedError < StandardError
29
- attr_reader :spec
30
-
31
- def initialize(spec)
32
- super
33
-
34
- @spec = spec
35
- end
36
-
37
- def message
38
- 'Input not supported for this API!'
39
- end
40
- end
41
29
  end
42
30
 
43
- module Spec
31
+ class Spec < Core::Transport::HTTP::API::Spec
44
32
  attr_accessor :input
45
33
 
46
34
  def send_input(env, &block)
47
- raise NoInputEndpointDefinedError, self if input.nil?
35
+ raise Core::Transport::HTTP::API::Spec::EndpointNotDefinedError.new('input', self) if input.nil?
48
36
 
49
37
  input.call(env, &block)
50
38
  end
51
-
52
- class NoInputEndpointDefinedError < StandardError
53
- attr_reader :spec
54
-
55
- def initialize(spec)
56
- super
57
-
58
- @spec = spec
59
- end
60
-
61
- def message
62
- 'No input endpoint is defined for API specification!'
63
- end
64
- end
65
39
  end
66
40
 
67
- # Endpoint for negotiation
68
41
  class Endpoint < Datadog::Core::Transport::HTTP::API::Endpoint
69
42
  HEADER_CONTENT_TYPE = 'Content-Type'
70
43
 
@@ -81,7 +54,7 @@ module Datadog
81
54
  env.headers[HEADER_CONTENT_TYPE] = encoder.content_type
82
55
  env.body = env.request.parcel.data
83
56
 
84
- super(env, &block)
57
+ super
85
58
  end
86
59
  end
87
60
  end
@@ -1,15 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'uri'
4
-
5
- require_relative '../../core/environment/container'
6
- require_relative '../../core/environment/ext'
7
- require_relative '../../core/transport/ext'
8
3
  require_relative 'diagnostics'
9
4
  require_relative 'input'
10
5
  require_relative 'http/api'
11
6
  require_relative '../../core/transport/http'
12
- require_relative '../../../datadog/version'
13
7
 
14
8
  module Datadog
15
9
  module DI
@@ -18,86 +12,44 @@ module Datadog
18
12
  module HTTP
19
13
  module_function
20
14
 
21
- # Builds a new Transport::HTTP::Client
22
- def new(klass, &block)
23
- Core::Transport::HTTP.build(
24
- api_instance_class: API::Instance, &block
25
- ).to_transport(klass)
26
- end
27
-
28
15
  # Builds a new Transport::HTTP::Client with default settings
29
16
  # Pass a block to override any settings.
30
17
  def diagnostics(
31
18
  agent_settings:,
32
- **options
19
+ logger:,
20
+ api_version: nil,
21
+ headers: nil
33
22
  )
34
- new(DI::Transport::Diagnostics::Transport) do |transport|
35
- transport.adapter(agent_settings)
36
- transport.headers default_headers
37
-
23
+ Core::Transport::HTTP.build(api_instance_class: Diagnostics::API::Instance,
24
+ logger: logger,
25
+ agent_settings: agent_settings, api_version: api_version, headers: headers) do |transport|
38
26
  apis = API.defaults
39
27
 
40
28
  transport.api API::DIAGNOSTICS, apis[API::DIAGNOSTICS]
41
29
 
42
- # Apply any settings given by options
43
- unless options.empty?
44
- transport.default_api = options[:api_version] if options.key?(:api_version)
45
- transport.headers options[:headers] if options.key?(:headers)
46
- end
47
-
48
30
  # Call block to apply any customization, if provided
49
31
  yield(transport) if block_given?
50
- end
32
+ end.to_transport(DI::Transport::Diagnostics::Transport)
51
33
  end
52
34
 
53
35
  # Builds a new Transport::HTTP::Client with default settings
54
36
  # Pass a block to override any settings.
55
37
  def input(
56
38
  agent_settings:,
57
- **options
39
+ logger:,
40
+ api_version: nil,
41
+ headers: nil
58
42
  )
59
- new(DI::Transport::Input::Transport) do |transport|
60
- transport.adapter(agent_settings)
61
- transport.headers default_headers
62
-
43
+ Core::Transport::HTTP.build(api_instance_class: Input::API::Instance,
44
+ logger: logger,
45
+ agent_settings: agent_settings, api_version: api_version, headers: headers) do |transport|
63
46
  apis = API.defaults
64
47
 
65
48
  transport.api API::INPUT, apis[API::INPUT]
66
49
 
67
- # Apply any settings given by options
68
- unless options.empty?
69
- transport.default_api = options[:api_version] if options.key?(:api_version)
70
- transport.headers options[:headers] if options.key?(:headers)
71
- end
72
-
73
50
  # Call block to apply any customization, if provided
74
51
  yield(transport) if block_given?
75
- end
76
- end
77
-
78
- def default_headers
79
- {
80
- Datadog::Core::Transport::Ext::HTTP::HEADER_CLIENT_COMPUTED_TOP_LEVEL => '1',
81
- Datadog::Core::Transport::Ext::HTTP::HEADER_META_LANG => Datadog::Core::Environment::Ext::LANG,
82
- Datadog::Core::Transport::Ext::HTTP::HEADER_META_LANG_VERSION => Datadog::Core::Environment::Ext::LANG_VERSION,
83
- Datadog::Core::Transport::Ext::HTTP::HEADER_META_LANG_INTERPRETER =>
84
- Datadog::Core::Environment::Ext::LANG_INTERPRETER,
85
- Datadog::Core::Transport::Ext::HTTP::HEADER_META_LANG_INTERPRETER_VENDOR => Core::Environment::Ext::LANG_ENGINE,
86
- Datadog::Core::Transport::Ext::HTTP::HEADER_META_TRACER_VERSION =>
87
- Datadog::Core::Environment::Ext::GEM_DATADOG_VERSION
88
- }.tap do |headers|
89
- # Add container ID, if present.
90
- container_id = Datadog::Core::Environment::Container.container_id
91
- headers[Datadog::Core::Transport::Ext::HTTP::HEADER_CONTAINER_ID] = container_id unless container_id.nil?
92
- # Pretend that stats computation are already done by the client
93
- if Datadog.configuration.appsec.standalone.enabled
94
- headers[Datadog::Core::Transport::Ext::HTTP::HEADER_CLIENT_COMPUTED_STATS] = 'yes'
95
- end
96
- end
97
- end
98
-
99
- def default_adapter
100
- Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
52
+ end.to_transport(DI::Transport::Input::Transport)
101
53
  end
102
54
  end
103
55
  end
@@ -15,12 +15,13 @@ module Datadog
15
15
  end
16
16
 
17
17
  class Transport
18
- attr_reader :client, :apis, :default_api, :current_api_id
18
+ attr_reader :client, :apis, :default_api, :current_api_id, :logger
19
19
 
20
- def initialize(apis, default_api)
20
+ def initialize(apis, default_api, logger:)
21
21
  @apis = apis
22
+ @logger = logger
22
23
 
23
- @client = HTTP::Client.new(current_api)
24
+ @client = HTTP::Client.new(current_api, logger: logger)
24
25
  end
25
26
 
26
27
  def current_api
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # standard gets itself into an infinite loop over this
4
+ # rubocop:disable Layout/SpaceAfterNot
5
+
3
6
  module Datadog
4
7
  module DI
5
8
  module Utils
@@ -135,3 +138,5 @@ module Datadog
135
138
  end
136
139
  end
137
140
  end
141
+
142
+ # rubocop:enable Layout/SpaceAfterNot
@@ -10,6 +10,7 @@ module Datadog
10
10
  LOGIN_SUCCESS_EVENT = 'users.login.success'
11
11
  LOGIN_FAILURE_EVENT = 'users.login.failure'
12
12
  SIGNUP_EVENT = 'users.signup'
13
+ USER_LOGIN_KEYS = ['usr.login', :'usr.login'].freeze
13
14
 
14
15
  class << self
15
16
  # Attach login success event information to the trace
@@ -30,11 +31,15 @@ module Datadog
30
31
  set_trace_and_span_context('track_login_success', trace, span) do |active_trace, active_span|
31
32
  user_options = user.dup
32
33
  user_id = user_options.delete(:id)
34
+ user_login = user_options[:login] || others[:'usr.login'] || others['usr.login'] || user_id
33
35
 
34
36
  raise ArgumentError, 'missing required key: :user => { :id }' if user_id.nil?
35
37
 
38
+ others = others.reject { |key, _| USER_LOGIN_KEYS.include?(key) }
39
+ others[:'usr.login'] = user_login
36
40
  track(LOGIN_SUCCESS_EVENT, active_trace, active_span, **others)
37
41
 
42
+ user_options[:login] = user_login
38
43
  Kit::Identity.set_user(active_trace, active_span, id: user_id, **user_options)
39
44
  end
40
45
  end
@@ -55,6 +60,7 @@ module Datadog
55
60
  # event information to attach to the trace.
56
61
  def track_login_failure(trace = nil, span = nil, user_exists:, user_id: nil, **others)
57
62
  set_trace_and_span_context('track_login_failure', trace, span) do |active_trace, active_span|
63
+ others[:'usr.login'] = user_id if user_id && !others.key?(:'usr.login') && !others.key?('usr.login')
58
64
  track(LOGIN_FAILURE_EVENT, active_trace, active_span, **others)
59
65
 
60
66
  active_span.set_tag('appsec.events.users.login.failure.usr.id', user_id) if user_id
@@ -80,11 +86,15 @@ module Datadog
80
86
  set_trace_and_span_context('track_signup', trace, span) do |active_trace, active_span|
81
87
  user_options = user.dup
82
88
  user_id = user_options.delete(:id)
89
+ user_login = user_options[:login] || others[:'usr.login'] || others['usr.login'] || user_id
83
90
 
84
91
  raise ArgumentError, 'missing required key: :user => { :id }' if user_id.nil?
85
92
 
93
+ others = others.reject { |key, _| USER_LOGIN_KEYS.include?(key) }
94
+ others[:'usr.login'] = user_login
86
95
  track(SIGNUP_EVENT, active_trace, active_span, **others)
87
96
 
97
+ user_options[:login] = user_login
88
98
  Kit::Identity.set_user(trace, id: user_id, **user_options)
89
99
  end
90
100
  end
@@ -131,6 +141,8 @@ module Datadog
131
141
  active_trace.keep!
132
142
  end
133
143
  end
144
+
145
+ ::Datadog::AppSec::Instrumentation.gateway.push('appsec.events.user_lifecycle', event)
134
146
  end
135
147
 
136
148
  private
@@ -33,6 +33,7 @@ module Datadog
33
33
  # @param others [Hash<Symbol, String>] Additional free-form
34
34
  # user information to attach to the trace.
35
35
  #
36
+ # rubocop:disable Metrics/AbcSize
36
37
  # rubocop:disable Metrics/CyclomaticComplexity
37
38
  # rubocop:disable Metrics/PerceivedComplexity
38
39
  def set_user(
@@ -67,11 +68,14 @@ module Datadog
67
68
  end
68
69
 
69
70
  if Datadog::AppSec.active_context
70
- user = ::Datadog::AppSec::Instrumentation::Gateway::User.new(id)
71
+ active_span.set_tag('_dd.appsec.user.collection_mode', 'sdk')
72
+
73
+ user = ::Datadog::AppSec::Instrumentation::Gateway::User.new(id, others[:login])
71
74
  ::Datadog::AppSec::Instrumentation.gateway.push('identity.set_user', user)
72
75
  end
73
76
  end
74
77
  end
78
+ # rubocop:enable Metrics/AbcSize
75
79
  # rubocop:enable Metrics/PerceivedComplexity
76
80
  # rubocop:enable Metrics/CyclomaticComplexity
77
81
 
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'trace/span'
4
+ require_relative '../../tracing/trace_operation'
5
+ require_relative '../trace'
6
+
7
+ module Datadog
8
+ module OpenTelemetry
9
+ module API
10
+ # The Baggage module provides an implementation of the OpenTelemetry Baggage API.
11
+ #
12
+ # Baggage is a set of name/value pairs describing user-defined properties that can be
13
+ # propagated through a distributed trace. This implementation follows the W3C Baggage
14
+ # specification and the OpenTelemetry Baggage API.
15
+ #
16
+ # @see https://www.w3.org/TR/baggage/
17
+ # @see https://opentelemetry.io/docs/specs/otel/baggage/api/
18
+ module Baggage
19
+ def initialize(trace: nil)
20
+ @trace = trace
21
+ end
22
+
23
+ # Returns a new context with empty baggage
24
+ #
25
+ # @param [optional Context] context Context to clear baggage from. Defaults
26
+ # to ::OpenTelemetry::Context.current
27
+ # @return [Context]
28
+ def clear(context: ::OpenTelemetry::Context.current)
29
+ context.ensure_trace.baggage.clear
30
+ context
31
+ end
32
+
33
+ # Returns the corresponding value for key
34
+ #
35
+ # @param [String] key The lookup key
36
+ # @param [optional Context] context The context from which to retrieve
37
+ # the key. Defaults to ::OpenTelemetry::Context.current
38
+ # @return [String, nil]
39
+ def value(key, context: ::OpenTelemetry::Context.current)
40
+ trace = context.ensure_trace
41
+ return nil if trace.nil?
42
+
43
+ trace.baggage && trace.baggage[key]
44
+ end
45
+
46
+ # Returns all baggage values
47
+ #
48
+ # @param [optional Context] context The context from which to retrieve
49
+ # the baggage. Defaults to ::OpenTelemetry::Context.current
50
+ # @return [Hash<String, String>]
51
+ def values(context: ::OpenTelemetry::Context.current)
52
+ trace = context.ensure_trace
53
+ return {} if trace.nil?
54
+
55
+ trace.baggage ? trace.baggage.dup : {}
56
+ end
57
+
58
+ # Returns a new context with new key-value pair
59
+ #
60
+ # @param [String] key The key to store this value under
61
+ # @param [String] value String value to be stored under key
62
+ # @param [optional String] metadata This is here to store properties
63
+ # received from other W3C Baggage implementations but is not exposed in
64
+ # OpenTelemetry. This is considered private API and not for use by
65
+ # end-users.
66
+ # @param [optional Context] context The context to update with new
67
+ # value. Defaults to ::OpenTelemetry::Context.current
68
+ # @return [Context]
69
+ def set_value(key, value, metadata: nil, context: ::OpenTelemetry::Context.current)
70
+ # Delegate to the context to set the value because an active trace is not guaranteed
71
+ # set_values handles this logic
72
+ context.set_values({ ::OpenTelemetry::Baggage.const_get(:BAGGAGE_KEY) => { key => value } })
73
+ end
74
+
75
+ # Returns a new context with value at key removed
76
+ #
77
+ # @param [String] key The key to remove
78
+ # @param [optional Context] context The context to remove baggage
79
+ # from. Defaults to ::OpenTelemetry::Context.current
80
+ # @return [Context]
81
+ def remove_value(key, context: ::OpenTelemetry::Context.current)
82
+ # Delegate to the context to remove the value because an active trace is not guaranteed
83
+ # set_values handles this logic
84
+ context.set_values({ Context::BAGGAGE_REMOVE_KEY => key })
85
+ end
86
+ ::OpenTelemetry::Baggage.singleton_class.prepend(self)
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module OpenTelemetry
5
+ module API
6
+ module Baggage
7
+ def initialize: (?trace: Datadog::Tracing::TraceOperation?) -> void
8
+
9
+ # Returns a new context with empty baggage
10
+ def clear: (?context: OpenTelemetry::Context) -> OpenTelemetry::Context
11
+
12
+ # Returns the corresponding value for key
13
+ def value: (String key, ?context: OpenTelemetry::Context) -> String?
14
+
15
+ # Returns all baggage values
16
+ def values: (?context: OpenTelemetry::Context) -> Hash[String, String]
17
+
18
+ # Returns a new context with key-value pair
19
+ def set_value: (String key, String value, ?metadata: String?, ?context: OpenTelemetry::Context) -> OpenTelemetry::Context
20
+
21
+ # Returns a new context with value at key removed
22
+ def remove_value: (String key, ?context: OpenTelemetry::Context) -> OpenTelemetry::Context
23
+ end
24
+ end
25
+ end
26
+ end
@@ -21,11 +21,13 @@ module Datadog
21
21
  module Context
22
22
  CURRENT_SPAN_KEY = ::OpenTelemetry::Trace.const_get(:CURRENT_SPAN_KEY)
23
23
  private_constant :CURRENT_SPAN_KEY
24
+ BAGGAGE_REMOVE_KEY = Object.new # sentinel object to indicate the deletion of a value in baggage
24
25
 
25
- def initialize(entries, trace: nil)
26
+ def initialize(entries, trace: nil, baggage: nil)
26
27
  @trace = trace || ::Datadog::Tracing.send(:tracer).send(:start_trace)
27
28
  @trace.otel_values.merge!(entries) if entries
28
29
  @trace.otel_context ||= self
30
+ @trace.baggage = baggage if baggage
29
31
  end
30
32
 
31
33
  # Because Context can be reused, we have to make sure we have
@@ -79,8 +81,20 @@ module Datadog
79
81
  end
80
82
 
81
83
  existing_values = @trace && @trace.otel_values || {}
84
+ existing_baggage = @trace && @trace.baggage || {}
82
85
 
83
- ::OpenTelemetry::Context.new(existing_values.merge(values), trace: trace)
86
+ # Retrieve the baggage removal sentinel and remove it from the values hash
87
+ existing_baggage.delete(values[BAGGAGE_REMOVE_KEY]) if values.key?(BAGGAGE_REMOVE_KEY)
88
+
89
+ # If the values hash contains a BAGGAGE_KEY, merge its contents with existing baggage
90
+ # Otherwise, keep the existing baggage unchanged
91
+ new_baggage = if values.key?(::OpenTelemetry::Baggage.const_get(:BAGGAGE_KEY))
92
+ existing_baggage.merge(values[::OpenTelemetry::Baggage.const_get(:BAGGAGE_KEY)])
93
+ else
94
+ existing_baggage
95
+ end
96
+
97
+ ::OpenTelemetry::Context.new(existing_values.merge(values), trace: trace, baggage: new_baggage)
84
98
  end
85
99
 
86
100
  # The Datadog {TraceOperation} associated with this {Context}.
@@ -45,7 +45,7 @@ module Datadog
45
45
  def add_attributes(attributes)
46
46
  res = super
47
47
  # Attributes can get dropped or their values truncated by `super`
48
- attributes.each { |key, _| datadog_set_attribute(key) }
48
+ attributes.each_key { |key| datadog_set_attribute(key) }
49
49
  res
50
50
  end
51
51
 
@@ -13,6 +13,7 @@ require_relative 'tracing'
13
13
  require_relative 'tracing/contrib'
14
14
 
15
15
  require_relative 'opentelemetry/api/context'
16
+ require_relative 'opentelemetry/api/baggage'
16
17
 
17
18
  # DEV: Should this be a Contrib integration, that depends on the `opentelemetry-sdk`
18
19
  # DEV: and checks for compatibility?
@@ -29,7 +30,7 @@ module Datadog
29
30
 
30
31
  # Use `Datadog.logger` as the default logger
31
32
  def logger
32
- @logger ||= ::Datadog.logger
33
+ ::Datadog.logger
33
34
  end
34
35
 
35
36
  ::OpenTelemetry.singleton_class.prepend(self)
@@ -31,6 +31,9 @@ module Datadog
31
31
  # Instead of trying to figure out real process start time by checking
32
32
  # /proc or some other complex/non-portable way, approximate start time
33
33
  # by time of requirement of this file.
34
+ #
35
+ # Note: this does not use Core::Utils::Time.now because this constant
36
+ # gets initialized before a user has a chance to configure the library.
34
37
  START_TIME = Time.now.utc.freeze
35
38
 
36
39
  def collect_platform_info
@@ -60,7 +60,7 @@ module Datadog
60
60
 
61
61
  def inspect
62
62
  # Compose Ruby's default inspect with our custom inspect for the native parts
63
- result = super()
63
+ result = super
64
64
  result[-1] = "#{self.class._native_inspect(self)}>"
65
65
  result
66
66
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Profiling
5
+ # This class exists to wrap a ddog_prof_EncodedProfile into a Ruby object
6
+ #
7
+ # This class is not empty; all of this class is implemented as native code.
8
+ class EncodedProfile # rubocop:disable Lint/EmptyClass
9
+ end
10
+ end
11
+ end
@@ -57,7 +57,7 @@ module Datadog
57
57
  serialization_result = pprof_recorder.serialize
58
58
  return if serialization_result.nil?
59
59
 
60
- start, finish, compressed_pprof, profile_stats = serialization_result
60
+ start, finish, encoded_profile, profile_stats = serialization_result
61
61
  @last_flush_finish_at = finish
62
62
 
63
63
  if duration_below_threshold?(start, finish)
@@ -70,8 +70,7 @@ module Datadog
70
70
  Flush.new(
71
71
  start: start,
72
72
  finish: finish,
73
- pprof_file_name: Datadog::Profiling::Ext::Transport::HTTP::PPROF_DEFAULT_FILENAME,
74
- pprof_data: compressed_pprof.to_s,
73
+ encoded_profile: encoded_profile,
75
74
  code_provenance_file_name: Datadog::Profiling::Ext::Transport::HTTP::CODE_PROVENANCE_FILENAME,
76
75
  code_provenance_data: uncompressed_code_provenance,
77
76
  tags_as_array: Datadog::Profiling::TagBuilder.call(settings: Datadog.configuration).to_a,