datadog 2.3.0 → 2.4.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 (129) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -1
  3. data/ext/datadog_profiling_loader/datadog_profiling_loader.c +9 -1
  4. data/ext/datadog_profiling_loader/extconf.rb +10 -22
  5. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +148 -30
  6. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +4 -2
  7. data/ext/datadog_profiling_native_extension/collectors_stack.c +89 -46
  8. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +580 -29
  9. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +9 -1
  10. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +0 -27
  11. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +0 -4
  12. data/ext/datadog_profiling_native_extension/extconf.rb +38 -21
  13. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +50 -0
  14. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +75 -0
  15. data/ext/datadog_profiling_native_extension/heap_recorder.c +20 -6
  16. data/ext/datadog_profiling_native_extension/http_transport.c +38 -6
  17. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +52 -1
  18. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +3 -0
  19. data/ext/datadog_profiling_native_extension/profiling.c +1 -1
  20. data/ext/datadog_profiling_native_extension/stack_recorder.h +1 -0
  21. data/ext/libdatadog_api/crashtracker.c +20 -18
  22. data/ext/libdatadog_api/datadog_ruby_common.c +0 -27
  23. data/ext/libdatadog_api/datadog_ruby_common.h +0 -4
  24. data/ext/libdatadog_extconf_helpers.rb +1 -1
  25. data/lib/datadog/appsec/assets/waf_rules/recommended.json +2184 -108
  26. data/lib/datadog/appsec/assets/waf_rules/strict.json +1430 -2
  27. data/lib/datadog/appsec/component.rb +29 -8
  28. data/lib/datadog/appsec/configuration/settings.rb +2 -2
  29. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +1 -0
  30. data/lib/datadog/appsec/contrib/devise/patcher/rememberable_patch.rb +21 -0
  31. data/lib/datadog/appsec/contrib/devise/patcher.rb +12 -2
  32. data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +0 -14
  33. data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +67 -31
  34. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +18 -15
  35. data/lib/datadog/appsec/contrib/graphql/integration.rb +14 -1
  36. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +2 -5
  37. data/lib/datadog/appsec/event.rb +1 -1
  38. data/lib/datadog/appsec/processor/rule_loader.rb +3 -1
  39. data/lib/datadog/appsec/processor/rule_merger.rb +33 -15
  40. data/lib/datadog/appsec/processor.rb +36 -37
  41. data/lib/datadog/appsec/rate_limiter.rb +25 -40
  42. data/lib/datadog/appsec/remote.rb +7 -3
  43. data/lib/datadog/appsec.rb +2 -2
  44. data/lib/datadog/core/configuration/components.rb +4 -3
  45. data/lib/datadog/core/configuration/settings.rb +84 -5
  46. data/lib/datadog/core/crashtracking/component.rb +1 -1
  47. data/lib/datadog/core/environment/execution.rb +5 -5
  48. data/lib/datadog/core/metrics/client.rb +7 -0
  49. data/lib/datadog/core/rate_limiter.rb +183 -0
  50. data/lib/datadog/core/remote/client/capabilities.rb +4 -3
  51. data/lib/datadog/core/remote/component.rb +4 -2
  52. data/lib/datadog/core/remote/negotiation.rb +4 -4
  53. data/lib/datadog/core/remote/tie.rb +2 -0
  54. data/lib/datadog/core/runtime/metrics.rb +1 -1
  55. data/lib/datadog/core/telemetry/component.rb +2 -0
  56. data/lib/datadog/core/telemetry/event.rb +12 -7
  57. data/lib/datadog/core/telemetry/logger.rb +51 -0
  58. data/lib/datadog/core/telemetry/logging.rb +50 -14
  59. data/lib/datadog/core/telemetry/request.rb +13 -1
  60. data/lib/datadog/core/utils/time.rb +12 -0
  61. data/lib/datadog/di/code_tracker.rb +168 -0
  62. data/lib/datadog/di/configuration/settings.rb +163 -0
  63. data/lib/datadog/di/configuration.rb +11 -0
  64. data/lib/datadog/di/error.rb +31 -0
  65. data/lib/datadog/di/extensions.rb +16 -0
  66. data/lib/datadog/di/probe.rb +133 -0
  67. data/lib/datadog/di/probe_builder.rb +41 -0
  68. data/lib/datadog/di/redactor.rb +188 -0
  69. data/lib/datadog/di/serializer.rb +193 -0
  70. data/lib/datadog/di.rb +14 -0
  71. data/lib/datadog/opentelemetry/sdk/propagator.rb +2 -0
  72. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +12 -10
  73. data/lib/datadog/profiling/collectors/info.rb +12 -3
  74. data/lib/datadog/profiling/collectors/thread_context.rb +26 -0
  75. data/lib/datadog/profiling/component.rb +20 -4
  76. data/lib/datadog/profiling/http_transport.rb +6 -1
  77. data/lib/datadog/profiling/scheduler.rb +2 -0
  78. data/lib/datadog/profiling/stack_recorder.rb +3 -0
  79. data/lib/datadog/single_step_instrument.rb +12 -0
  80. data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +8 -12
  81. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +5 -0
  82. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +78 -0
  83. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +33 -0
  84. data/lib/datadog/tracing/contrib/action_pack/patcher.rb +2 -0
  85. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +4 -0
  86. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +3 -1
  87. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +3 -1
  88. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +5 -1
  89. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +5 -0
  90. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
  91. data/lib/datadog/tracing/contrib/faraday/middleware.rb +9 -0
  92. data/lib/datadog/tracing/contrib/grape/endpoint.rb +19 -0
  93. data/lib/datadog/tracing/contrib/graphql/patcher.rb +9 -12
  94. data/lib/datadog/tracing/contrib/graphql/trace_patcher.rb +3 -3
  95. data/lib/datadog/tracing/contrib/graphql/tracing_patcher.rb +3 -3
  96. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +13 -9
  97. data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +6 -3
  98. data/lib/datadog/tracing/contrib/http/instrumentation.rb +18 -15
  99. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -5
  100. data/lib/datadog/tracing/contrib/httpclient/patcher.rb +1 -14
  101. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +5 -0
  102. data/lib/datadog/tracing/contrib/httprb/patcher.rb +1 -14
  103. data/lib/datadog/tracing/contrib/lograge/patcher.rb +1 -2
  104. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +2 -0
  105. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +13 -6
  106. data/lib/datadog/tracing/contrib/patcher.rb +2 -1
  107. data/lib/datadog/tracing/contrib/presto/patcher.rb +1 -13
  108. data/lib/datadog/tracing/contrib/rack/middlewares.rb +27 -0
  109. data/lib/datadog/tracing/contrib/redis/tags.rb +4 -0
  110. data/lib/datadog/tracing/contrib/sinatra/tracer.rb +4 -0
  111. data/lib/datadog/tracing/contrib/stripe/request.rb +3 -2
  112. data/lib/datadog/tracing/distributed/propagation.rb +7 -0
  113. data/lib/datadog/tracing/metadata/ext.rb +2 -0
  114. data/lib/datadog/tracing/remote.rb +5 -2
  115. data/lib/datadog/tracing/sampling/matcher.rb +6 -1
  116. data/lib/datadog/tracing/sampling/rate_sampler.rb +1 -1
  117. data/lib/datadog/tracing/sampling/rule.rb +2 -0
  118. data/lib/datadog/tracing/sampling/rule_sampler.rb +9 -5
  119. data/lib/datadog/tracing/sampling/span/ext.rb +1 -1
  120. data/lib/datadog/tracing/sampling/span/rule.rb +2 -2
  121. data/lib/datadog/tracing/trace_operation.rb +26 -2
  122. data/lib/datadog/tracing/tracer.rb +14 -12
  123. data/lib/datadog/tracing/transport/http/client.rb +1 -0
  124. data/lib/datadog/tracing/transport/io/client.rb +1 -0
  125. data/lib/datadog/tracing/workers/trace_writer.rb +1 -1
  126. data/lib/datadog/tracing/workers.rb +1 -1
  127. data/lib/datadog/version.rb +1 -1
  128. metadata +25 -8
  129. data/lib/datadog/tracing/sampling/rate_limiter.rb +0 -185
@@ -20,6 +20,8 @@ module Datadog
20
20
  tracer:,
21
21
  endpoint_collection_enabled:,
22
22
  timeline_enabled:,
23
+ waiting_for_gvl_threshold_ns:,
24
+ otel_context_enabled:,
23
25
  allocation_type_enabled: true
24
26
  )
25
27
  tracer_context_key = safely_extract_context_key_from(tracer)
@@ -30,10 +32,34 @@ module Datadog
30
32
  tracer_context_key,
31
33
  endpoint_collection_enabled,
32
34
  timeline_enabled,
35
+ waiting_for_gvl_threshold_ns,
36
+ otel_context_enabled,
33
37
  allocation_type_enabled,
34
38
  )
35
39
  end
36
40
 
41
+ def self.for_testing(
42
+ recorder:,
43
+ max_frames: 400,
44
+ tracer: nil,
45
+ endpoint_collection_enabled: false,
46
+ timeline_enabled: false,
47
+ waiting_for_gvl_threshold_ns: 10_000_000,
48
+ otel_context_enabled: false,
49
+ **options
50
+ )
51
+ new(
52
+ recorder: recorder,
53
+ max_frames: max_frames,
54
+ tracer: tracer,
55
+ endpoint_collection_enabled: endpoint_collection_enabled,
56
+ timeline_enabled: timeline_enabled,
57
+ waiting_for_gvl_threshold_ns: waiting_for_gvl_threshold_ns,
58
+ otel_context_enabled: otel_context_enabled,
59
+ **options,
60
+ )
61
+ end
62
+
37
63
  def inspect
38
64
  # Compose Ruby's default inspect with our custom inspect for the native parts
39
65
  result = super()
@@ -62,6 +62,7 @@ module Datadog
62
62
  dynamic_sampling_rate_overhead_target_percentage: overhead_target_percentage,
63
63
  allocation_profiling_enabled: allocation_profiling_enabled,
64
64
  allocation_counting_enabled: settings.profiling.advanced.allocation_counting_enabled,
65
+ gvl_profiling_enabled: enable_gvl_profiling?(settings),
65
66
  )
66
67
 
67
68
  internal_metadata = {
@@ -89,6 +90,8 @@ module Datadog
89
90
  tracer: optional_tracer,
90
91
  endpoint_collection_enabled: settings.profiling.advanced.endpoint.collection.enabled,
91
92
  timeline_enabled: timeline_enabled,
93
+ waiting_for_gvl_threshold_ns: settings.profiling.advanced.waiting_for_gvl_threshold_ns,
94
+ otel_context_enabled: settings.profiling.advanced.preview_otel_context_enabled,
92
95
  )
93
96
  end
94
97
 
@@ -252,6 +255,7 @@ module Datadog
252
255
  legacy_ruby_that_should_use_workaround = RUBY_VERSION.start_with?("2.5.")
253
256
 
254
257
  unless [true, false, :auto].include?(setting_value)
258
+ # TODO: Replace with a warning instead.
255
259
  Datadog.logger.error(
256
260
  "Ignoring invalid value for profiling no_signals_workaround_enabled setting: #{setting_value.inspect}. " \
257
261
  "Valid options are `true`, `false` or (default) `:auto`."
@@ -394,6 +398,7 @@ module Datadog
394
398
  if overhead_target_percentage > 0 && overhead_target_percentage <= 20
395
399
  overhead_target_percentage
396
400
  else
401
+ # TODO: Replace with a warning instead.
397
402
  Datadog.logger.error(
398
403
  "Ignoring invalid value for profiling overhead_target_percentage setting: " \
399
404
  "#{overhead_target_percentage.inspect}. Falling back to default value."
@@ -433,13 +438,24 @@ module Datadog
433
438
  end
434
439
 
435
440
  private_class_method def self.dir_interruption_workaround_enabled?(settings, no_signals_workaround_enabled)
436
- return false if no_signals_workaround_enabled
437
-
438
- # NOTE: In the future this method will evolve to check for Ruby versions affected and not apply the workaround
439
- # when it's not needed but currently all known Ruby versions are affected.
441
+ return false if no_signals_workaround_enabled || RUBY_VERSION >= "3.4"
440
442
 
441
443
  settings.profiling.advanced.dir_interruption_workaround_enabled
442
444
  end
445
+
446
+ private_class_method def self.enable_gvl_profiling?(settings)
447
+ if RUBY_VERSION < "3.2"
448
+ if settings.profiling.advanced.preview_gvl_enabled
449
+ Datadog.logger.warn("GVL profiling is currently not supported in Ruby < 3.2 and will not be enabled.")
450
+ end
451
+
452
+ return false
453
+ end
454
+
455
+ # GVL profiling only makes sense in the context of timeline. We could emit a warning here, but not sure how
456
+ # useful it is -- if a customer disables timeline, there's nowhere to look for GVL profiling anyway!
457
+ settings.profiling.advanced.timeline_enabled && settings.profiling.advanced.preview_gvl_enabled
458
+ end
443
459
  end
444
460
  end
445
461
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "../core/transport/ext"
4
+ require_relative "../core/telemetry/logger"
4
5
 
5
6
  module Datadog
6
7
  module Profiling
@@ -60,10 +61,14 @@ module Datadog
60
61
  "Failed to report profiling data (#{config_without_api_key}): " \
61
62
  "server returned unexpected HTTP #{result} status code"
62
63
  )
64
+ Datadog::Core::Telemetry::Logger.error(
65
+ "Failed to report profiling data: unexpected HTTP #{result} status code"
66
+ )
63
67
  false
64
68
  end
65
69
  else
66
70
  Datadog.logger.error("Failed to report profiling data (#{config_without_api_key}): #{result}")
71
+ Datadog::Core::Telemetry::Logger.error("Failed to report profiling data")
67
72
  false
68
73
  end
69
74
  end
@@ -134,7 +139,7 @@ module Datadog
134
139
  end
135
140
 
136
141
  def config_without_api_key
137
- [exporter_configuration[0..1]].to_h
142
+ "#{exporter_configuration[0]}: #{exporter_configuration[1]}"
138
143
  end
139
144
  end
140
145
  end
@@ -4,6 +4,7 @@ require_relative "../core/utils/time"
4
4
 
5
5
  require_relative "../core/worker"
6
6
  require_relative "../core/workers/polling"
7
+ require_relative "../core/telemetry/logger"
7
8
 
8
9
  module Datadog
9
10
  module Profiling
@@ -134,6 +135,7 @@ module Datadog
134
135
  Datadog.logger.error(
135
136
  "Unable to report profile. Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
136
137
  )
138
+ Datadog::Core::Telemetry::Logger.report(e, description: "Unable to report profile")
137
139
  end
138
140
 
139
141
  true
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../core/telemetry/logger"
4
+
3
5
  module Datadog
4
6
  module Profiling
5
7
  # Stores stack samples in a native libdatadog data structure and expose Ruby-level serialization APIs
@@ -42,6 +44,7 @@ module Datadog
42
44
  error_message = result
43
45
 
44
46
  Datadog.logger.error("Failed to serialize profiling data: #{error_message}")
47
+ Datadog::Core::Telemetry::Logger.error("Failed to serialize profiling data")
45
48
 
46
49
  nil
47
50
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Entrypoint file for single step instrumentation.
5
+ #
6
+ # This file's path is private. Do not reference this file.
7
+ #
8
+ begin
9
+ require_relative 'auto_instrument'
10
+ rescue StandardError, LoadError => e
11
+ warn "Single step instrumentation failed: #{e.class}:#{e.message}\n\tSource:\n\t#{Array(e.backtrace).join("\n\t")}"
12
+ end
@@ -14,21 +14,17 @@ module Datadog
14
14
  module ActionCableConnection
15
15
  def on_open
16
16
  Tracing.trace(Ext::SPAN_ON_OPEN) do |span, trace|
17
- begin
18
- span.resource = "#{self.class}#on_open"
19
- span.type = Tracing::Metadata::Ext::AppTypes::TYPE_WEB
17
+ span.resource = "#{self.class}#on_open"
18
+ span.type = Tracing::Metadata::Ext::AppTypes::TYPE_WEB
20
19
 
21
- span.set_tag(Ext::TAG_ACTION, 'on_open')
22
- span.set_tag(Ext::TAG_CONNECTION, self.class.to_s)
20
+ span.set_tag(Ext::TAG_ACTION, 'on_open')
21
+ span.set_tag(Ext::TAG_CONNECTION, self.class.to_s)
23
22
 
24
- span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
25
- span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_ON_OPEN)
23
+ span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
24
+ span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_ON_OPEN)
26
25
 
27
- # Set the resource name of the trace
28
- trace.resource = span.resource
29
- rescue StandardError => e
30
- Datadog.logger.error("Error preparing span for ActionCable::Connection: #{e}")
31
- end
26
+ # Set the resource name of the trace
27
+ trace.resource = span.resource
32
28
 
33
29
  super
34
30
  end
@@ -7,6 +7,7 @@ require_relative '../ext'
7
7
  require_relative '../utils'
8
8
  require_relative '../../rack/middlewares'
9
9
  require_relative '../../analytics'
10
+ require_relative '../../../../core/telemetry/logger'
10
11
 
11
12
  module Datadog
12
13
  module Tracing
@@ -43,6 +44,7 @@ module Datadog
43
44
  span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_CONTROLLER)
44
45
  rescue StandardError => e
45
46
  Datadog.logger.error(e.message)
47
+ Datadog::Core::Telemetry::Logger.report(e)
46
48
  end
47
49
 
48
50
  def finish_processing(payload)
@@ -81,10 +83,13 @@ module Datadog
81
83
  end
82
84
  rescue StandardError => e
83
85
  Datadog.logger.error(e.message)
86
+ Datadog::Core::Telemetry::Logger.report(e)
84
87
  end
85
88
 
86
89
  # Instrumentation for ActionController::Metal
87
90
  module Metal
91
+ # TODO: Refactor this method to avoid using async API that splits the logic
92
+ # into two different methods (`start_processing` and `finish_processing`)
88
93
  def process_action(*args)
89
94
  # mutable payload with a tracing context that is used in two different
90
95
  # signals; it propagates the request span so that it can be finished
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../metadata/ext'
4
+
5
+ module Datadog
6
+ module Tracing
7
+ module Contrib
8
+ module ActionPack
9
+ module ActionDispatch
10
+ # Instrumentation for ActionDispatch components
11
+ module Instrumentation
12
+ module_function
13
+
14
+ def set_http_route_tags(route_spec, script_name)
15
+ return unless Tracing.enabled?
16
+
17
+ return unless route_spec
18
+
19
+ request_trace = Tracing.active_trace
20
+ return unless request_trace
21
+
22
+ request_trace.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE, route_spec.to_s.gsub(/\(.:format\)\z/, ''))
23
+
24
+ if script_name && !script_name.empty?
25
+ request_trace.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH, script_name)
26
+ end
27
+ end
28
+
29
+ def dispatcher_route?(route)
30
+ return true if route.dispatcher?
31
+
32
+ # in Rails 4 there is no #rack_app method on the app
33
+ return true if route.app.respond_to?(:rack_app) && !route.app.rack_app.nil?
34
+
35
+ false
36
+ end
37
+
38
+ # Instrumentation for ActionDispatch::Journey components
39
+ module Journey
40
+ # Instrumentation for ActionDispatch::Journey::Router for Rails versions older than 7.1
41
+ module Router
42
+ def find_routes(req)
43
+ result = super
44
+
45
+ # result is an array of [match, parameters, route] tuples
46
+ routes = result.map(&:last)
47
+
48
+ routes.each do |route|
49
+ if Instrumentation.dispatcher_route?(route)
50
+ Instrumentation.set_http_route_tags(route.path.spec, req.env['SCRIPT_NAME'])
51
+ break
52
+ end
53
+ end
54
+
55
+ result
56
+ end
57
+ end
58
+
59
+ # Since Rails 7.1 `Router#find_routes` makes the route computation lazy
60
+ # https://github.com/rails/rails/commit/35b280fcc2d5d474f9f2be3aca3ae7aa6bba66eb
61
+ module LazyRouter
62
+ def find_routes(req)
63
+ super do |match, parameters, route|
64
+ if Instrumentation.dispatcher_route?(route)
65
+ Instrumentation.set_http_route_tags(route.path.spec, req.env['SCRIPT_NAME'])
66
+ end
67
+
68
+ yield [match, parameters, route]
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../patcher'
4
+ require_relative 'instrumentation'
5
+
6
+ module Datadog
7
+ module Tracing
8
+ module Contrib
9
+ module ActionPack
10
+ module ActionDispatch
11
+ # Patcher for ActionController components
12
+ module Patcher
13
+ include Contrib::Patcher
14
+
15
+ module_function
16
+
17
+ def target_version
18
+ Integration.version
19
+ end
20
+
21
+ def patch
22
+ if ::ActionPack.gem_version >= Gem::Version.new('7.1')
23
+ ::ActionDispatch::Journey::Router.prepend(ActionDispatch::Instrumentation::Journey::LazyRouter)
24
+ else
25
+ ::ActionDispatch::Journey::Router.prepend(ActionDispatch::Instrumentation::Journey::Router)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative '../patcher'
4
4
  require_relative 'action_controller/patcher'
5
+ require_relative 'action_dispatch/patcher'
5
6
 
6
7
  module Datadog
7
8
  module Tracing
@@ -19,6 +20,7 @@ module Datadog
19
20
 
20
21
  def patch
21
22
  ActionController::Patcher.patch
23
+ ActionDispatch::Patcher.patch
22
24
  end
23
25
  end
24
26
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative '../../configuration/resolver'
4
4
  require_relative 'makara_resolver'
5
+ require_relative '../../../../core/telemetry/logger'
5
6
 
6
7
  module Datadog
7
8
  module Tracing
@@ -72,10 +73,12 @@ module Datadog
72
73
  #
73
74
  # `db_config` input may contain sensitive information such as passwords,
74
75
  # hence provide a succinct summary for the error logging.
76
+ #
75
77
  Datadog.logger.error(
76
78
  'Failed to resolve ActiveRecord database configuration. '\
77
79
  "Cause: #{e.class.name} Source: #{Array(e.backtrace).first}"
78
80
  )
81
+ Core::Telemetry::Logger.report(e, description: 'Failed to resolve ActiveRecord database configuration')
79
82
 
80
83
  nil
81
84
  end
@@ -95,6 +98,7 @@ module Datadog
95
98
  "Failed to resolve key #{matcher.inspect}. " \
96
99
  "Cause: #{e.class.name} Source: #{Array(e.backtrace).first}"
97
100
  )
101
+ Core::Telemetry::Logger.report(e, description: 'Failed to resolve key')
98
102
 
99
103
  nil
100
104
  end
@@ -4,6 +4,7 @@ require_relative '../../../metadata/ext'
4
4
  require_relative '../../analytics'
5
5
  require_relative '../ext'
6
6
  require_relative '../event'
7
+ require_relative '../../../../core/telemetry/logger'
7
8
 
8
9
  module Datadog
9
10
  module Tracing
@@ -48,7 +49,8 @@ module Datadog
48
49
  span.set_tag(Ext::TAG_INSTANTIATION_CLASS_NAME, payload.fetch(:class_name))
49
50
  span.set_tag(Ext::TAG_INSTANTIATION_RECORD_COUNT, payload.fetch(:record_count))
50
51
  rescue StandardError => e
51
- Datadog.logger.debug(e.message)
52
+ Datadog.logger.error(e.message)
53
+ Datadog::Core::Telemetry::Logger.report(e)
52
54
  end
53
55
  end
54
56
  end
@@ -6,6 +6,7 @@ require_relative '../event'
6
6
  require_relative '../ext'
7
7
  require_relative '../../analytics'
8
8
  require_relative '../../utils/database'
9
+ require_relative '../../../../core/telemetry/logger'
9
10
 
10
11
  module Datadog
11
12
  module Tracing
@@ -68,7 +69,8 @@ module Datadog
68
69
  span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_HOST, config[:host]) if config[:host]
69
70
  span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_PORT, config[:port]) if config[:port]
70
71
  rescue StandardError => e
71
- Datadog.logger.debug(e.message)
72
+ Datadog.logger.error(e.message)
73
+ Datadog::Core::Telemetry::Logger.report(e)
72
74
  end
73
75
  end
74
76
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative '../../ext'
4
4
  require_relative '../event'
5
+ require_relative '../../../../../core/telemetry/logger'
5
6
 
6
7
  module Datadog
7
8
  module Tracing
@@ -64,7 +65,7 @@ module Datadog
64
65
  key = payload[:key]
65
66
  store = payload[:store]
66
67
 
67
- mapping = MAPPING[event]
68
+ mapping = MAPPING.fetch(event)
68
69
 
69
70
  span.service = configuration[:cache_service]
70
71
  span.resource = mapping[:resource]
@@ -81,6 +82,9 @@ module Datadog
81
82
  span.set_tag('EVENT', event)
82
83
 
83
84
  set_cache_key(span, key, mapping[:multi_key])
85
+ rescue StandardError => e
86
+ Datadog.logger.error(e.message)
87
+ Datadog::Core::Telemetry::Logger.report(e)
84
88
  end
85
89
 
86
90
  def set_cache_key(span, key, multi_key)
@@ -29,6 +29,7 @@ module Datadog
29
29
  private
30
30
 
31
31
  # rubocop:disable Metrics/AbcSize
32
+ # rubocop:disable Metrics/MethodLength
32
33
  def annotate!(span, context)
33
34
  span.service = configuration[:service_name]
34
35
  span.type = Tracing::Metadata::Ext::HTTP::TYPE_OUTBOUND
@@ -76,7 +77,11 @@ module Datadog
76
77
  span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_STATUS_CODE, context.safely(:status_code))
77
78
 
78
79
  Contrib::SpanAttributeSchema.set_peer_service!(span, Ext::PEER_SERVICE_SOURCES)
80
+ rescue StandardError => e
81
+ Datadog.logger.error(e.message)
82
+ Datadog::Core::Telemetry::Logger.report(e)
79
83
  end
84
+ # rubocop:enable Metrics/MethodLength
80
85
  # rubocop:enable Metrics/AbcSize
81
86
 
82
87
  def configuration
@@ -93,11 +93,16 @@ module Datadog
93
93
  span.resource = "#{method} #{quantized_url}"
94
94
  Contrib::SpanAttributeSchema.set_peer_service!(span, Ext::PEER_SERVICE_SOURCES)
95
95
  rescue StandardError => e
96
+ # TODO: Refactor the code to streamline the execution without ensure
96
97
  Datadog.logger.error(e.message)
98
+ Datadog::Core::Telemetry::Logger.report(e)
97
99
  ensure
98
100
  # the call is still executed
99
101
  response = super
100
- span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_STATUS_CODE, response.status)
102
+
103
+ if response && response.respond_to?(:status)
104
+ span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_STATUS_CODE, response.status)
105
+ end
101
106
  end
102
107
  end
103
108
  response
@@ -7,6 +7,7 @@ require_relative '../http'
7
7
  require_relative '../analytics'
8
8
  require_relative 'ext'
9
9
  require_relative '../http_annotation_helper'
10
+ require_relative '../../../core/telemetry/logger'
10
11
 
11
12
  module Datadog
12
13
  module Tracing
@@ -37,6 +38,7 @@ module Datadog
37
38
 
38
39
  attr_reader :app
39
40
 
41
+ # rubocop:disable Metrics/AbcSize
40
42
  def annotate!(span, env, options)
41
43
  span.resource = resource_name(env)
42
44
  span.service = service_name(env[:url].host, options)
@@ -75,7 +77,11 @@ module Datadog
75
77
  )
76
78
 
77
79
  Contrib::SpanAttributeSchema.set_peer_service!(span, Ext::PEER_SERVICE_SOURCES)
80
+ rescue StandardError => e
81
+ Datadog.logger.error(e.message)
82
+ Datadog::Core::Telemetry::Logger.report(e)
78
83
  end
84
+ # rubocop:enable Metrics/AbcSize
79
85
 
80
86
  def handle_response(span, env, options)
81
87
  span.set_error(["Error #{env[:status]}", env[:body]]) if options[:error_status_codes].include? env[:status]
@@ -85,6 +91,9 @@ module Datadog
85
91
  span.set_tags(
86
92
  Datadog.configuration.tracing.header_tags.response_tags(env[:response_headers])
87
93
  )
94
+ rescue StandardError => e
95
+ Datadog.logger.error(e.message)
96
+ Datadog::Core::Telemetry::Logger.report(e)
88
97
  end
89
98
 
90
99
  def propagate!(trace, span, env)
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../../../core'
4
+ require_relative '../../../core/telemetry/logger'
4
5
  require_relative '../../metadata/ext'
5
6
  require_relative '../analytics'
6
7
  require_relative '../rack/ext'
@@ -41,6 +42,7 @@ module Datadog
41
42
 
42
43
  # collect endpoint details
43
44
  endpoint = payload.fetch(:endpoint)
45
+ env = payload.fetch(:env)
44
46
  api_view = api_view(endpoint.options[:for])
45
47
  request_method = endpoint.options.fetch(:method).first
46
48
  path = endpoint_expand_path(endpoint)
@@ -61,9 +63,22 @@ module Datadog
61
63
  span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
62
64
  span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_ENDPOINT_RUN)
63
65
 
66
+ if (grape_route = env['grape.routing_args']) && grape_route[:route_info]
67
+ trace.set_tag(
68
+ Tracing::Metadata::Ext::HTTP::TAG_ROUTE,
69
+ # here we are removing the format from the path:
70
+ # e.g. /path/to/resource(.json) => /path/to/resource
71
+ # e.g. /path/to/resource(.:format) => /path/to/resource
72
+ grape_route[:route_info].path&.gsub(/\(\.:?\w+\)\z/, '')
73
+ )
74
+
75
+ trace.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH, env['SCRIPT_NAME'])
76
+ end
77
+
64
78
  Thread.current[KEY_RUN] = true
65
79
  rescue StandardError => e
66
80
  Datadog.logger.error(e.message)
81
+ Datadog::Core::Telemetry::Logger.report(e)
67
82
  end
68
83
 
69
84
  def endpoint_run(name, start, finish, id, payload)
@@ -107,6 +122,7 @@ module Datadog
107
122
  end
108
123
  rescue StandardError => e
109
124
  Datadog.logger.error(e.message)
125
+ Datadog::Core::Telemetry::Logger.report(e)
110
126
  end
111
127
 
112
128
  # Status code resolution is tied to the exception handling
@@ -150,6 +166,7 @@ module Datadog
150
166
  Thread.current[KEY_RENDER] = true
151
167
  rescue StandardError => e
152
168
  Datadog.logger.error(e.message)
169
+ Datadog::Core::Telemetry::Logger.report(e)
153
170
  end
154
171
 
155
172
  def endpoint_render(name, start, finish, id, payload)
@@ -174,6 +191,7 @@ module Datadog
174
191
  end
175
192
  rescue StandardError => e
176
193
  Datadog.logger.error(e.message)
194
+ Datadog::Core::Telemetry::Logger.report(e)
177
195
  end
178
196
 
179
197
  def endpoint_run_filters(name, start, finish, id, payload)
@@ -212,6 +230,7 @@ module Datadog
212
230
  end
213
231
  rescue StandardError => e
214
232
  Datadog.logger.error(e.message)
233
+ Datadog::Core::Telemetry::Logger.report(e)
215
234
  end
216
235
 
217
236
  private
@@ -21,13 +21,18 @@ module Datadog
21
21
  end
22
22
 
23
23
  def patch
24
+ # DEV-3.0: We should remove as many patching options as possible, given the alternatives do not
25
+ # DEV-3.0: provide any benefit to the recommended `with_unified_tracer` patching method.
26
+ # DEV-3.0: `with_deprecated_tracer` is likely safe to remove.
27
+ # DEV-3.0: `with_unified_tracer: false` should be removed if possible.
28
+ # DEV-3.0: `with_unified_tracer: true` should be the default and hopefully not even necessary as an option.
24
29
  if configuration[:with_deprecated_tracer]
25
- TracingPatcher.patch!(schemas, trace_options)
30
+ TracingPatcher.patch!(schemas)
26
31
  elsif Integration.trace_supported?
27
32
  if configuration[:with_unified_tracer]
28
- UnifiedTracePatcher.patch!(schemas, trace_options)
33
+ UnifiedTracePatcher.patch!(schemas)
29
34
  else
30
- TracePatcher.patch!(schemas, trace_options)
35
+ TracePatcher.patch!(schemas)
31
36
  end
32
37
  else
33
38
  Datadog.logger.warn(
@@ -35,18 +40,10 @@ module Datadog
35
40
  'or Datadog::Tracing::Contrib::GraphQL::UnifiedTrace.'\
36
41
  'Falling back to GraphQL::Tracing::DataDogTracing.'
37
42
  )
38
- TracingPatcher.patch!(schemas, trace_options)
43
+ TracingPatcher.patch!(schemas)
39
44
  end
40
45
  end
41
46
 
42
- def trace_options
43
- {
44
- service: configuration[:service_name],
45
- analytics_enabled: Contrib::Analytics.enabled?(configuration[:analytics_enabled]),
46
- analytics_sample_rate: configuration[:analytics_sample_rate]
47
- }
48
- end
49
-
50
47
  def configuration
51
48
  Datadog.configuration.tracing[:graphql]
52
49
  end
@@ -8,12 +8,12 @@ module Datadog
8
8
  module TracePatcher
9
9
  module_function
10
10
 
11
- def patch!(schemas, options)
11
+ def patch!(schemas)
12
12
  if schemas.empty?
13
- ::GraphQL::Schema.trace_with(::GraphQL::Tracing::DataDogTrace, **options)
13
+ ::GraphQL::Schema.trace_with(::GraphQL::Tracing::DataDogTrace)
14
14
  else
15
15
  schemas.each do |schema|
16
- schema.trace_with(::GraphQL::Tracing::DataDogTrace, **options)
16
+ schema.trace_with(::GraphQL::Tracing::DataDogTrace)
17
17
  end
18
18
  end
19
19
  end