datadog 2.12.0 → 2.12.2

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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -1
  3. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +8 -0
  4. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +23 -6
  5. data/lib/datadog/appsec/contrib/active_record/patcher.rb +63 -12
  6. data/lib/datadog/appsec/contrib/rack/ext.rb +20 -0
  7. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +20 -0
  8. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +3 -0
  9. data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +24 -0
  10. data/lib/datadog/appsec/instrumentation/gateway.rb +17 -22
  11. data/lib/datadog/appsec/processor/rule_merger.rb +2 -1
  12. data/lib/datadog/appsec/remote.rb +7 -0
  13. data/lib/datadog/core/configuration/components.rb +9 -8
  14. data/lib/datadog/core/metrics/client.rb +9 -8
  15. data/lib/datadog/core/remote/client.rb +5 -4
  16. data/lib/datadog/core/remote/component.rb +3 -3
  17. data/lib/datadog/core/remote/negotiation.rb +1 -1
  18. data/lib/datadog/core/remote/transport/http.rb +4 -33
  19. data/lib/datadog/core/transport/http.rb +38 -0
  20. data/lib/datadog/core/workers/runtime_metrics.rb +1 -1
  21. data/lib/datadog/di/transport/http.rb +2 -16
  22. data/lib/datadog/tracing/metadata/metastruct.rb +36 -0
  23. data/lib/datadog/tracing/metadata/metastruct_tagging.rb +42 -0
  24. data/lib/datadog/tracing/metadata.rb +2 -0
  25. data/lib/datadog/tracing/span.rb +10 -1
  26. data/lib/datadog/tracing/span_operation.rb +6 -1
  27. data/lib/datadog/tracing/sync_writer.rb +4 -2
  28. data/lib/datadog/tracing/tracer.rb +6 -1
  29. data/lib/datadog/tracing/transport/http.rb +3 -32
  30. data/lib/datadog/tracing/transport/serializable_trace.rb +3 -1
  31. data/lib/datadog/tracing/workers/trace_writer.rb +6 -2
  32. data/lib/datadog/tracing/writer.rb +6 -2
  33. data/lib/datadog/version.rb +1 -1
  34. metadata +8 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5687b95de2487329c4b7e6d6eab86704f8eb2cdcedd5588bcf11af0fdc266f7e
4
- data.tar.gz: 837992da8e2c14754b6eb12eb6b26de83a20b68d2bdc369ba925ddd404c2d91b
3
+ metadata.gz: 5a27bb8e1291ee014e342297fc3d53aca8a895017281201b1b0a29cd376ba905
4
+ data.tar.gz: e26c326437e4edcbdfac0ad604514a48c23c31500a68dcc4affb53251aed5f8f
5
5
  SHA512:
6
- metadata.gz: de9312020663a01030298e462fa5b86e12b151203c6c2a555fc091954c39ecebb36c49a6dee31f9b337c35d3cad7df24c93a883f0d7da426f78d62581200d272
7
- data.tar.gz: 26b49b0f342521eccdafe2390ab13c2762abfb1791cf27faf68c75be5727a949f888ccfc8ebff39ae69de267563ea38c1abea1faaafcfef166dd25226b340c9d
6
+ metadata.gz: e8dab2f6ed8bc48fb95a4c9c3c28fce16b8eaaceb70179ee12b9a009498dabe498d73b08a25180fdb53642fc78da4388b2c80bbf76a61afd25af53449f2e9375
7
+ data.tar.gz: 4489a8e084f7873e59b4d2a13d27b9a75f2b95ae0c9b5129edfdb02a58c736890bd5226df765de216010512b9fd0ffad6f82cc373ea8ee995340ef838c721d65
data/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [2.12.2] - 2025-03-17
6
+
7
+ ### Fixed
8
+
9
+ * AppSec: Fix custom In-App WAF blocking response that was configured in the UI is now applied correctly ([#4497][])
10
+
11
+ ## [2.12.1] - 2025-03-05
12
+
13
+ ### Fixed
14
+
15
+ * AppSec: Fix `ArgumentError` from ActiveRecord for Ruby < 2.7 ([#4437][])
16
+
5
17
  ## [2.12.0] - 2025-02-27
6
18
 
7
19
  ### Added
@@ -3133,7 +3145,9 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
3133
3145
  Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3134
3146
 
3135
3147
 
3136
- [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.12.0...master
3148
+ [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.12.2...master
3149
+ [2.12.2]: https://github.com/DataDog/dd-trace-rb/compare/v2.12.1...v2.12.2
3150
+ [2.12.1]: https://github.com/DataDog/dd-trace-rb/compare/v2.12.0...v2.12.1
3137
3151
  [2.12.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.11.0...v2.12.0
3138
3152
  [2.11.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.10.0...v2.11.0
3139
3153
  [2.10.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.9.0...v2.10.0
@@ -4635,6 +4649,8 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
4635
4649
  [#4424]: https://github.com/DataDog/dd-trace-rb/issues/4424
4636
4650
  [#4425]: https://github.com/DataDog/dd-trace-rb/issues/4425
4637
4651
  [#4426]: https://github.com/DataDog/dd-trace-rb/issues/4426
4652
+ [#4437]: https://github.com/DataDog/dd-trace-rb/issues/4437
4653
+ [#4497]: https://github.com/DataDog/dd-trace-rb/issues/4497
4638
4654
  [@AdrianLC]: https://github.com/AdrianLC
4639
4655
  [@Azure7111]: https://github.com/Azure7111
4640
4656
  [@BabyGroot]: https://github.com/BabyGroot
@@ -312,6 +312,7 @@ VALUE thread_name_for(VALUE thread) {
312
312
  // to support our custom rb_profile_frames (see below)
313
313
  // Modifications:
314
314
  // * Support int first_lineno for Ruby 3.2.0+ (https://github.com/ruby/ruby/pull/6430)
315
+ // * Validate iseq and pos before calling `rb_iseq_line_no` as a safety measure (see comment below for details)
315
316
  //
316
317
  // `node_id` gets used depending on Ruby VM compilation settings (USE_ISEQ_NODE_ID being defined).
317
318
  // To avoid getting false "unused argument" warnings in setups where it's not used, we need to do this weird dance
@@ -358,6 +359,13 @@ calc_pos(const rb_iseq_t *iseq, const VALUE *pc, int *lineno, int *node_id)
358
359
  __builtin_trap();
359
360
  }
360
361
  #endif
362
+
363
+ // In PROF-11475 we spotted a crash when calling `rb_iseq_line_no` from this method. We couldn't reproduce or
364
+ // figure out the root cause, but "just in case", we're validating that the iseq looks valid and that the
365
+ // `n` used for the position is also sane, and if they don't look good, we don't calculate the line, rather
366
+ // than potentially trigger any issues.
367
+ if (RB_UNLIKELY(!RB_TYPE_P((VALUE) iseq, T_IMEMO) || n < 0 || n > ISEQ_BODY(iseq)->iseq_size)) return 0;
368
+
361
369
  if (lineno) *lineno = rb_iseq_line_no(iseq, pos);
362
370
  #ifdef USE_ISEQ_NODE_ID
363
371
  if (node_id) *node_id = rb_iseq_node_id(iseq, pos);
@@ -43,7 +43,7 @@ module Datadog
43
43
  end
44
44
  end
45
45
 
46
- # patch for all adapters in ActiveRecord >= 7.1
46
+ # patch for mysql2, sqlite3, and postgres+jdbc adapters in ActiveRecord >= 7.1
47
47
  module InternalExecQueryAdapterPatch
48
48
  def internal_exec_query(sql, *args, **rest)
49
49
  Instrumentation.detect_sql_injection(sql, adapter_name)
@@ -52,7 +52,25 @@ module Datadog
52
52
  end
53
53
  end
54
54
 
55
- # patch for postgres adapter in ActiveRecord < 7.1
55
+ # patch for mysql2, sqlite3, and postgres+jdbc adapters in ActiveRecord < 7.1
56
+ module ExecQueryAdapterPatch
57
+ def exec_query(sql, *args, **rest)
58
+ Instrumentation.detect_sql_injection(sql, adapter_name)
59
+
60
+ super
61
+ end
62
+ end
63
+
64
+ # patch for mysql2, sqlite3, and postgres+jdbc db adapters in ActiveRecord 4
65
+ module Rails4ExecQueryAdapterPatch
66
+ def exec_query(sql, *args)
67
+ Instrumentation.detect_sql_injection(sql, adapter_name)
68
+
69
+ super
70
+ end
71
+ end
72
+
73
+ # patch for non-jdbc postgres adapter in ActiveRecord > 4
56
74
  module ExecuteAndClearAdapterPatch
57
75
  def execute_and_clear(sql, *args, **rest)
58
76
  Instrumentation.detect_sql_injection(sql, adapter_name)
@@ -61,10 +79,9 @@ module Datadog
61
79
  end
62
80
  end
63
81
 
64
- # patch for mysql2 and sqlite3 adapters in ActiveRecord < 7.1
65
- # this patch is also used when using JDBC adapter
66
- module ExecQueryAdapterPatch
67
- def exec_query(sql, *args, **rest)
82
+ # patch for non-jdbc postgres adapter in ActiveRecord 4
83
+ module Rails4ExecuteAndClearAdapterPatch
84
+ def execute_and_clear(sql, name, binds)
68
85
  Instrumentation.detect_sql_injection(sql, adapter_name)
69
86
 
70
87
  super
@@ -19,30 +19,81 @@ module Datadog
19
19
  end
20
20
 
21
21
  def patch
22
+ # Rails 7.0 intruduced new on-load hooks for sqlite3 and postgresql adapters
23
+ # The load hook for mysql2 adapter was introduced in Rails 7.1
24
+ #
25
+ # If the adapter is not loaded when the :active_record load hook is called,
26
+ # we need to add a load hook for the adapter
22
27
  ActiveSupport.on_load :active_record do
23
- instrumentation_module = if ::ActiveRecord.gem_version >= Gem::Version.new('7.1')
24
- Instrumentation::InternalExecQueryAdapterPatch
25
- else
26
- Instrumentation::ExecQueryAdapterPatch
27
- end
28
-
29
28
  if defined?(::ActiveRecord::ConnectionAdapters::SQLite3Adapter)
30
- ::ActiveRecord::ConnectionAdapters::SQLite3Adapter.prepend(instrumentation_module)
29
+ ::Datadog::AppSec::Contrib::ActiveRecord::Patcher.patch_sqlite3_adapter
30
+ else
31
+ ActiveSupport.on_load :active_record_sqlite3adapter do
32
+ ::Datadog::AppSec::Contrib::ActiveRecord::Patcher.patch_sqlite3_adapter
33
+ end
31
34
  end
32
35
 
33
36
  if defined?(::ActiveRecord::ConnectionAdapters::Mysql2Adapter)
34
- ::ActiveRecord::ConnectionAdapters::Mysql2Adapter.prepend(instrumentation_module)
37
+ ::Datadog::AppSec::Contrib::ActiveRecord::Patcher.patch_mysql2_adapter
38
+ else
39
+ ActiveSupport.on_load :active_record_mysql2adapter do
40
+ ::Datadog::AppSec::Contrib::ActiveRecord::Patcher.patch_mysql2_adapter
41
+ end
35
42
  end
36
43
 
37
44
  if defined?(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
38
- unless defined?(::ActiveRecord::ConnectionAdapters::JdbcAdapter)
39
- instrumentation_module = Instrumentation::ExecuteAndClearAdapterPatch
45
+ ::Datadog::AppSec::Contrib::ActiveRecord::Patcher.patch_postgresql_adapter
46
+ else
47
+ ActiveSupport.on_load :active_record_postgresqladapter do
48
+ ::Datadog::AppSec::Contrib::ActiveRecord::Patcher.patch_postgresql_adapter
40
49
  end
41
-
42
- ::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(instrumentation_module)
43
50
  end
44
51
  end
45
52
  end
53
+
54
+ def patch_sqlite3_adapter
55
+ instrumentation_module = if ::ActiveRecord.gem_version >= Gem::Version.new('7.1')
56
+ Instrumentation::InternalExecQueryAdapterPatch
57
+ elsif ::ActiveRecord.gem_version.segments.first == 4
58
+ Instrumentation::Rails4ExecQueryAdapterPatch
59
+ else
60
+ Instrumentation::ExecQueryAdapterPatch
61
+ end
62
+
63
+ ::ActiveRecord::ConnectionAdapters::SQLite3Adapter.prepend(instrumentation_module)
64
+ end
65
+
66
+ def patch_mysql2_adapter
67
+ instrumentation_module = if ::ActiveRecord.gem_version >= Gem::Version.new('7.1')
68
+ Instrumentation::InternalExecQueryAdapterPatch
69
+ elsif ::ActiveRecord.gem_version.segments.first == 4
70
+ Instrumentation::Rails4ExecQueryAdapterPatch
71
+ else
72
+ Instrumentation::ExecQueryAdapterPatch
73
+ end
74
+
75
+ ::ActiveRecord::ConnectionAdapters::Mysql2Adapter.prepend(instrumentation_module)
76
+ end
77
+
78
+ def patch_postgresql_adapter
79
+ instrumentation_module = if ::ActiveRecord.gem_version.segments.first == 4
80
+ Instrumentation::Rails4ExecuteAndClearAdapterPatch
81
+ else
82
+ Instrumentation::ExecuteAndClearAdapterPatch
83
+ end
84
+
85
+ if defined?(::ActiveRecord::ConnectionAdapters::JdbcAdapter)
86
+ instrumentation_module = if ::ActiveRecord.gem_version >= Gem::Version.new('7.1')
87
+ Instrumentation::InternalExecQueryAdapterPatch
88
+ elsif ::ActiveRecord.gem_version.segments.first == 4
89
+ Instrumentation::Rails4ExecQueryAdapterPatch
90
+ else
91
+ Instrumentation::ExecQueryAdapterPatch
92
+ end
93
+ end
94
+
95
+ ::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(instrumentation_module)
96
+ end
46
97
  end
47
98
  end
48
99
  end
@@ -6,6 +6,26 @@ module Datadog
6
6
  module Rack
7
7
  # Rack integration constants
8
8
  module Ext
9
+ IDENTITY_COLLECTABLE_REQUEST_HEADERS = [
10
+ 'accept-encoding',
11
+ 'accept-language',
12
+ 'cf-connecting-ip',
13
+ 'cf-connecting-ipv6',
14
+ 'content-encoding',
15
+ 'content-language',
16
+ 'content-length',
17
+ 'fastly-client-ip',
18
+ 'forwarded',
19
+ 'forwarded-for',
20
+ 'host',
21
+ 'true-client-ip',
22
+ 'via',
23
+ 'x-client-ip',
24
+ 'x-cluster-client-ip',
25
+ 'x-forwarded',
26
+ 'x-forwarded-for',
27
+ 'x-real-ip'
28
+ ].freeze
9
29
  end
10
30
  end
11
31
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../ext'
3
4
  require_relative '../../../instrumentation/gateway'
4
5
  require_relative '../../../event'
5
6
 
@@ -110,6 +111,25 @@ module Datadog
110
111
  stack.call(gateway_request.request)
111
112
  end
112
113
  end
114
+
115
+ # NOTE: In the current state we unable to substibe twice to the same
116
+ # event within the same group. Ideally this code should live
117
+ # somewhere closer to identity related monitor.
118
+ # WARNING: The Gateway is a subject of refactoring
119
+ def watch_request_finish(gateway = Instrumentation.gateway)
120
+ gateway.watch('rack.request.finish', :appsec) do |stack, gateway_request|
121
+ context = gateway_request.env[AppSec::Ext::CONTEXT_KEY]
122
+ next stack.call(gateway_request.request) if context.span.nil? || !gateway.pushed?('identity.set_user')
123
+
124
+ gateway_request.headers.each do |name, value|
125
+ next unless Ext::IDENTITY_COLLECTABLE_REQUEST_HEADERS.include?(name)
126
+
127
+ context.span["http.request.headers.#{name}"] = value
128
+ end
129
+
130
+ stack.call(gateway_request.request)
131
+ end
132
+ end
113
133
  end
114
134
  end
115
135
  end
@@ -77,6 +77,8 @@ module Datadog
77
77
  gateway_response = nil
78
78
 
79
79
  interrupt_params = catch(::Datadog::AppSec::Ext::INTERRUPT) do
80
+ # TODO: This event should be renamed into `rack.request.start` to
81
+ # reflect that it's the beginning of the request-cycle
80
82
  http_response, _gateway_request = Instrumentation.gateway.push('rack.request', gateway_request) do
81
83
  @app.call(env)
82
84
  end
@@ -85,6 +87,7 @@ module Datadog
85
87
  http_response[2], http_response[0], http_response[1], context: ctx
86
88
  )
87
89
 
90
+ Instrumentation.gateway.push('rack.request.finish', gateway_request)
88
91
  Instrumentation.gateway.push('rack.response', gateway_response)
89
92
 
90
93
  nil
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module AppSec
5
+ module Instrumentation
6
+ class Gateway
7
+ # NOTE: This class extracted as-is and will be deprecated
8
+ # Instrumentation gateway middleware
9
+ class Middleware
10
+ attr_reader :key, :block
11
+
12
+ def initialize(key, &block)
13
+ @key = key
14
+ @block = block
15
+ end
16
+
17
+ def call(stack, env)
18
+ @block.call(stack, env)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,35 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'gateway/middleware'
4
+
3
5
  module Datadog
4
6
  module AppSec
5
7
  # Instrumentation for AppSec
6
8
  module Instrumentation
7
9
  # Instrumentation gateway implementation
8
10
  class Gateway
9
- # Instrumentation gateway middleware
10
- class Middleware
11
- attr_reader :key, :block
12
-
13
- def initialize(key, &block)
14
- @key = key
15
- @block = block
16
- end
17
-
18
- def call(stack, env)
19
- @block.call(stack, env)
20
- end
21
- end
22
-
23
- private_constant :Middleware
24
-
25
11
  def initialize
26
12
  @middlewares = Hash.new { |h, k| h[k] = [] }
13
+ @pushed_events = {}
27
14
  end
28
15
 
16
+ # NOTE: Be careful with pushed names because every pushed event name
17
+ # is recorded in order to provide an ability to any subscriber
18
+ # to check wether an arbitrary event had happened.
19
+ #
20
+ # WARNING: If we start pushing generated names we should consider
21
+ # limiting the storage of pushed names.
29
22
  def push(name, env, &block)
30
- block ||= -> {}
23
+ @pushed_events[name] = true
31
24
 
32
- middlewares_for_name = middlewares[name]
25
+ block ||= -> {}
26
+ middlewares_for_name = @middlewares[name]
33
27
 
34
28
  return [block.call, nil] if middlewares_for_name.empty?
35
29
 
@@ -48,14 +42,15 @@ module Datadog
48
42
  end
49
43
 
50
44
  def watch(name, key, &block)
51
- @middlewares[name] << Middleware.new(key, &block) unless middlewares[name].any? { |m| m.key == key }
45
+ @middlewares[name] << Middleware.new(key, &block) unless @middlewares[name].any? { |m| m.key == key }
52
46
  end
53
47
 
54
- private
55
-
56
- attr_reader :middlewares
48
+ def pushed?(name)
49
+ @pushed_events.key?(name)
50
+ end
57
51
  end
58
52
 
53
+ # NOTE: This left as-is and will be depricated soon.
59
54
  def self.gateway
60
55
  @gateway ||= Gateway.new # TODO: not thread safe
61
56
  end
@@ -22,7 +22,7 @@ module Datadog
22
22
  # TODO: `processors` and `scanners` are not provided by the caller, consider removing them
23
23
  def merge(
24
24
  telemetry:,
25
- rules:, data: [], overrides: [], exclusions: [], custom_rules: [],
25
+ rules:, actions: [], data: [], overrides: [], exclusions: [], custom_rules: [],
26
26
  processors: nil, scanners: nil
27
27
  )
28
28
  processors ||= begin
@@ -54,6 +54,7 @@ module Datadog
54
54
  combined_exclusions = combine_exclusions(exclusions) if exclusions.any?
55
55
  combined_custom_rules = combine_custom_rules(custom_rules) if custom_rules.any?
56
56
 
57
+ combined_rules['actions'] = actions if actions.any?
57
58
  combined_rules['rules_data'] = combined_data if combined_data
58
59
  combined_rules['rules_override'] = combined_overrides if combined_overrides
59
60
  combined_rules['exclusions'] = combined_exclusions if combined_exclusions
@@ -53,10 +53,12 @@ module Datadog
53
53
  end
54
54
 
55
55
  # rubocop:disable Metrics/MethodLength
56
+ # rubocop:disable Metrics/CyclomaticComplexity
56
57
  def receivers(telemetry)
57
58
  return [] unless remote_features_enabled?
58
59
 
59
60
  matcher = Core::Remote::Dispatcher::Matcher::Product.new(ASM_PRODUCTS)
61
+ # rubocop:disable Metrics/BlockLength
60
62
  receiver = Core::Remote::Dispatcher::Receiver.new(matcher) do |repository, changes|
61
63
  changes.each do |change|
62
64
  Datadog.logger.debug { "remote config change: '#{change.path}'" }
@@ -67,6 +69,7 @@ module Datadog
67
69
  data = []
68
70
  overrides = []
69
71
  exclusions = []
72
+ actions = []
70
73
 
71
74
  repository.contents.each do |content|
72
75
  parsed_content = parse_content(content)
@@ -80,6 +83,7 @@ module Datadog
80
83
  overrides << parsed_content['rules_override'] if parsed_content['rules_override']
81
84
  exclusions << parsed_content['exclusions'] if parsed_content['exclusions']
82
85
  custom_rules << parsed_content['custom_rules'] if parsed_content['custom_rules']
86
+ actions.concat(parsed_content['actions']) if parsed_content['actions']
83
87
  end
84
88
  end
85
89
 
@@ -97,6 +101,7 @@ module Datadog
97
101
  ruleset = AppSec::Processor::RuleMerger.merge(
98
102
  rules: rules,
99
103
  data: data,
104
+ actions: actions,
100
105
  overrides: overrides,
101
106
  exclusions: exclusions,
102
107
  custom_rules: custom_rules,
@@ -109,10 +114,12 @@ module Datadog
109
114
  content.applied if ASM_PRODUCTS.include?(content.path.product)
110
115
  end
111
116
  end
117
+ # rubocop:enable Metrics/BlockLength
112
118
 
113
119
  [receiver]
114
120
  end
115
121
  # rubocop:enable Metrics/MethodLength
122
+ # rubocop:enable Metrics/CyclomaticComplexity
116
123
 
117
124
  private
118
125
 
@@ -26,12 +26,12 @@ module Datadog
26
26
  class << self
27
27
  include Datadog::Tracing::Component
28
28
 
29
- def build_health_metrics(settings)
29
+ def build_health_metrics(settings, logger)
30
30
  settings = settings.health_metrics
31
31
  options = { enabled: settings.enabled }
32
32
  options[:statsd] = settings.statsd unless settings.statsd.nil?
33
33
 
34
- Core::Diagnostics::Health::Metrics.new(**options)
34
+ Core::Diagnostics::Health::Metrics.new(logger: logger, **options)
35
35
  end
36
36
 
37
37
  def build_logger(settings)
@@ -41,19 +41,20 @@ module Datadog
41
41
  logger
42
42
  end
43
43
 
44
- def build_runtime_metrics(settings)
44
+ def build_runtime_metrics(settings, logger)
45
45
  options = { enabled: settings.runtime_metrics.enabled }
46
46
  options[:statsd] = settings.runtime_metrics.statsd unless settings.runtime_metrics.statsd.nil?
47
47
  options[:services] = [settings.service] unless settings.service.nil?
48
48
 
49
- Core::Runtime::Metrics.new(**options)
49
+ Core::Runtime::Metrics.new(logger: logger, **options)
50
50
  end
51
51
 
52
- def build_runtime_metrics_worker(settings)
52
+ def build_runtime_metrics_worker(settings, logger)
53
53
  # NOTE: Should we just ignore building the worker if its not enabled?
54
54
  options = settings.runtime_metrics.opts.merge(
55
55
  enabled: settings.runtime_metrics.enabled,
56
- metrics: build_runtime_metrics(settings)
56
+ metrics: build_runtime_metrics(settings, logger),
57
+ logger: logger,
57
58
  )
58
59
 
59
60
  Core::Workers::RuntimeMetrics.new(options)
@@ -116,8 +117,8 @@ module Datadog
116
117
  )
117
118
  @environment_logger_extra.merge!(profiler_logger_extra) if profiler_logger_extra
118
119
 
119
- @runtime_metrics = self.class.build_runtime_metrics_worker(settings)
120
- @health_metrics = self.class.build_health_metrics(settings)
120
+ @runtime_metrics = self.class.build_runtime_metrics_worker(settings, @logger)
121
+ @health_metrics = self.class.build_health_metrics(settings, @logger)
121
122
  @appsec = Datadog::AppSec::Component.build_appsec_component(settings, telemetry: telemetry)
122
123
  @dynamic_instrumentation = Datadog::DI::Component.build(settings, agent_settings, @logger, telemetry: telemetry)
123
124
  @environment_logger_extra[:dynamic_instrumentation_enabled] = !!@dynamic_instrumentation
@@ -21,9 +21,10 @@ module Datadog
21
21
  extend Options
22
22
  extend Helpers
23
23
 
24
- attr_reader :statsd
24
+ attr_reader :statsd, :logger
25
25
 
26
- def initialize(statsd: nil, enabled: true, **_)
26
+ def initialize(logger:, statsd: nil, enabled: true, **_)
27
+ @logger = logger
27
28
  @statsd =
28
29
  if supported?
29
30
  statsd || default_statsd_client
@@ -98,7 +99,7 @@ module Datadog
98
99
 
99
100
  statsd.count(stat, value, metric_options(options))
100
101
  rescue StandardError => e
101
- Datadog.logger.error(
102
+ logger.error(
102
103
  "Failed to send count stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
103
104
  )
104
105
  Telemetry::Logger.report(e, description: 'Failed to send count stat')
@@ -112,7 +113,7 @@ module Datadog
112
113
 
113
114
  statsd.distribution(stat, value, metric_options(options))
114
115
  rescue StandardError => e
115
- Datadog.logger.error(
116
+ logger.error(
116
117
  "Failed to send distribution stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
117
118
  )
118
119
  Telemetry::Logger.report(e, description: 'Failed to send distribution stat')
@@ -125,7 +126,7 @@ module Datadog
125
126
 
126
127
  statsd.increment(stat, metric_options(options))
127
128
  rescue StandardError => e
128
- Datadog.logger.error(
129
+ logger.error(
129
130
  "Failed to send increment stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
130
131
  )
131
132
  Telemetry::Logger.report(e, description: 'Failed to send increment stat')
@@ -139,7 +140,7 @@ module Datadog
139
140
 
140
141
  statsd.gauge(stat, value, metric_options(options))
141
142
  rescue StandardError => e
142
- Datadog.logger.error(
143
+ logger.error(
143
144
  "Failed to send gauge stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
144
145
  )
145
146
  Telemetry::Logger.report(e, description: 'Failed to send gauge stat')
@@ -159,7 +160,7 @@ module Datadog
159
160
  end
160
161
  rescue StandardError => e
161
162
  # TODO: Likely to be redundant, since `distribution` handles its own errors.
162
- Datadog.logger.error(
163
+ logger.error(
163
164
  "Failed to send time stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
164
165
  )
165
166
  Telemetry::Logger.report(e, description: 'Failed to send time stat')
@@ -194,7 +195,7 @@ module Datadog
194
195
 
195
196
  def ignored_statsd_warning
196
197
  IGNORED_STATSD_ONLY_ONCE.run do
197
- Datadog.logger.warn(
198
+ logger.warn(
198
199
  'Ignoring user-supplied statsd instance as currently-installed version of dogstastd-ruby is incompatible. ' \
199
200
  "To fix this, ensure that you have `gem 'dogstatsd-ruby', '~> 5.3'` on your Gemfile or gems.rb file."
200
201
  )
@@ -13,10 +13,11 @@ module Datadog
13
13
  class TransportError < StandardError; end
14
14
  class SyncError < StandardError; end
15
15
 
16
- attr_reader :transport, :repository, :id, :dispatcher
16
+ attr_reader :transport, :repository, :id, :dispatcher, :logger
17
17
 
18
- def initialize(transport, capabilities, repository: Configuration::Repository.new)
18
+ def initialize(transport, capabilities, logger:, repository: Configuration::Repository.new)
19
19
  @transport = transport
20
+ @logger = logger
20
21
 
21
22
  @repository = repository
22
23
  @id = SecureRandom.uuid
@@ -40,7 +41,7 @@ module Datadog
40
41
  def process_response(response)
41
42
  # when response is completely empty, do nothing as in: leave as is
42
43
  if response.empty?
43
- Datadog.logger.debug { 'remote: empty response => NOOP' }
44
+ logger.debug { 'remote: empty response => NOOP' }
44
45
 
45
46
  return
46
47
  end
@@ -112,7 +113,7 @@ module Datadog
112
113
  end
113
114
 
114
115
  if changes.empty?
115
- Datadog.logger.debug { 'remote: no changes' }
116
+ logger.debug { 'remote: no changes' }
116
117
  else
117
118
  dispatcher.dispatch(changes, repository)
118
119
  end
@@ -22,11 +22,11 @@ module Datadog
22
22
  transport_options[:agent_settings] = agent_settings if agent_settings
23
23
 
24
24
  negotiation = Negotiation.new(settings, agent_settings)
25
- transport_v7 = Datadog::Core::Remote::Transport::HTTP.v7(**transport_options.dup)
25
+ transport_v7 = Datadog::Core::Remote::Transport::HTTP.v7(**transport_options) # steep:ignore
26
26
 
27
27
  @barrier = Barrier.new(settings.remote.boot_timeout_seconds)
28
28
 
29
- @client = Client.new(transport_v7, capabilities)
29
+ @client = Client.new(transport_v7, capabilities, logger: logger)
30
30
  @healthy = false
31
31
  logger.debug { "new remote configuration client: #{@client.id}" }
32
32
 
@@ -58,7 +58,7 @@ module Datadog
58
58
  end
59
59
 
60
60
  # client state is unknown, state might be corrupted
61
- @client = Client.new(transport_v7, capabilities)
61
+ @client = Client.new(transport_v7, capabilities, logger: logger)
62
62
  @healthy = false
63
63
  logger.debug { "new remote configuration client: #{@client.id}" }
64
64
 
@@ -11,7 +11,7 @@ module Datadog
11
11
  transport_options = {}
12
12
  transport_options[:agent_settings] = agent_settings if agent_settings
13
13
 
14
- @transport_root = Datadog::Core::Remote::Transport::HTTP.root(**transport_options.dup)
14
+ @transport_root = Datadog::Core::Remote::Transport::HTTP.root(**transport_options) # steep:ignore
15
15
  @logged = suppress_logging
16
16
  end
17
17
 
@@ -1,14 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'uri'
4
-
5
3
  require_relative '../../environment/container'
6
4
  require_relative '../../environment/ext'
7
5
  require_relative '../../transport/ext'
8
- require_relative '../../transport/http/builder'
9
- require_relative '../../transport/http/adapters/net'
10
- require_relative '../../transport/http/adapters/unix_socket'
11
- require_relative '../../transport/http/adapters/test'
6
+ require_relative '../../transport/http'
12
7
 
13
8
  # TODO: Improve negotiation to allow per endpoint selection
14
9
  #
@@ -32,21 +27,11 @@ module Datadog
32
27
  module Transport
33
28
  # Namespace for HTTP transport components
34
29
  module HTTP
35
- # NOTE: Due to... legacy reasons... This class likes having a default `AgentSettings` instance to fall back to.
36
- # Because we generate this instance with an empty instance of `Settings`, the resulting `AgentSettings` below
37
- # represents only settings specified via environment variables + the usual defaults.
38
- #
39
- # DO NOT USE THIS IN NEW CODE, as it ignores any settings specified by users via `Datadog.configure`.
40
- DO_NOT_USE_ENVIRONMENT_AGENT_SETTINGS = Datadog::Core::Configuration::AgentSettingsResolver.call(
41
- Datadog::Core::Configuration::Settings.new,
42
- logger: nil,
43
- )
44
-
45
30
  module_function
46
31
 
47
32
  # Builds a new Transport::HTTP::Client
48
33
  def new(klass, &block)
49
- Core::Transport::HTTP::Builder.new(
34
+ Core::Transport::HTTP.build(
50
35
  api_instance_class: API::Instance, &block
51
36
  ).to_transport(klass)
52
37
  end
@@ -54,7 +39,7 @@ module Datadog
54
39
  # Builds a new Transport::HTTP::Client with default settings
55
40
  # Pass a block to override any settings.
56
41
  def root(
57
- agent_settings: DO_NOT_USE_ENVIRONMENT_AGENT_SETTINGS,
42
+ agent_settings:,
58
43
  **options
59
44
  )
60
45
  new(Core::Remote::Transport::Negotiation::Transport) do |transport|
@@ -79,7 +64,7 @@ module Datadog
79
64
  # Builds a new Transport::HTTP::Client with default settings
80
65
  # Pass a block to override any settings.
81
66
  def v7(
82
- agent_settings: DO_NOT_USE_ENVIRONMENT_AGENT_SETTINGS,
67
+ agent_settings:,
83
68
  **options
84
69
  )
85
70
  new(Core::Remote::Transport::Config::Transport) do |transport|
@@ -126,20 +111,6 @@ module Datadog
126
111
  def default_adapter
127
112
  Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
128
113
  end
129
-
130
- # Add adapters to registry
131
- Core::Transport::HTTP::Builder::REGISTRY.set(
132
- Datadog::Core::Transport::HTTP::Adapters::Net,
133
- Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
134
- )
135
- Core::Transport::HTTP::Builder::REGISTRY.set(
136
- Datadog::Core::Transport::HTTP::Adapters::Test,
137
- Datadog::Core::Transport::Ext::Test::ADAPTER
138
- )
139
- Core::Transport::HTTP::Builder::REGISTRY.set(
140
- Datadog::Core::Transport::HTTP::Adapters::UnixSocket,
141
- Datadog::Core::Configuration::Ext::Agent::UnixSocket::ADAPTER
142
- )
143
114
  end
144
115
  end
145
116
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'http/builder'
4
+ require_relative 'http/adapters/net'
5
+ require_relative 'http/adapters/unix_socket'
6
+ require_relative 'http/adapters/test'
7
+
8
+ module Datadog
9
+ module Core
10
+ module Transport
11
+ # HTTP transport
12
+ module HTTP
13
+ # Add adapters to registry
14
+ Builder::REGISTRY.set(
15
+ Transport::HTTP::Adapters::Net,
16
+ Core::Configuration::Ext::Agent::HTTP::ADAPTER
17
+ )
18
+ Builder::REGISTRY.set(
19
+ Transport::HTTP::Adapters::Test,
20
+ Transport::Ext::Test::ADAPTER
21
+ )
22
+ Builder::REGISTRY.set(
23
+ Transport::HTTP::Adapters::UnixSocket,
24
+ Transport::Ext::UnixSocket::ADAPTER
25
+ )
26
+
27
+ module_function
28
+
29
+ # Helper function that delegates to Builder.new
30
+ # but is under HTTP namespace so that client code requires this file
31
+ # to get the adapters configured, and not the builder directly.
32
+ def build(api_instance_class:, &block)
33
+ Builder.new(api_instance_class: api_instance_class, &block)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -21,7 +21,7 @@ module Datadog
21
21
  :metrics
22
22
 
23
23
  def initialize(options = {})
24
- @metrics = options.fetch(:metrics) { Core::Runtime::Metrics.new }
24
+ @metrics = options.fetch(:metrics) { Core::Runtime::Metrics.new(logger: options[:logger]) }
25
25
 
26
26
  # Workers::Async::Thread settings
27
27
  self.fork_policy = options.fetch(:fork_policy, Workers::Async::Thread::FORK_POLICY_STOP)
@@ -5,13 +5,10 @@ require 'uri'
5
5
  require_relative '../../core/environment/container'
6
6
  require_relative '../../core/environment/ext'
7
7
  require_relative '../../core/transport/ext'
8
- require_relative '../../core/transport/http/adapters/net'
9
- require_relative '../../core/transport/http/adapters/test'
10
- require_relative '../../core/transport/http/adapters/unix_socket'
11
8
  require_relative 'diagnostics'
12
9
  require_relative 'input'
13
10
  require_relative 'http/api'
14
- require_relative '../../core/transport/http/builder'
11
+ require_relative '../../core/transport/http'
15
12
  require_relative '../../../datadog/version'
16
13
 
17
14
  module Datadog
@@ -23,7 +20,7 @@ module Datadog
23
20
 
24
21
  # Builds a new Transport::HTTP::Client
25
22
  def new(klass, &block)
26
- Core::Transport::HTTP::Builder.new(
23
+ Core::Transport::HTTP.build(
27
24
  api_instance_class: API::Instance, &block
28
25
  ).to_transport(klass)
29
26
  end
@@ -102,17 +99,6 @@ module Datadog
102
99
  def default_adapter
103
100
  Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
104
101
  end
105
-
106
- # Add adapters to registry
107
- Datadog::Core::Transport::HTTP::Builder::REGISTRY.set(
108
- Datadog::Core::Transport::HTTP::Adapters::Net,
109
- Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
110
- )
111
- Datadog::Core::Transport::HTTP::Builder::REGISTRY.set(Datadog::Core::Transport::HTTP::Adapters::Test, Datadog::Core::Transport::Ext::Test::ADAPTER)
112
- Datadog::Core::Transport::HTTP::Builder::REGISTRY.set(
113
- Datadog::Core::Transport::HTTP::Adapters::UnixSocket,
114
- Datadog::Core::Transport::Ext::UnixSocket::ADAPTER
115
- )
116
102
  end
117
103
  end
118
104
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ module Datadog
6
+ module Tracing
7
+ module Metadata
8
+ # This class is a data structure that is used to store
9
+ # complex metadata, such as an array of objects.
10
+ #
11
+ # It is serialized to MessagePack format when sent to the agent.
12
+ class Metastruct
13
+ extend Forwardable
14
+
15
+ def_delegators :@metastruct, :[], :[]=, :to_h
16
+
17
+ def initialize
18
+ @metastruct = {}
19
+ end
20
+
21
+ def to_msgpack(packer = nil)
22
+ # JRuby doesn't pass the packer
23
+ packer ||= MessagePack::Packer.new
24
+
25
+ packer.write(@metastruct.transform_values(&:to_msgpack))
26
+ end
27
+
28
+ def pretty_print(q)
29
+ q.seplist @metastruct.each do |key, value|
30
+ q.text "#{key} => #{value}"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'metastruct'
4
+
5
+ module Datadog
6
+ module Tracing
7
+ module Metadata
8
+ # Adds data storage for the `meta_struct` field.
9
+ #
10
+ # This field is used to send more complex data like an array of objects
11
+ # in MessagePack format to the agent, and has no size limitations.
12
+ #
13
+ # The agent fully supports meta_struct from version v7.35.0 (April 2022).
14
+ #
15
+ # On versions older than v7.35.0, sending traces containing meta_struct
16
+ # has no unexpected side-effects; traces are sent to the backend as expected,
17
+ # while the meta_struct field is stripped.
18
+ module MetastructTagging
19
+ # Set the given key / value tag pair on the metastruct.
20
+ #
21
+ # A valid example is:
22
+ #
23
+ # span.set_metastruct_tag('_dd.stack', [])
24
+ def set_metastruct_tag(key, value)
25
+ metastruct[key] = value
26
+ end
27
+
28
+ # Return the metastruct tag value for the given key,
29
+ # returns nil if the key doesn't exist.
30
+ def get_metastruct_tag(key)
31
+ metastruct[key]
32
+ end
33
+
34
+ private
35
+
36
+ def metastruct
37
+ @metastruct ||= Metastruct.new
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'metadata/analytics'
4
4
  require_relative 'metadata/tagging'
5
+ require_relative 'metadata/metastruct_tagging'
5
6
  require_relative 'metadata/errors'
6
7
 
7
8
  module Datadog
@@ -10,6 +11,7 @@ module Datadog
10
11
  module Metadata
11
12
  def self.included(base)
12
13
  base.include(Metadata::Tagging)
14
+ base.include(Metadata::MetastructTagging)
13
15
  base.include(Metadata::Errors)
14
16
 
15
17
  # Additional extensions
@@ -33,6 +33,9 @@ module Datadog
33
33
  :status,
34
34
  :trace_id
35
35
 
36
+ attr_reader \
37
+ :metastruct
38
+
36
39
  attr_writer \
37
40
  :duration
38
41
 
@@ -54,6 +57,7 @@ module Datadog
54
57
  id: nil,
55
58
  meta: nil,
56
59
  metrics: nil,
60
+ metastruct: nil,
57
61
  parent_id: 0,
58
62
  resource: name,
59
63
  service: nil,
@@ -76,6 +80,7 @@ module Datadog
76
80
 
77
81
  @meta = meta || {}
78
82
  @metrics = metrics || {}
83
+ @metastruct = metastruct || {}
79
84
  @status = status || 0
80
85
 
81
86
  # start_time and end_time track wall clock. In Ruby, wall clock
@@ -144,6 +149,7 @@ module Datadog
144
149
  error: @status,
145
150
  meta: @meta,
146
151
  metrics: @metrics,
152
+ meta_struct: @metastruct.to_h,
147
153
  name: @name,
148
154
  parent_id: @parent_id,
149
155
  resource: @resource,
@@ -185,12 +191,15 @@ module Datadog
185
191
  q.text "#{key} => #{value}"
186
192
  end
187
193
  end
188
- q.group(2, 'Metrics: [', ']') do
194
+ q.group(2, 'Metrics: [', "]\n") do
189
195
  q.breakable
190
196
  q.seplist @metrics.each do |key, value|
191
197
  q.text "#{key} => #{value}"
192
198
  end
193
199
  end
200
+ q.group(2, 'Metastruct: [', ']') do
201
+ metastruct.pretty_print(q)
202
+ end
194
203
  end
195
204
  end
196
205
 
@@ -289,6 +289,7 @@ module Datadog
289
289
  id: @id,
290
290
  meta: meta,
291
291
  metrics: metrics,
292
+ metastruct: metastruct,
292
293
  name: @name,
293
294
  parent_id: @parent_id,
294
295
  resource: @resource,
@@ -328,12 +329,15 @@ module Datadog
328
329
  q.text "#{key} => #{value}"
329
330
  end
330
331
  end
331
- q.group(2, 'Metrics: [', ']') do
332
+ q.group(2, 'Metrics: [', "]\n") do
332
333
  q.breakable
333
334
  q.seplist metrics.each do |key, value|
334
335
  q.text "#{key} => #{value}"
335
336
  end
336
337
  end
338
+ q.group(2, 'Metastruct: [', ']') do
339
+ metastruct.pretty_print(q)
340
+ end
337
341
  end
338
342
  end
339
343
 
@@ -456,6 +460,7 @@ module Datadog
456
460
  id: @id,
457
461
  meta: Core::Utils::SafeDup.frozen_or_dup(meta),
458
462
  metrics: Core::Utils::SafeDup.frozen_or_dup(metrics),
463
+ metastruct: Core::Utils::SafeDup.frozen_or_dup(metastruct),
459
464
  parent_id: @parent_id,
460
465
  resource: @resource,
461
466
  service: @service,
@@ -19,7 +19,8 @@ module Datadog
19
19
  attr_reader \
20
20
  :logger,
21
21
  :events,
22
- :transport
22
+ :transport,
23
+ :agent_settings
23
24
 
24
25
  # @param [Datadog::Tracing::Transport::Traces::Transport] transport a custom transport instance.
25
26
  # If provided, overrides `transport_options` and `agent_settings`.
@@ -28,9 +29,10 @@ module Datadog
28
29
  # the default transport instance.
29
30
  def initialize(transport: nil, transport_options: {}, agent_settings: nil, logger: Datadog.logger)
30
31
  @logger = logger
32
+ @agent_settings = agent_settings
31
33
 
32
34
  @transport = transport || begin
33
- transport_options[:agent_settings] = agent_settings if agent_settings
35
+ transport_options = transport_options.merge(agent_settings: agent_settings) if agent_settings
34
36
  Transport::HTTP.default(**transport_options)
35
37
  end
36
38
 
@@ -49,6 +49,8 @@ module Datadog
49
49
  # @param tags [Hash] default tags added to all spans
50
50
  # @param writer [Datadog::Tracing::Writer] consumes traces returned by the provided +trace_flush+
51
51
  def initialize(
52
+ # rubocop:disable Style/KeywordParametersOrder
53
+ # https://github.com/rubocop/rubocop/issues/13933
52
54
  trace_flush: Flush::Finished.new,
53
55
  context_provider: DefaultContextProvider.new,
54
56
  default_service: Core::Environment::Ext::FALLBACK_SERVICE_NAME,
@@ -60,7 +62,10 @@ module Datadog
60
62
  ),
61
63
  span_sampler: Sampling::Span::Sampler.new,
62
64
  tags: {},
63
- writer: Writer.new(logger: logger)
65
+ # writer is not defaulted because creating it requires agent_settings,
66
+ # which we do not have here and otherwise do not need.
67
+ writer:
68
+ # rubocop:enable Style/KeywordParametersOrder
64
69
  )
65
70
  @trace_flush = trace_flush
66
71
  @default_service = default_service
@@ -1,14 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'uri'
4
-
5
3
  require_relative '../../core/environment/container'
6
4
  require_relative '../../core/environment/ext'
7
5
  require_relative '../../core/transport/ext'
8
- require_relative '../../core/transport/http/adapters/net'
9
- require_relative '../../core/transport/http/adapters/test'
10
- require_relative '../../core/transport/http/adapters/unix_socket'
11
- require_relative '../../core/transport/http/builder'
6
+ require_relative '../../core/transport/http'
12
7
  require_relative 'http/api'
13
8
  require_relative '../../../datadog/version'
14
9
 
@@ -17,21 +12,11 @@ module Datadog
17
12
  module Transport
18
13
  # Namespace for HTTP transport components
19
14
  module HTTP
20
- # NOTE: Due to... legacy reasons... This class likes having a default `AgentSettings` instance to fall back to.
21
- # Because we generate this instance with an empty instance of `Settings`, the resulting `AgentSettings` below
22
- # represents only settings specified via environment variables + the usual defaults.
23
- #
24
- # DO NOT USE THIS IN NEW CODE, as it ignores any settings specified by users via `Datadog.configure`.
25
- DO_NOT_USE_ENVIRONMENT_AGENT_SETTINGS = Datadog::Core::Configuration::AgentSettingsResolver.call(
26
- Datadog::Core::Configuration::Settings.new,
27
- logger: nil,
28
- )
29
-
30
15
  module_function
31
16
 
32
17
  # Builds a new Transport::HTTP::Client
33
18
  def new(klass, &block)
34
- Core::Transport::HTTP::Builder.new(
19
+ Core::Transport::HTTP.build(
35
20
  api_instance_class: API::Instance, &block
36
21
  ).to_transport(klass)
37
22
  end
@@ -39,7 +24,7 @@ module Datadog
39
24
  # Builds a new Transport::HTTP::Client with default settings
40
25
  # Pass a block to override any settings.
41
26
  def default(
42
- agent_settings: DO_NOT_USE_ENVIRONMENT_AGENT_SETTINGS,
27
+ agent_settings:,
43
28
  **options
44
29
  )
45
30
  new(Transport::Traces::Transport) do |transport|
@@ -86,20 +71,6 @@ module Datadog
86
71
  def default_adapter
87
72
  Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
88
73
  end
89
-
90
- # Add adapters to registry
91
- Core::Transport::HTTP::Builder::REGISTRY.set(
92
- Datadog::Core::Transport::HTTP::Adapters::Net,
93
- Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
94
- )
95
- Core::Transport::HTTP::Builder::REGISTRY.set(
96
- Datadog::Core::Transport::HTTP::Adapters::Test,
97
- Datadog::Core::Transport::Ext::Test::ADAPTER
98
- )
99
- Core::Transport::HTTP::Builder::REGISTRY.set(
100
- Datadog::Core::Transport::HTTP::Adapters::UnixSocket,
101
- Datadog::Core::Transport::Ext::UnixSocket::ADAPTER
102
- )
103
74
  end
104
75
  end
105
76
  end
@@ -69,7 +69,7 @@ module Datadog
69
69
  def to_msgpack(packer = nil)
70
70
  packer ||= MessagePack::Packer.new
71
71
 
72
- number_of_elements_to_write = 11
72
+ number_of_elements_to_write = 12
73
73
 
74
74
  number_of_elements_to_write += 1 if span.events.any? && @native_events_supported
75
75
 
@@ -117,6 +117,8 @@ module Datadog
117
117
  packer.write(span.meta)
118
118
  packer.write('metrics')
119
119
  packer.write(span.metrics)
120
+ packer.write('meta_struct')
121
+ packer.write(span.metastruct)
120
122
  packer.write('span_links')
121
123
  packer.write(span.links.map(&:to_hash))
122
124
  packer.write('error')
@@ -18,7 +18,8 @@ module Datadog
18
18
  class TraceWriter < Core::Worker
19
19
  attr_reader \
20
20
  :logger,
21
- :transport
21
+ :transport,
22
+ :agent_settings
22
23
 
23
24
  # rubocop:disable Lint/MissingSuper
24
25
  def initialize(options = {})
@@ -26,7 +27,10 @@ module Datadog
26
27
 
27
28
  transport_options = options.fetch(:transport_options, {})
28
29
 
29
- transport_options[:agent_settings] = options[:agent_settings] if options.key?(:agent_settings)
30
+ if options.key?(:agent_settings)
31
+ @agent_settings = options[:agent_settings]
32
+ transport_options = transport_options.merge(agent_settings: @agent_settings)
33
+ end
30
34
 
31
35
  @transport = options.fetch(:transport) do
32
36
  Datadog::Tracing::Transport::HTTP.default(**transport_options)
@@ -16,7 +16,8 @@ module Datadog
16
16
  :logger,
17
17
  :transport,
18
18
  :worker,
19
- :events
19
+ :events,
20
+ :agent_settings
20
21
 
21
22
  def initialize(options = {})
22
23
  @logger = options[:logger] || Datadog.logger
@@ -26,7 +27,10 @@ module Datadog
26
27
  @flush_interval = options.fetch(:flush_interval, Workers::AsyncTransport::DEFAULT_FLUSH_INTERVAL)
27
28
  transport_options = options.fetch(:transport_options, {})
28
29
 
29
- transport_options[:agent_settings] = options[:agent_settings] if options.key?(:agent_settings)
30
+ if options.key?(:agent_settings)
31
+ @agent_settings = options[:agent_settings]
32
+ transport_options = transport_options.merge(agent_settings: @agent_settings)
33
+ end
30
34
 
31
35
  # transport and buffers
32
36
  @transport = options.fetch(:transport) do
@@ -4,7 +4,7 @@ module Datadog
4
4
  module VERSION
5
5
  MAJOR = 2
6
6
  MINOR = 12
7
- PATCH = 0
7
+ PATCH = 2
8
8
  PRE = nil
9
9
  BUILD = nil
10
10
  # PRE and BUILD above are modified for dev gems during gem build GHA workflow
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datadog
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.12.0
4
+ version: 2.12.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Datadog, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-02-27 00:00:00.000000000 Z
11
+ date: 2025-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -226,6 +226,7 @@ files:
226
226
  - lib/datadog/appsec/instrumentation.rb
227
227
  - lib/datadog/appsec/instrumentation/gateway.rb
228
228
  - lib/datadog/appsec/instrumentation/gateway/argument.rb
229
+ - lib/datadog/appsec/instrumentation/gateway/middleware.rb
229
230
  - lib/datadog/appsec/metrics.rb
230
231
  - lib/datadog/appsec/metrics/collector.rb
231
232
  - lib/datadog/appsec/metrics/exporter.rb
@@ -342,6 +343,7 @@ files:
342
343
  - lib/datadog/core/telemetry/request.rb
343
344
  - lib/datadog/core/telemetry/worker.rb
344
345
  - lib/datadog/core/transport/ext.rb
346
+ - lib/datadog/core/transport/http.rb
345
347
  - lib/datadog/core/transport/http/adapters/net.rb
346
348
  - lib/datadog/core/transport/http/adapters/registry.rb
347
349
  - lib/datadog/core/transport/http/adapters/test.rb
@@ -875,6 +877,8 @@ files:
875
877
  - lib/datadog/tracing/metadata/analytics.rb
876
878
  - lib/datadog/tracing/metadata/errors.rb
877
879
  - lib/datadog/tracing/metadata/ext.rb
880
+ - lib/datadog/tracing/metadata/metastruct.rb
881
+ - lib/datadog/tracing/metadata/metastruct_tagging.rb
878
882
  - lib/datadog/tracing/metadata/tagging.rb
879
883
  - lib/datadog/tracing/pipeline.rb
880
884
  - lib/datadog/tracing/pipeline/span_filter.rb
@@ -929,8 +933,8 @@ licenses:
929
933
  - Apache-2.0
930
934
  metadata:
931
935
  allowed_push_host: https://rubygems.org
932
- changelog_uri: https://github.com/DataDog/dd-trace-rb/blob/v2.12.0/CHANGELOG.md
933
- source_code_uri: https://github.com/DataDog/dd-trace-rb/tree/v2.12.0
936
+ changelog_uri: https://github.com/DataDog/dd-trace-rb/blob/v2.12.2/CHANGELOG.md
937
+ source_code_uri: https://github.com/DataDog/dd-trace-rb/tree/v2.12.2
934
938
  post_install_message:
935
939
  rdoc_options: []
936
940
  require_paths: