datadog 2.13.0 → 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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -2
  3. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +7 -6
  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/assets/waf_rules/README.md +50 -5
  12. data/lib/datadog/appsec/assets/waf_rules/processors.json +239 -10
  13. data/lib/datadog/appsec/assets/waf_rules/recommended.json +0 -1344
  14. data/lib/datadog/appsec/assets/waf_rules/scanners.json +926 -17
  15. data/lib/datadog/appsec/assets/waf_rules/strict.json +0 -1344
  16. data/lib/datadog/appsec/component.rb +19 -17
  17. data/lib/datadog/appsec/compressed_json.rb +40 -0
  18. data/lib/datadog/appsec/contrib/active_record/integration.rb +1 -1
  19. data/lib/datadog/appsec/event.rb +21 -50
  20. data/lib/datadog/appsec/remote.rb +4 -0
  21. data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
  22. data/lib/datadog/core/environment/agent_info.rb +1 -1
  23. data/lib/datadog/core/metrics/client.rb +1 -1
  24. data/lib/datadog/core/remote/client.rb +1 -1
  25. data/lib/datadog/core/remote/negotiation.rb +1 -1
  26. data/lib/datadog/core/remote/transport/config.rb +2 -2
  27. data/lib/datadog/core/remote/transport/http/client.rb +1 -1
  28. data/lib/datadog/core/remote/transport/http.rb +2 -2
  29. data/lib/datadog/core/remote/transport/negotiation.rb +2 -2
  30. data/lib/datadog/core/telemetry/metric.rb +5 -5
  31. data/lib/datadog/core/telemetry/request.rb +1 -1
  32. data/lib/datadog/core/transport/http/builder.rb +2 -2
  33. data/lib/datadog/core/transport/http.rb +1 -1
  34. data/lib/datadog/di/probe_notification_builder.rb +1 -1
  35. data/lib/datadog/di/transport/diagnostics.rb +2 -2
  36. data/lib/datadog/di/transport/http/client.rb +1 -1
  37. data/lib/datadog/di/transport/http/diagnostics.rb +0 -1
  38. data/lib/datadog/di/transport/http/input.rb +0 -1
  39. data/lib/datadog/di/transport/http.rb +0 -6
  40. data/lib/datadog/di/transport/input.rb +2 -2
  41. data/lib/datadog/kit/appsec/events.rb +6 -3
  42. data/lib/datadog/profiling/collectors/info.rb +3 -0
  43. data/lib/datadog/profiling/encoded_profile.rb +11 -0
  44. data/lib/datadog/profiling/exporter.rb +2 -3
  45. data/lib/datadog/profiling/ext.rb +0 -1
  46. data/lib/datadog/profiling/flush.rb +4 -7
  47. data/lib/datadog/profiling/http_transport.rb +10 -59
  48. data/lib/datadog/profiling/stack_recorder.rb +4 -4
  49. data/lib/datadog/profiling.rb +1 -0
  50. data/lib/datadog/tracing/contrib/active_record/integration.rb +1 -1
  51. data/lib/datadog/tracing/contrib/ext.rb +1 -0
  52. data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +27 -0
  53. data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +46 -0
  54. data/lib/datadog/tracing/contrib/karafka/ext.rb +27 -0
  55. data/lib/datadog/tracing/contrib/karafka/integration.rb +45 -0
  56. data/lib/datadog/tracing/contrib/karafka/monitor.rb +66 -0
  57. data/lib/datadog/tracing/contrib/karafka/patcher.rb +71 -0
  58. data/lib/datadog/tracing/contrib/karafka.rb +37 -0
  59. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +17 -0
  60. data/lib/datadog/tracing/contrib/opensearch/ext.rb +9 -0
  61. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +5 -1
  62. data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
  63. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +1 -1
  64. data/lib/datadog/tracing/contrib.rb +1 -0
  65. data/lib/datadog/tracing/span_event.rb +1 -1
  66. data/lib/datadog/tracing/transport/http/client.rb +1 -1
  67. data/lib/datadog/tracing/transport/http.rb +1 -1
  68. data/lib/datadog/tracing/transport/traces.rb +11 -6
  69. data/lib/datadog/version.rb +1 -1
  70. data/lib/datadog.rb +1 -1
  71. metadata +17 -6
@@ -12,7 +12,25 @@ module Datadog
12
12
  class << self
13
13
  def build_appsec_component(settings, telemetry:)
14
14
  return if !settings.respond_to?(:appsec) || !settings.appsec.enabled
15
- return if incompatible_ffi_version?
15
+
16
+ ffi_version = Gem.loaded_specs['ffi'] && Gem.loaded_specs['ffi'].version
17
+ unless ffi_version
18
+ Datadog.logger.warn('FFI gem is not loaded, AppSec will be disabled.')
19
+ telemetry.error('AppSec: Component not loaded, due to missing FFI gem')
20
+
21
+ return
22
+ end
23
+
24
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.3') && ffi_version < Gem::Version.new('1.16.0')
25
+ Datadog.logger.warn(
26
+ 'AppSec is not supported in Ruby versions above 3.3.0 when using `ffi` versions older than 1.16.0, ' \
27
+ 'and will be forcibly disabled due to a memory leak in `ffi`. ' \
28
+ 'Please upgrade your `ffi` version to 1.16.0 or higher.'
29
+ )
30
+ telemetry.error('AppSec: Component not loaded, ffi version is leaky with ruby > 3.3.0')
31
+
32
+ return
33
+ end
16
34
 
17
35
  processor = create_processor(settings, telemetry)
18
36
 
@@ -29,22 +47,6 @@ module Datadog
29
47
 
30
48
  private
31
49
 
32
- def incompatible_ffi_version?
33
- ffi_version = Gem.loaded_specs['ffi'] && Gem.loaded_specs['ffi'].version
34
- return true unless ffi_version
35
-
36
- return false unless Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.3') &&
37
- ffi_version < Gem::Version.new('1.16.0')
38
-
39
- Datadog.logger.warn(
40
- 'AppSec is not supported in Ruby versions above 3.3.0 when using `ffi` versions older than 1.16.0, ' \
41
- 'and will be forcibly disabled due to a memory leak in `ffi`. ' \
42
- 'Please upgrade your `ffi` version to 1.16.0 or higher.'
43
- )
44
-
45
- true
46
- end
47
-
48
50
  def create_processor(settings, telemetry)
49
51
  rules = AppSec::Processor::RuleLoader.load_rules(
50
52
  telemetry: telemetry,
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'zlib'
5
+ require 'stringio'
6
+
7
+ require_relative '../core/utils/base64'
8
+
9
+ module Datadog
10
+ module AppSec
11
+ # Converts derivative schema payloads into JSON and compresses them into a
12
+ # base64 encoded string if the payload is worth compressing.
13
+ #
14
+ # See: https://github.com/DataDog/dd-trace-rb/pull/3177#issuecomment-1747221082
15
+ module CompressedJson
16
+ MIN_SIZE_FOR_COMPRESSION = 260
17
+
18
+ def self.dump(payload)
19
+ value = JSON.dump(payload)
20
+ return value if value.bytesize < MIN_SIZE_FOR_COMPRESSION
21
+
22
+ compress_and_encode(value)
23
+ rescue ArgumentError, Encoding::UndefinedConversionError, JSON::JSONError => e
24
+ AppSec.telemetry.report(e, description: 'AppSec: Failed to convert value into JSON')
25
+
26
+ nil
27
+ end
28
+
29
+ private_class_method def self.compress_and_encode(payload)
30
+ Core::Utils::Base64.strict_encode64(
31
+ Zlib.gzip(payload, level: Zlib::BEST_SPEED, strategy: Zlib::DEFAULT_STRATEGY)
32
+ )
33
+ rescue Zlib::Error, TypeError => e
34
+ AppSec.telemetry.report(e, description: 'AppSec: Failed to compress and encode value')
35
+
36
+ nil
37
+ end
38
+ end
39
+ end
40
+ end
@@ -13,7 +13,7 @@ module Datadog
13
13
 
14
14
  MINIMUM_VERSION = Gem::Version.new('4')
15
15
 
16
- register_as :active_record, auto_patch: false
16
+ register_as :active_record, auto_patch: true
17
17
 
18
18
  def self.version
19
19
  Gem.loaded_specs['activerecord'] && Gem.loaded_specs['activerecord'].version
@@ -1,15 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'json'
4
- require 'zlib'
5
-
6
4
  require_relative 'rate_limiter'
7
- require_relative '../core/utils/base64'
5
+ require_relative 'compressed_json'
8
6
 
9
7
  module Datadog
10
8
  module AppSec
11
9
  # AppSec event
12
10
  module Event
11
+ DERIVATIVE_SCHEMA_KEY_PREFIX = '_dd.appsec.s.'
12
+ DERIVATIVE_SCHEMA_MAX_COMPRESSED_SIZE = 25000
13
13
  ALLOWED_REQUEST_HEADERS = %w[
14
14
  X-Forwarded-For
15
15
  X-Client-IP
@@ -38,11 +38,6 @@ module Datadog
38
38
  Content-Language
39
39
  ].map!(&:downcase).freeze
40
40
 
41
- MAX_ENCODED_SCHEMA_SIZE = 25000
42
- # For more information about this number
43
- # please check https://github.com/DataDog/dd-trace-rb/pull/3177#issuecomment-1747221082
44
- MIN_SCHEMA_SIZE_FOR_COMPRESSION = 260
45
-
46
41
  # Record events for a trace
47
42
  #
48
43
  # This is expected to be called only once per trace for the rate limiter
@@ -80,7 +75,6 @@ module Datadog
80
75
  end
81
76
  end
82
77
 
83
- # rubocop:disable Metrics/MethodLength
84
78
  def build_service_entry_tags(event_group)
85
79
  waf_events = []
86
80
  entry_tags = event_group.each_with_object({ '_dd.origin' => 'appsec' }) do |event, tags|
@@ -106,26 +100,17 @@ module Datadog
106
100
  waf_events += waf_result.events
107
101
 
108
102
  waf_result.derivatives.each do |key, value|
109
- parsed_value = json_parse(value)
110
- next unless parsed_value
111
-
112
- parsed_value_size = parsed_value.size
113
-
114
- schema_value = if parsed_value_size >= MIN_SCHEMA_SIZE_FOR_COMPRESSION
115
- compressed_and_base64_encoded(parsed_value)
116
- else
117
- parsed_value
118
- end
119
- next unless schema_value
120
-
121
- if schema_value.size >= MAX_ENCODED_SCHEMA_SIZE
122
- Datadog.logger.debug do
123
- "Schema key: #{key} exceeds the max size value. It will not be included as part of the span tags"
124
- end
103
+ next tags[key] = value unless key.start_with?(DERIVATIVE_SCHEMA_KEY_PREFIX)
104
+
105
+ value = CompressedJson.dump(value)
106
+ next if value.nil?
107
+
108
+ if value.size >= DERIVATIVE_SCHEMA_MAX_COMPRESSED_SIZE
109
+ Datadog.logger.debug { "AppSec: Schema key '#{key}' will not be included into span tags due to it's size" }
125
110
  next
126
111
  end
127
112
 
128
- tags[key] = schema_value
113
+ tags[key] = value
129
114
  end
130
115
 
131
116
  tags
@@ -135,14 +120,16 @@ module Datadog
135
120
  entry_tags['_dd.appsec.json'] = appsec_events if appsec_events
136
121
  entry_tags
137
122
  end
138
- # rubocop:enable Metrics/MethodLength
139
123
 
140
124
  def tag_and_keep!(context, waf_result)
141
125
  # We want to keep the trace in case of security event
142
126
  context.trace.keep! if context.trace
143
127
 
144
128
  if context.span
145
- context.span.set_tag('appsec.blocked', 'true') if waf_result.actions.key?('block_request')
129
+ if waf_result.actions.key?('block_request') || waf_result.actions.key?('redirect_request')
130
+ context.span.set_tag('appsec.blocked', 'true')
131
+ end
132
+
146
133
  context.span.set_tag('appsec.event', 'true')
147
134
  end
148
135
 
@@ -151,31 +138,15 @@ module Datadog
151
138
 
152
139
  private
153
140
 
154
- def compressed_and_base64_encoded(value)
155
- Datadog::Core::Utils::Base64.strict_encode64(gzip(value))
156
- rescue TypeError => e
157
- Datadog.logger.debug do
158
- "Failed to compress and encode value when populating AppSec::Event. Error: #{e.message}"
159
- end
160
- nil
161
- end
162
-
141
+ # NOTE: Handling of Encoding::UndefinedConversionError is added as a quick fix to
142
+ # the issue between Ruby encoded strings and libddwaf produced events and now
143
+ # is under investigation.
163
144
  def json_parse(value)
164
145
  JSON.dump(value)
165
- rescue ArgumentError => e
166
- Datadog.logger.debug do
167
- "Failed to parse value to JSON when populating AppSec::Event. Error: #{e.message}"
168
- end
169
- nil
170
- end
146
+ rescue ArgumentError, Encoding::UndefinedConversionError, JSON::JSONError => e
147
+ AppSec.telemetry.report(e, description: 'AppSec: Failed to convert value into JSON')
171
148
 
172
- def gzip(value)
173
- sio = StringIO.new
174
- # For an in depth comparison of Zlib options check https://github.com/DataDog/dd-trace-rb/pull/3177#issuecomment-1747215473
175
- gz = Zlib::GzipWriter.new(sio, Zlib::BEST_SPEED, Zlib::DEFAULT_STRATEGY)
176
- gz.write(value)
177
- gz.close
178
- sio.string
149
+ nil
179
150
  end
180
151
 
181
152
  # Propagate to downstream services the information that the current distributed trace is
@@ -23,6 +23,8 @@ module Datadog
23
23
  CAP_ASM_CUSTOM_RULES = 1 << 8 # accept custom rules
24
24
  CAP_ASM_CUSTOM_BLOCKING_RESPONSE = 1 << 9 # supports custom http code or redirect sa blocking response
25
25
  CAP_ASM_TRUSTED_IPS = 1 << 10 # supports trusted ip
26
+ CAP_ASM_RASP_SSRF = 1 << 23 # support for server-side request forgery exploit prevention rules
27
+ CAP_ASM_RASP_SQLI = 1 << 21 # support for SQL injection exploit prevention rules
26
28
 
27
29
  # TODO: we need to dynamically add CAP_ASM_ACTIVATION once we support it
28
30
  ASM_CAPABILITIES = [
@@ -35,6 +37,8 @@ module Datadog
35
37
  CAP_ASM_CUSTOM_RULES,
36
38
  CAP_ASM_CUSTOM_BLOCKING_RESPONSE,
37
39
  CAP_ASM_TRUSTED_IPS,
40
+ CAP_ASM_RASP_SSRF,
41
+ CAP_ASM_RASP_SQLI,
38
42
  ].freeze
39
43
 
40
44
  ASM_PRODUCTS = [
@@ -79,7 +79,7 @@ module Datadog
79
79
 
80
80
  # @return [String] current time in ISO8601 format
81
81
  def date
82
- Time.now.utc.iso8601
82
+ Core::Utils::Time.now.utc.iso8601
83
83
  end
84
84
 
85
85
  # Best portable guess of OS information.
@@ -53,7 +53,7 @@ module Datadog
53
53
  class AgentInfo
54
54
  attr_reader :agent_settings, :logger
55
55
 
56
- def initialize(agent_settings, logger:)
56
+ def initialize(agent_settings, logger: Datadog.logger)
57
57
  @agent_settings = agent_settings
58
58
  @logger = logger
59
59
  @client = Remote::Transport::HTTP.root(agent_settings: agent_settings, logger: logger)
@@ -23,7 +23,7 @@ module Datadog
23
23
 
24
24
  attr_reader :statsd, :logger
25
25
 
26
- def initialize(logger:, statsd: nil, enabled: true, **_)
26
+ def initialize(logger: Datadog.logger, statsd: nil, enabled: true, **_)
27
27
  @logger = logger
28
28
  @statsd =
29
29
  if supported?
@@ -15,7 +15,7 @@ module Datadog
15
15
 
16
16
  attr_reader :transport, :repository, :id, :dispatcher, :logger
17
17
 
18
- def initialize(transport, capabilities, logger:, repository: Configuration::Repository.new)
18
+ def initialize(transport, capabilities, logger: Datadog.logger, repository: Configuration::Repository.new)
19
19
  @transport = transport
20
20
  @logger = logger
21
21
 
@@ -9,7 +9,7 @@ module Datadog
9
9
  class Negotiation
10
10
  attr_reader :logger
11
11
 
12
- def initialize(_settings, agent_settings, logger:, suppress_logging: {})
12
+ def initialize(_settings, agent_settings, logger: Datadog.logger, suppress_logging: {})
13
13
  @logger = logger
14
14
  @transport_root = Datadog::Core::Remote::Transport::HTTP.root(agent_settings: agent_settings, logger: logger)
15
15
  @logged = suppress_logging
@@ -34,11 +34,11 @@ module Datadog
34
34
  class Transport
35
35
  attr_reader :client, :apis, :default_api, :current_api_id, :logger
36
36
 
37
- def initialize(apis, default_api, logger)
37
+ def initialize(apis, default_api, logger: Datadog.logger)
38
38
  @apis = apis
39
39
  @logger = logger
40
40
 
41
- @client = HTTP::Client.new(current_api, logger)
41
+ @client = HTTP::Client.new(current_api, logger: logger)
42
42
  end
43
43
 
44
44
  ##### there is only one transport! it's negotiation!
@@ -17,7 +17,7 @@ module Datadog
17
17
  class Client
18
18
  attr_reader :api, :logger
19
19
 
20
- def initialize(api, logger)
20
+ def initialize(api, logger: Datadog.logger)
21
21
  @api = api
22
22
  @logger = logger
23
23
  end
@@ -33,7 +33,7 @@ module Datadog
33
33
  # Pass a block to override any settings.
34
34
  def root(
35
35
  agent_settings:,
36
- logger:,
36
+ logger: Datadog.logger,
37
37
  api_version: nil,
38
38
  headers: nil
39
39
  )
@@ -57,7 +57,7 @@ module Datadog
57
57
  # Pass a block to override any settings.
58
58
  def v7(
59
59
  agent_settings:,
60
- logger:,
60
+ logger: Datadog.logger,
61
61
  api_version: nil,
62
62
  headers: nil
63
63
  )
@@ -51,11 +51,11 @@ module Datadog
51
51
  class Transport
52
52
  attr_reader :client, :apis, :default_api, :current_api_id, :logger
53
53
 
54
- def initialize(apis, default_api, logger)
54
+ def initialize(apis, default_api, logger: Datadog.logger)
55
55
  @apis = apis
56
56
  @logger = logger
57
57
 
58
- @client = HTTP::Client.new(current_api, logger)
58
+ @client = HTTP::Client.new(current_api, logger: logger)
59
59
  end
60
60
 
61
61
  def send_info
@@ -108,9 +108,9 @@ module Datadog
108
108
  value = value.to_i
109
109
 
110
110
  if values.empty?
111
- values << [Time.now.to_i, value]
111
+ values << [Core::Utils::Time.now.to_i, value]
112
112
  else
113
- values[0][0] = Time.now.to_i
113
+ values[0][0] = Core::Utils::Time.now.to_i
114
114
  values[0][1] += value
115
115
  end
116
116
  nil
@@ -129,9 +129,9 @@ module Datadog
129
129
 
130
130
  def track(value)
131
131
  if values.empty?
132
- values << [Time.now.to_i, value]
132
+ values << [Core::Utils::Time.now.to_i, value]
133
133
  else
134
- values[0][0] = Time.now.to_i
134
+ values[0][0] = Core::Utils::Time.now.to_i
135
135
  values[0][1] = value
136
136
  end
137
137
  nil
@@ -155,7 +155,7 @@ module Datadog
155
155
 
156
156
  def track(value = 1.0)
157
157
  @value += value
158
- @values = [[Time.now.to_i, @value / interval]]
158
+ @values = [[Core::Utils::Time.now.to_i, @value / interval]]
159
159
  nil
160
160
  end
161
161
  end
@@ -21,7 +21,7 @@ module Datadog
21
21
  request_type: event.type,
22
22
  runtime_id: Core::Environment::Identity.id,
23
23
  seq_id: seq_id,
24
- tracer_time: Time.now.to_i,
24
+ tracer_time: Core::Utils::Time.now.to_i,
25
25
  }
26
26
  hash.compact!
27
27
  hash
@@ -21,7 +21,7 @@ module Datadog
21
21
  :default_headers,
22
22
  :logger
23
23
 
24
- def initialize(api_instance_class:, logger:)
24
+ def initialize(api_instance_class:, logger: Datadog.logger)
25
25
  # Global settings
26
26
  @default_adapter = nil
27
27
  @default_headers = {}
@@ -88,7 +88,7 @@ module Datadog
88
88
  def to_transport(klass)
89
89
  raise NoDefaultApiError if @default_api.nil?
90
90
 
91
- klass.new(to_api_instances, @default_api, logger)
91
+ klass.new(to_api_instances, @default_api, logger: logger)
92
92
  end
93
93
 
94
94
  def to_api_instances
@@ -29,7 +29,7 @@ module Datadog
29
29
  # Helper function that delegates to Builder.new
30
30
  # but is under HTTP namespace so that client code requires this file
31
31
  # to get the adapters configured, and not the builder directly.
32
- def build(api_instance_class:, agent_settings:, logger:, api_version: nil, headers: nil, &block)
32
+ def build(api_instance_class:, agent_settings:, logger: Datadog.logger, api_version: nil, headers: nil, &block)
33
33
  Builder.new(api_instance_class: api_instance_class, logger: logger) do |transport|
34
34
  transport.adapter(agent_settings)
35
35
  transport.headers(default_headers)
@@ -191,7 +191,7 @@ module Datadog
191
191
  end
192
192
 
193
193
  def timestamp_now
194
- (Time.now.to_f * 1000).to_i
194
+ (Core::Utils::Time.now.to_f * 1000).to_i
195
195
  end
196
196
 
197
197
  def get_local_variables(trace_point)
@@ -17,11 +17,11 @@ module Datadog
17
17
  class Transport
18
18
  attr_reader :client, :apis, :default_api, :current_api_id, :logger
19
19
 
20
- def initialize(apis, default_api, logger)
20
+ def initialize(apis, default_api, logger:)
21
21
  @apis = apis
22
22
  @logger = logger
23
23
 
24
- @client = HTTP::Client.new(current_api, logger)
24
+ @client = HTTP::Client.new(current_api, logger: logger)
25
25
  end
26
26
 
27
27
  def current_api
@@ -16,7 +16,7 @@ module Datadog
16
16
  class Client
17
17
  attr_reader :api, :logger
18
18
 
19
- def initialize(api, logger)
19
+ def initialize(api, logger:)
20
20
  @api = api
21
21
  @logger = logger
22
22
  end
@@ -38,7 +38,6 @@ module Datadog
38
38
  end
39
39
  end
40
40
 
41
- # Endpoint for negotiation
42
41
  class Endpoint < Datadog::Core::Transport::HTTP::API::Endpoint
43
42
  attr_reader :encoder
44
43
 
@@ -38,7 +38,6 @@ module Datadog
38
38
  end
39
39
  end
40
40
 
41
- # Endpoint for negotiation
42
41
  class Endpoint < Datadog::Core::Transport::HTTP::API::Endpoint
43
42
  HEADER_CONTENT_TYPE = 'Content-Type'
44
43
 
@@ -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
@@ -17,11 +17,11 @@ module Datadog
17
17
  class Transport
18
18
  attr_reader :client, :apis, :default_api, :current_api_id, :logger
19
19
 
20
- def initialize(apis, default_api, logger)
20
+ def initialize(apis, default_api, logger:)
21
21
  @apis = apis
22
22
  @logger = logger
23
23
 
24
- @client = HTTP::Client.new(current_api, logger)
24
+ @client = HTTP::Client.new(current_api, logger: logger)
25
25
  end
26
26
 
27
27
  def current_api
@@ -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,10 +31,11 @@ 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)
33
- user_login = user_options[:login] || others[:'usr.login'] || user_id
34
+ user_login = user_options[:login] || others[:'usr.login'] || others['usr.login'] || user_id
34
35
 
35
36
  raise ArgumentError, 'missing required key: :user => { :id }' if user_id.nil?
36
37
 
38
+ others = others.reject { |key, _| USER_LOGIN_KEYS.include?(key) }
37
39
  others[:'usr.login'] = user_login
38
40
  track(LOGIN_SUCCESS_EVENT, active_trace, active_span, **others)
39
41
 
@@ -58,7 +60,7 @@ module Datadog
58
60
  # event information to attach to the trace.
59
61
  def track_login_failure(trace = nil, span = nil, user_exists:, user_id: nil, **others)
60
62
  set_trace_and_span_context('track_login_failure', trace, span) do |active_trace, active_span|
61
- others[:'usr.login'] = user_id if user_id && !others.key?(:'usr.login')
63
+ others[:'usr.login'] = user_id if user_id && !others.key?(:'usr.login') && !others.key?('usr.login')
62
64
  track(LOGIN_FAILURE_EVENT, active_trace, active_span, **others)
63
65
 
64
66
  active_span.set_tag('appsec.events.users.login.failure.usr.id', user_id) if user_id
@@ -84,10 +86,11 @@ module Datadog
84
86
  set_trace_and_span_context('track_signup', trace, span) do |active_trace, active_span|
85
87
  user_options = user.dup
86
88
  user_id = user_options.delete(:id)
87
- user_login = user_options[:login] || others[:'usr.login'] || user_id
89
+ user_login = user_options[:login] || others[:'usr.login'] || others['usr.login'] || user_id
88
90
 
89
91
  raise ArgumentError, 'missing required key: :user => { :id }' if user_id.nil?
90
92
 
93
+ others = others.reject { |key, _| USER_LOGIN_KEYS.include?(key) }
91
94
  others[:'usr.login'] = user_login
92
95
  track(SIGNUP_EVENT, active_trace, active_span, **others)
93
96
 
@@ -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
@@ -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,
@@ -26,7 +26,6 @@ module Datadog
26
26
  TAG_GIT_REPOSITORY_URL = "git.repository_url"
27
27
  TAG_GIT_COMMIT_SHA = "git.commit.sha"
28
28
 
29
- PPROF_DEFAULT_FILENAME = "rubyprofile.pprof"
30
29
  CODE_PROVENANCE_FILENAME = "code-provenance.json"
31
30
  end
32
31
  end
@@ -9,10 +9,9 @@ module Datadog
9
9
  attr_reader \
10
10
  :start,
11
11
  :finish,
12
- :pprof_file_name,
13
- :pprof_data, # gzipped pprof bytes
12
+ :encoded_profile,
14
13
  :code_provenance_file_name,
15
- :code_provenance_data, # gzipped json bytes
14
+ :code_provenance_data,
16
15
  :tags_as_array,
17
16
  :internal_metadata_json,
18
17
  :info_json
@@ -20,8 +19,7 @@ module Datadog
20
19
  def initialize(
21
20
  start:,
22
21
  finish:,
23
- pprof_file_name:,
24
- pprof_data:,
22
+ encoded_profile:,
25
23
  code_provenance_file_name:,
26
24
  code_provenance_data:,
27
25
  tags_as_array:,
@@ -30,8 +28,7 @@ module Datadog
30
28
  )
31
29
  @start = start
32
30
  @finish = finish
33
- @pprof_file_name = pprof_file_name
34
- @pprof_data = pprof_data
31
+ @encoded_profile = encoded_profile
35
32
  @code_provenance_file_name = code_provenance_file_name
36
33
  @code_provenance_data = code_provenance_data
37
34
  @tags_as_array = tags_as_array