ddtrace 1.21.0 → 1.22.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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +57 -2
  3. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +32 -12
  4. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +5 -2
  5. data/ext/datadog_profiling_native_extension/heap_recorder.c +45 -3
  6. data/ext/datadog_profiling_native_extension/heap_recorder.h +7 -1
  7. data/ext/datadog_profiling_native_extension/http_transport.c +5 -5
  8. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +1 -1
  9. data/ext/datadog_profiling_native_extension/stack_recorder.c +7 -9
  10. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +43 -13
  11. data/lib/datadog/appsec/event.rb +1 -1
  12. data/lib/datadog/auto_instrument.rb +3 -0
  13. data/lib/datadog/core/configuration/components.rb +2 -1
  14. data/lib/datadog/core/configuration/option.rb +7 -5
  15. data/lib/datadog/core/configuration/settings.rb +38 -17
  16. data/lib/datadog/core/configuration.rb +20 -4
  17. data/lib/datadog/core/environment/platform.rb +7 -1
  18. data/lib/datadog/core/remote/client/capabilities.rb +1 -1
  19. data/lib/datadog/core/remote/transport/http/config.rb +1 -1
  20. data/lib/datadog/core/telemetry/client.rb +18 -10
  21. data/lib/datadog/core/telemetry/emitter.rb +9 -13
  22. data/lib/datadog/core/telemetry/event.rb +247 -57
  23. data/lib/datadog/core/telemetry/ext.rb +1 -0
  24. data/lib/datadog/core/telemetry/heartbeat.rb +1 -3
  25. data/lib/datadog/core/telemetry/http/ext.rb +4 -1
  26. data/lib/datadog/core/telemetry/http/transport.rb +9 -4
  27. data/lib/datadog/core/telemetry/request.rb +59 -0
  28. data/lib/datadog/profiling/collectors/code_provenance.rb +10 -4
  29. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +25 -0
  30. data/lib/datadog/profiling/component.rb +23 -15
  31. data/lib/datadog/profiling/load_native_extension.rb +14 -1
  32. data/lib/datadog/profiling.rb +11 -0
  33. data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +1 -1
  34. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +11 -4
  35. data/lib/datadog/tracing/contrib/configurable.rb +1 -1
  36. data/lib/datadog/tracing/contrib/grape/endpoint.rb +0 -5
  37. data/lib/datadog/tracing/contrib/rack/middlewares.rb +4 -28
  38. data/lib/datadog/tracing/contrib/rails/patcher.rb +0 -16
  39. data/lib/datadog/tracing/contrib/sinatra/tracer.rb +3 -6
  40. data/lib/datadog/tracing/metadata/ext.rb +0 -2
  41. data/lib/datadog/tracing/sampling/matcher.rb +23 -3
  42. data/lib/datadog/tracing/sampling/rule.rb +7 -2
  43. data/lib/datadog/tracing/sampling/rule_sampler.rb +2 -0
  44. data/lib/ddtrace/version.rb +1 -1
  45. metadata +10 -20
  46. data/lib/datadog/core/telemetry/collector.rb +0 -250
  47. data/lib/datadog/core/telemetry/v1/app_event.rb +0 -59
  48. data/lib/datadog/core/telemetry/v1/application.rb +0 -92
  49. data/lib/datadog/core/telemetry/v1/configuration.rb +0 -25
  50. data/lib/datadog/core/telemetry/v1/dependency.rb +0 -43
  51. data/lib/datadog/core/telemetry/v1/host.rb +0 -59
  52. data/lib/datadog/core/telemetry/v1/install_signature.rb +0 -38
  53. data/lib/datadog/core/telemetry/v1/integration.rb +0 -64
  54. data/lib/datadog/core/telemetry/v1/product.rb +0 -36
  55. data/lib/datadog/core/telemetry/v1/telemetry_request.rb +0 -106
  56. data/lib/datadog/core/telemetry/v2/app_client_configuration_change.rb +0 -41
  57. data/lib/datadog/core/telemetry/v2/request.rb +0 -29
@@ -39,10 +39,15 @@ module Datadog
39
39
 
40
40
  def headers(request_type:, api_version: Http::Ext::API_VERSION)
41
41
  {
42
- Datadog::Core::Transport::Ext::HTTP::HEADER_DD_INTERNAL_UNTRACED_REQUEST => '1',
43
- Http::Ext::HEADER_CONTENT_TYPE => Http::Ext::CONTENT_TYPE_APPLICATION_JSON,
44
- Http::Ext::HEADER_DD_TELEMETRY_API_VERSION => api_version,
45
- Http::Ext::HEADER_DD_TELEMETRY_REQUEST_TYPE => request_type,
42
+ Core::Transport::Ext::HTTP::HEADER_DD_INTERNAL_UNTRACED_REQUEST => '1',
43
+ Ext::HEADER_CONTENT_TYPE => Http::Ext::CONTENT_TYPE_APPLICATION_JSON,
44
+ Ext::HEADER_DD_TELEMETRY_API_VERSION => api_version,
45
+ Ext::HEADER_DD_TELEMETRY_REQUEST_TYPE => request_type,
46
+ Ext::HEADER_CLIENT_LIBRARY_LANGUAGE => Core::Environment::Ext::LANG,
47
+ Ext::HEADER_CLIENT_LIBRARY_VERSION => DDTrace::VERSION::STRING,
48
+
49
+ # Enable debug mode for telemetry
50
+ # HEADER_TELEMETRY_DEBUG_ENABLED => 'true',
46
51
  }
47
52
  end
48
53
 
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../environment/platform'
4
+ require_relative '../utils/hash'
5
+
6
+ module Datadog
7
+ module Core
8
+ module Telemetry
9
+ # Module defining methods for collecting metadata for telemetry
10
+ module Request
11
+ class << self
12
+ using Core::Utils::Hash::Refinement
13
+
14
+ def build_payload(event, seq_id)
15
+ hash = {
16
+ api_version: Http::Ext::API_VERSION,
17
+ application: application,
18
+ debug: false,
19
+ host: host,
20
+ payload: event.payload(seq_id),
21
+ request_type: event.type,
22
+ runtime_id: Core::Environment::Identity.id,
23
+ seq_id: seq_id,
24
+ tracer_time: Time.now.to_i,
25
+ }
26
+ hash.compact!
27
+ hash
28
+ end
29
+
30
+ private
31
+
32
+ def application
33
+ config = Datadog.configuration
34
+ {
35
+ env: config.env,
36
+ language_name: Core::Environment::Ext::LANG,
37
+ language_version: Core::Environment::Ext::LANG_VERSION,
38
+ runtime_name: Core::Environment::Ext::RUBY_ENGINE,
39
+ runtime_version: Core::Environment::Ext::ENGINE_VERSION,
40
+ service_name: config.service,
41
+ service_version: config.version,
42
+ tracer_version: Core::Environment::Identity.tracer_version
43
+ }
44
+ end
45
+
46
+ def host
47
+ {
48
+ architecture: Core::Environment::Platform.architecture,
49
+ hostname: Core::Environment::Platform.hostname,
50
+ kernel_name: Core::Environment::Platform.kernel_name,
51
+ kernel_release: Core::Environment::Platform.kernel_release,
52
+ kernel_version: Core::Environment::Platform.kernel_version
53
+ }
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -97,14 +97,20 @@ module Datadog
97
97
  end
98
98
  end
99
99
 
100
- Library = Struct.new(:kind, :name, :version, :path) do
100
+ # Represents metadata we have for a ruby gem
101
+ class Library
102
+ attr_reader :kind, :name, :version, :path
103
+
101
104
  def initialize(kind:, name:, version:, path:)
102
- super(kind.freeze, name.dup.freeze, version.to_s.dup.freeze, path.dup.freeze)
105
+ @kind = kind.freeze
106
+ @name = name.dup.freeze
107
+ @version = version.to_s.dup.freeze
108
+ @path = path.dup.freeze
103
109
  freeze
104
110
  end
105
111
 
106
- def to_json(*args)
107
- { kind: kind, name: name, version: version, paths: [path] }.to_json(*args)
112
+ def to_json(arg = nil)
113
+ { kind: @kind, name: @name, version: @version, paths: [@path] }.to_json(arg)
108
114
  end
109
115
  end
110
116
  end
@@ -22,6 +22,7 @@ module Datadog
22
22
  # **NOTE**: This should only be used for testing; disabling the dynamic sampling rate will increase the
23
23
  # profiler overhead!
24
24
  dynamic_sampling_rate_enabled: true,
25
+ skip_idle_samples_for_testing: false,
25
26
  idle_sampling_helper: IdleSamplingHelper.new
26
27
  )
27
28
  unless dynamic_sampling_rate_enabled
@@ -39,11 +40,14 @@ module Datadog
39
40
  dynamic_sampling_rate_enabled,
40
41
  dynamic_sampling_rate_overhead_target_percentage,
41
42
  allocation_profiling_enabled,
43
+ skip_idle_samples_for_testing,
42
44
  )
43
45
  @worker_thread = nil
44
46
  @failure_exception = nil
45
47
  @start_stop_mutex = Mutex.new
46
48
  @idle_sampling_helper = idle_sampling_helper
49
+ @wait_until_running_mutex = Mutex.new
50
+ @wait_until_running_condition = ConditionVariable.new
47
51
  end
48
52
 
49
53
  def start(on_failure_proc: nil)
@@ -106,6 +110,27 @@ module Datadog
106
110
  self.class._native_stats_reset_not_thread_safe(self)
107
111
  stats
108
112
  end
113
+
114
+ # Useful for testing, to e.g. make sure the profiler is running before we start running some code we want to observe
115
+ def wait_until_running(timeout_seconds: 5)
116
+ @wait_until_running_mutex.synchronize do
117
+ return true if self.class._native_is_running?(self)
118
+
119
+ @wait_until_running_condition.wait(@wait_until_running_mutex, timeout_seconds)
120
+
121
+ if self.class._native_is_running?(self)
122
+ true
123
+ else
124
+ raise "Timeout waiting for #{self.class.name} to start (waited for #{timeout_seconds} seconds)"
125
+ end
126
+ end
127
+ end
128
+
129
+ private
130
+
131
+ def signal_running
132
+ @wait_until_running_mutex.synchronize { @wait_until_running_condition.broadcast }
133
+ end
109
134
  end
110
135
  end
111
136
  end
@@ -111,19 +111,30 @@ module Datadog
111
111
  end
112
112
 
113
113
  private_class_method def self.enable_gc_profiling?(settings)
114
- # See comments on the setting definition for more context on why it exists.
115
- if settings.profiling.advanced.force_enable_gc_profiling
116
- if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3')
117
- Datadog.logger.debug(
118
- 'Profiling time/resources spent in Garbage Collection force enabled. Do not use Ractors in combination ' \
119
- 'with this option as profiles will be incomplete.'
120
- )
121
- end
114
+ return false unless settings.profiling.advanced.gc_enabled
122
115
 
123
- true
124
- else
125
- false
116
+ # SEVERE - Only with Ractors
117
+ # On Ruby versions 3.0 (all), 3.1.0 to 3.1.3, and 3.2.0 to 3.2.2 gc profiling can trigger a VM bug
118
+ # that causes a segmentation fault during garbage collection of Ractors
119
+ # (https://bugs.ruby-lang.org/issues/18464). We don't allow enabling gc profiling on such Rubies.
120
+ # This bug is fixed on Ruby versions 3.1.4, 3.2.3 and 3.3.0.
121
+ if RUBY_VERSION.start_with?('3.0.') ||
122
+ (RUBY_VERSION.start_with?('3.1.') && RUBY_VERSION < '3.1.4') ||
123
+ (RUBY_VERSION.start_with?('3.2.') && RUBY_VERSION < '3.2.3')
124
+ Datadog.logger.warn(
125
+ "Current Ruby version (#{RUBY_VERSION}) has a VM bug where enabling GC profiling would cause "\
126
+ 'crashes (https://bugs.ruby-lang.org/issues/18464). GC profiling has been disabled.'
127
+ )
128
+ return false
129
+ elsif RUBY_VERSION.start_with?('3.')
130
+ Datadog.logger.debug(
131
+ 'In all known versions of Ruby 3.x, using Ractors may result in GC profiling unexpectedly ' \
132
+ 'stopping (https://bugs.ruby-lang.org/issues/19112). Note that this stop has no impact in your ' \
133
+ 'application stability or performance. This does not happen if Ractors are not used.'
134
+ )
126
135
  end
136
+
137
+ true
127
138
  end
128
139
 
129
140
  private_class_method def self.get_heap_sample_every(settings)
@@ -135,10 +146,7 @@ module Datadog
135
146
  end
136
147
 
137
148
  private_class_method def self.enable_allocation_profiling?(settings)
138
- unless settings.profiling.allocation_enabled
139
- # Allocation profiling disabled, short-circuit out
140
- return false
141
- end
149
+ return false unless settings.profiling.allocation_enabled
142
150
 
143
151
  # Allocation sampling is safe and supported on Ruby 2.x, but has a few caveats on Ruby 3.x.
144
152
 
@@ -18,7 +18,20 @@ rescue LoadError => e
18
18
  end
19
19
 
20
20
  extension_name = "datadog_profiling_native_extension.#{RUBY_VERSION}_#{RUBY_PLATFORM}"
21
- full_file_path = "#{__dir__}/../../#{extension_name}.#{RbConfig::CONFIG['DLEXT']}"
21
+ file_name = "#{extension_name}.#{RbConfig::CONFIG['DLEXT']}"
22
+ full_file_path = "#{__dir__}/../../#{file_name}"
23
+
24
+ unless File.exist?(full_file_path)
25
+ extension_dir = Gem.loaded_specs['ddtrace'].extension_dir
26
+ candidate_path = "#{extension_dir}/#{file_name}"
27
+ if File.exist?(candidate_path)
28
+ full_file_path = candidate_path
29
+ else # rubocop:disable Style/EmptyElse
30
+ # We found none of the files. This is unexpected. Let's go ahead anyway, the error is going to be reported further
31
+ # down anyway.
32
+ end
33
+ end
34
+
22
35
  init_function_name = "Init_#{extension_name.split('.').first}"
23
36
 
24
37
  status, result = Datadog::Profiling::Loader._native_load(full_file_path, init_function_name)
@@ -63,6 +63,17 @@ module Datadog
63
63
  !!(profiler.send(:scheduler).running? if profiler)
64
64
  end
65
65
 
66
+ def self.wait_until_running(timeout_seconds: 5)
67
+ profiler = Datadog.send(:components).profiler
68
+ if profiler
69
+ # Use .send(...) to avoid exposing the attr_reader as an API to the outside
70
+ worker = profiler.send(:worker)
71
+ worker.wait_until_running(timeout_seconds: timeout_seconds)
72
+ else
73
+ raise 'Profiler not enabled or available'
74
+ end
75
+ end
76
+
66
77
  private_class_method def self.replace_noop_allocation_count
67
78
  def self.allocation_count # rubocop:disable Lint/NestedMethodDefinition (On purpose!)
68
79
  Datadog::Profiling::Collectors::CpuAndWallTimeWorker._native_allocation_count
@@ -37,7 +37,7 @@ module Datadog
37
37
 
38
38
  span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_DELIVER)
39
39
 
40
- # Since email date can contain PII we disable by default
40
+ # Since email data can contain PII we disable by default
41
41
  # Some of these fields can be either strings or arrays, so we try to normalize
42
42
  # https://github.com/rails/rails/blob/18707ab17fa492eb25ad2e8f9818a320dc20b823/actionmailer/lib/action_mailer/base.rb#L742-L754
43
43
  if configuration[:email_data] == true
@@ -65,9 +65,14 @@ module Datadog
65
65
 
66
66
  config
67
67
  rescue => e
68
+ # Resolving a valid database configuration should not raise an exception,
69
+ # but if it does, it can be due to adding a broken pattern match prior to this call.
70
+ #
71
+ # `db_config` input may contain sensitive information such as passwords,
72
+ # hence provide a succinct summary for the error logging.
68
73
  Datadog.logger.error(
69
- "Failed to resolve ActiveRecord configuration key #{db_config.inspect}. " \
70
- "Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
74
+ 'Failed to resolve ActiveRecord database configuration. '\
75
+ "Cause: #{e.class.name} Source: #{Array(e.backtrace).first}"
71
76
  )
72
77
 
73
78
  nil
@@ -85,9 +90,11 @@ module Datadog
85
90
  normalized
86
91
  rescue => e
87
92
  Datadog.logger.error(
88
- "Failed to resolve ActiveRecord configuration key #{matcher.inspect}. " \
89
- "Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
93
+ "Failed to resolve key #{matcher.inspect}. " \
94
+ "Cause: #{e.class.name} Source: #{Array(e.backtrace).first}"
90
95
  )
96
+
97
+ nil
91
98
  end
92
99
 
93
100
  #
@@ -50,7 +50,7 @@ module Datadog
50
50
  end
51
51
 
52
52
  # Apply the settings
53
- config.configure(options, &block)
53
+ config.configure(options, &block) if config
54
54
  config
55
55
  end
56
56
 
@@ -94,8 +94,6 @@ module Datadog
94
94
 
95
95
  span.set_error(payload[:exception_object]) if exception_is_error?(payload[:exception_object])
96
96
 
97
- integration_route = endpoint.env['grape.routing_args'][:route_info].pattern.origin
98
-
99
97
  # override the current span with this notification values
100
98
  span.set_tag(Ext::TAG_ROUTE_ENDPOINT, api_view) unless api_view.nil?
101
99
  span.set_tag(Ext::TAG_ROUTE_PATH, path)
@@ -103,9 +101,6 @@ module Datadog
103
101
 
104
102
  span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_METHOD, request_method)
105
103
  span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_URL, path)
106
-
107
- trace.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE, integration_route)
108
- trace.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH, endpoint.env['SCRIPT_NAME'])
109
104
  ensure
110
105
  span.start(start)
111
106
  span.finish(finish)
@@ -66,10 +66,6 @@ module Datadog
66
66
  end
67
67
  end
68
68
 
69
- # rubocop:disable Metrics/CyclomaticComplexity
70
- # rubocop:disable Metrics/PerceivedComplexity
71
- # rubocop:disable Metrics/MethodLength
72
- # rubocop:disable Metrics/AbcSize
73
69
  def call(env)
74
70
  # Find out if this is rack within rack
75
71
  previous_request_span = env[Ext::RACK_ENV_REQUEST_SPAN]
@@ -111,30 +107,6 @@ module Datadog
111
107
 
112
108
  # call the rest of the stack
113
109
  status, headers, response = @app.call(env)
114
-
115
- if status != 404 && (last_route = request_trace.get_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE))
116
- last_script_name = request_trace.get_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH)
117
-
118
- # If the last_script_name is empty but the env['SCRIPT_NAME'] is NOT empty
119
- # then the current rack request was not routed and must be accounted for
120
- # which only happens in pure nested rack requests i.e /rack/rack/hello/world
121
- #
122
- # To account for the unaccounted nested rack requests of /rack/hello/world,
123
- # we use 'PATH_INFO knowing that rack cannot have named parameters
124
- if last_script_name == '' && env['SCRIPT_NAME'] != ''
125
- last_script_name = last_route
126
- last_route = env['PATH_INFO']
127
- end
128
-
129
- # Clear the route and route path tags from the request trace to avoid possibility of misplacement
130
- request_trace.clear_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE)
131
- request_trace.clear_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH)
132
-
133
- # Ensure tags are placed in rack.request span as desired
134
- request_span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE, last_script_name + last_route)
135
- request_span.clear_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH)
136
- end
137
-
138
110
  [status, headers, response]
139
111
 
140
112
  # rubocop:disable Lint/RescueException
@@ -170,6 +142,10 @@ module Datadog
170
142
  end
171
143
  # rubocop:enable Lint/RescueException
172
144
 
145
+ # rubocop:disable Metrics/AbcSize
146
+ # rubocop:disable Metrics/CyclomaticComplexity
147
+ # rubocop:disable Metrics/PerceivedComplexity
148
+ # rubocop:disable Metrics/MethodLength
173
149
  def set_request_tags!(trace, request_span, env, status, headers, response, original_env)
174
150
  request_header_collection = Header::RequestHeaderCollection.new(env)
175
151
 
@@ -5,24 +5,11 @@ require_relative 'log_injection'
5
5
  require_relative 'middlewares'
6
6
  require_relative 'utils'
7
7
  require_relative '../semantic_logger/patcher'
8
- require_relative 'ext'
9
8
 
10
9
  module Datadog
11
10
  module Tracing
12
11
  module Contrib
13
12
  module Rails
14
- # Patcher to trace rails routing done by JourneyRouter
15
- module JourneyRouterPatch
16
- def find_routes(*args)
17
- result = super
18
- integration_route = result.first[2].path.spec.to_s.gsub(/\(\.:format\)/, '') if result.any?
19
- request_trace = Tracing.active_trace || TraceOperation.new
20
- request_trace.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE, integration_route)
21
- request_trace.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH, args.first.env['SCRIPT_NAME'])
22
- result
23
- end
24
- end
25
-
26
13
  # Patcher enables patching of 'rails' module.
27
14
  module Patcher
28
15
  include Contrib::Patcher
@@ -54,9 +41,6 @@ module Datadog
54
41
  # Sometimes we don't want to activate middleware e.g. OpenTracing, etc.
55
42
  add_middleware(app) if Datadog.configuration.tracing[:rails][:middleware]
56
43
 
57
- # ActionDispatch::Journey is not available or incompatible in Rails < 4.2.
58
- ActionDispatch::Journey::Router.prepend(JourneyRouterPatch) if Integration.version >= Gem::Version.new('4.2')
59
-
60
44
  Rails::LogInjection.configure_log_tags(app.config)
61
45
  end
62
46
  end
@@ -47,16 +47,16 @@ module Datadog
47
47
  configuration = Datadog.configuration.tracing[:sinatra]
48
48
  return super unless Tracing.enabled?
49
49
 
50
- integration_route = Sinatra::Env.route_path(env)
50
+ datadog_route = Sinatra::Env.route_path(env)
51
51
 
52
52
  Tracing.trace(
53
53
  Ext::SPAN_ROUTE,
54
54
  service: configuration[:service_name],
55
55
  span_type: Tracing::Metadata::Ext::HTTP::TYPE_INBOUND,
56
- resource: "#{request.request_method} #{integration_route}",
56
+ resource: "#{request.request_method} #{datadog_route}",
57
57
  ) do |span, trace|
58
58
  span.set_tag(Ext::TAG_APP_NAME, settings.name || settings.superclass.name)
59
- span.set_tag(Ext::TAG_ROUTE_PATH, integration_route)
59
+ span.set_tag(Ext::TAG_ROUTE_PATH, datadog_route)
60
60
 
61
61
  if request.script_name && !request.script_name.empty?
62
62
  span.set_tag(Ext::TAG_SCRIPT_NAME, request.script_name)
@@ -73,9 +73,6 @@ module Datadog
73
73
 
74
74
  Contrib::Analytics.set_measured(span)
75
75
 
76
- _, path = env['sinatra.route'].split(' ', 2)
77
- trace.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE, path)
78
- trace.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH, env['SCRIPT_NAME'])
79
76
  super
80
77
  end
81
78
  end
@@ -86,8 +86,6 @@ module Datadog
86
86
  TYPE_TEMPLATE = 'template'
87
87
  TAG_CLIENT_IP = 'http.client_ip'
88
88
  HEADER_USER_AGENT = 'User-Agent'
89
- TAG_ROUTE = 'http.route'
90
- TAG_ROUTE_PATH = 'http.route.path'
91
89
 
92
90
  # General header functionality
93
91
  module Headers
@@ -29,20 +29,40 @@ module Datadog
29
29
  end
30
30
  end.new
31
31
 
32
- attr_reader :name, :service
32
+ attr_reader :name, :service, :resource, :tags
33
33
 
34
34
  # @param name [String,Regexp,Proc] Matcher for case equality (===) with the trace name,
35
35
  # defaults to always match
36
36
  # @param service [String,Regexp,Proc] Matcher for case equality (===) with the service name,
37
37
  # defaults to always match
38
- def initialize(name: MATCH_ALL, service: MATCH_ALL)
38
+ # @param resource [String,Regexp,Proc] Matcher for case equality (===) with the resource name,
39
+ # defaults to always match
40
+ def initialize(name: MATCH_ALL, service: MATCH_ALL, resource: MATCH_ALL, tags: {})
39
41
  super()
40
42
  @name = name
41
43
  @service = service
44
+ @resource = resource
45
+ @tags = tags
42
46
  end
43
47
 
44
48
  def match?(trace)
45
- name === trace.name && service === trace.service
49
+ name === trace.name && service === trace.service && resource === trace.resource && tags_match?(trace)
50
+ end
51
+
52
+ private
53
+
54
+ # Match against the trace tags and metrics.
55
+ def tags_match?(trace)
56
+ @tags.all? do |name, matcher|
57
+ tag = trace.get_tag(name)
58
+
59
+ # Format metrics as strings, to allow for partial number matching (/4.*/ matching '400', '404', etc.).
60
+ # Because metrics are floats, we use the '%g' format specifier to avoid trailing zeros, which
61
+ # can affect exact string matching (e.g. '400' matching '400.0').
62
+ tag = format('%g', tag) if tag.is_a?(Numeric)
63
+
64
+ matcher === tag
65
+ end
46
66
  end
47
67
  end
48
68
 
@@ -51,8 +51,13 @@ module Datadog
51
51
  # @param name [String,Regexp,Proc] Matcher for case equality (===) with the trace name, defaults to always match
52
52
  # @param service [String,Regexp,Proc] Matcher for case equality (===) with the service name,
53
53
  # defaults to always match
54
+ # @param resource [String,Regexp,Proc] Matcher for case equality (===) with the resource name,
55
+ # defaults to always match
54
56
  # @param sample_rate [Float] Sampling rate between +[0,1]+
55
- def initialize(name: SimpleMatcher::MATCH_ALL, service: SimpleMatcher::MATCH_ALL, sample_rate: 1.0)
57
+ def initialize(
58
+ name: SimpleMatcher::MATCH_ALL, service: SimpleMatcher::MATCH_ALL,
59
+ resource: SimpleMatcher::MATCH_ALL, tags: {}, sample_rate: 1.0
60
+ )
56
61
  # We want to allow 0.0 to drop all traces, but {Datadog::Tracing::Sampling::RateSampler}
57
62
  # considers 0.0 an invalid rate and falls back to 100% sampling.
58
63
  #
@@ -64,7 +69,7 @@ module Datadog
64
69
  sampler = RateSampler.new
65
70
  sampler.sample_rate = sample_rate
66
71
 
67
- super(SimpleMatcher.new(name: name, service: service), sampler)
72
+ super(SimpleMatcher.new(name: name, service: service, resource: resource, tags: tags), sampler)
68
73
  end
69
74
  end
70
75
  end
@@ -61,6 +61,8 @@ module Datadog
61
61
  kwargs = {
62
62
  name: rule['name'],
63
63
  service: rule['service'],
64
+ resource: rule['resource'],
65
+ tags: rule['tags'],
64
66
  sample_rate: sample_rate,
65
67
  }
66
68
 
@@ -3,7 +3,7 @@
3
3
  module DDTrace
4
4
  module VERSION
5
5
  MAJOR = 1
6
- MINOR = 21
6
+ MINOR = 22
7
7
  PATCH = 0
8
8
  PRE = nil
9
9
  BUILD = nil
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ddtrace
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.21.0
4
+ version: 1.22.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Datadog, Inc.
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-14 00:00:00.000000000 Z
11
+ date: 2024-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 6.0.0.2.0
61
+ version: 7.0.0.1.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 6.0.0.2.0
68
+ version: 7.0.0.1.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: datadog-ci
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -221,6 +221,7 @@ files:
221
221
  - lib/datadog/appsec/utils/http.rb
222
222
  - lib/datadog/appsec/utils/http/media_range.rb
223
223
  - lib/datadog/appsec/utils/http/media_type.rb
224
+ - lib/datadog/auto_instrument.rb
224
225
  - lib/datadog/core.rb
225
226
  - lib/datadog/core/backport.rb
226
227
  - lib/datadog/core/buffer/cruby.rb
@@ -295,7 +296,6 @@ files:
295
296
  - lib/datadog/core/runtime/ext.rb
296
297
  - lib/datadog/core/runtime/metrics.rb
297
298
  - lib/datadog/core/telemetry/client.rb
298
- - lib/datadog/core/telemetry/collector.rb
299
299
  - lib/datadog/core/telemetry/emitter.rb
300
300
  - lib/datadog/core/telemetry/event.rb
301
301
  - lib/datadog/core/telemetry/ext.rb
@@ -305,17 +305,7 @@ files:
305
305
  - lib/datadog/core/telemetry/http/ext.rb
306
306
  - lib/datadog/core/telemetry/http/response.rb
307
307
  - lib/datadog/core/telemetry/http/transport.rb
308
- - lib/datadog/core/telemetry/v1/app_event.rb
309
- - lib/datadog/core/telemetry/v1/application.rb
310
- - lib/datadog/core/telemetry/v1/configuration.rb
311
- - lib/datadog/core/telemetry/v1/dependency.rb
312
- - lib/datadog/core/telemetry/v1/host.rb
313
- - lib/datadog/core/telemetry/v1/install_signature.rb
314
- - lib/datadog/core/telemetry/v1/integration.rb
315
- - lib/datadog/core/telemetry/v1/product.rb
316
- - lib/datadog/core/telemetry/v1/telemetry_request.rb
317
- - lib/datadog/core/telemetry/v2/app_client_configuration_change.rb
318
- - lib/datadog/core/telemetry/v2/request.rb
308
+ - lib/datadog/core/telemetry/request.rb
319
309
  - lib/datadog/core/transport/ext.rb
320
310
  - lib/datadog/core/transport/http/adapters/net.rb
321
311
  - lib/datadog/core/transport/http/adapters/registry.rb
@@ -889,7 +879,7 @@ licenses:
889
879
  metadata:
890
880
  allowed_push_host: https://rubygems.org
891
881
  changelog_uri: https://github.com/DataDog/dd-trace-rb/blob/master/CHANGELOG.md
892
- post_install_message:
882
+ post_install_message:
893
883
  rdoc_options: []
894
884
  require_paths:
895
885
  - lib
@@ -907,8 +897,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
907
897
  - !ruby/object:Gem::Version
908
898
  version: 2.0.0
909
899
  requirements: []
910
- rubygems_version: 3.4.10
911
- signing_key:
900
+ rubygems_version: 3.5.3
901
+ signing_key:
912
902
  specification_version: 4
913
903
  summary: Datadog tracing code for your Ruby applications
914
904
  test_files: []