datadog 2.9.0 → 2.11.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 (131) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +72 -1
  3. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +2 -2
  4. data/ext/datadog_profiling_native_extension/collectors_stack.c +3 -3
  5. data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
  6. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +46 -6
  7. data/ext/datadog_profiling_native_extension/extconf.rb +4 -0
  8. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +2 -0
  9. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +0 -8
  10. data/ext/datadog_profiling_native_extension/heap_recorder.c +51 -93
  11. data/ext/datadog_profiling_native_extension/heap_recorder.h +1 -1
  12. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +56 -0
  13. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +7 -0
  14. data/ext/datadog_profiling_native_extension/profiling.c +7 -0
  15. data/ext/datadog_profiling_native_extension/stack_recorder.c +9 -22
  16. data/ext/datadog_profiling_native_extension/stack_recorder.h +1 -1
  17. data/ext/libdatadog_api/crashtracker.c +4 -4
  18. data/ext/libdatadog_extconf_helpers.rb +1 -1
  19. data/lib/datadog/appsec/actions_handler.rb +27 -0
  20. data/lib/datadog/appsec/component.rb +14 -8
  21. data/lib/datadog/appsec/configuration/settings.rb +73 -11
  22. data/lib/datadog/appsec/context.rb +28 -8
  23. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +6 -2
  24. data/lib/datadog/appsec/contrib/active_record/patcher.rb +0 -3
  25. data/lib/datadog/appsec/contrib/devise/configuration.rb +76 -0
  26. data/lib/datadog/appsec/contrib/devise/event.rb +4 -7
  27. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +16 -21
  28. data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +8 -15
  29. data/lib/datadog/appsec/contrib/devise/patcher/rememberable_patch.rb +1 -1
  30. data/lib/datadog/appsec/contrib/devise/patcher.rb +0 -3
  31. data/lib/datadog/appsec/contrib/devise/tracking.rb +1 -1
  32. data/lib/datadog/appsec/contrib/excon/integration.rb +41 -0
  33. data/lib/datadog/appsec/contrib/excon/patcher.rb +28 -0
  34. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +43 -0
  35. data/lib/datadog/appsec/contrib/faraday/connection_patch.rb +22 -0
  36. data/lib/datadog/appsec/contrib/faraday/integration.rb +42 -0
  37. data/lib/datadog/appsec/contrib/faraday/patcher.rb +53 -0
  38. data/lib/datadog/appsec/contrib/faraday/rack_builder_patch.rb +22 -0
  39. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +42 -0
  40. data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +1 -7
  41. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +11 -14
  42. data/lib/datadog/appsec/contrib/graphql/patcher.rb +0 -3
  43. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +65 -70
  44. data/lib/datadog/appsec/contrib/rack/patcher.rb +0 -3
  45. data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +3 -3
  46. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +11 -22
  47. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +20 -24
  48. data/lib/datadog/appsec/contrib/rails/patcher.rb +3 -16
  49. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +38 -47
  50. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +3 -29
  51. data/lib/datadog/appsec/ext.rb +6 -1
  52. data/lib/datadog/appsec/metrics/collector.rb +38 -0
  53. data/lib/datadog/appsec/metrics/exporter.rb +35 -0
  54. data/lib/datadog/appsec/metrics/telemetry.rb +23 -0
  55. data/lib/datadog/appsec/metrics.rb +13 -0
  56. data/lib/datadog/appsec/monitor/gateway/watcher.rb +19 -24
  57. data/lib/datadog/appsec/processor.rb +4 -3
  58. data/lib/datadog/appsec/remote.rb +4 -0
  59. data/lib/datadog/appsec/response.rb +18 -80
  60. data/lib/datadog/appsec/security_engine/result.rb +67 -0
  61. data/lib/datadog/appsec/security_engine/runner.rb +88 -0
  62. data/lib/datadog/appsec/security_engine.rb +9 -0
  63. data/lib/datadog/appsec.rb +16 -5
  64. data/lib/datadog/core/configuration/components.rb +7 -1
  65. data/lib/datadog/core/configuration/ext.rb +1 -1
  66. data/lib/datadog/core/configuration/option_definition.rb +2 -0
  67. data/lib/datadog/core/configuration/settings.rb +22 -6
  68. data/lib/datadog/core/encoding.rb +16 -0
  69. data/lib/datadog/core/environment/agent_info.rb +77 -0
  70. data/lib/datadog/core/remote/transport/http/api.rb +13 -18
  71. data/lib/datadog/core/remote/transport/http/config.rb +0 -18
  72. data/lib/datadog/core/remote/transport/http/negotiation.rb +1 -18
  73. data/lib/datadog/core/remote/transport/http.rb +7 -12
  74. data/lib/datadog/core/remote/transport/negotiation.rb +13 -1
  75. data/lib/datadog/core/telemetry/event.rb +5 -0
  76. data/lib/datadog/core/transport/http/adapters/unix_socket.rb +1 -1
  77. data/lib/datadog/{tracing → core}/transport/http/api/instance.rb +1 -1
  78. data/lib/datadog/{tracing → core}/transport/http/api/spec.rb +1 -1
  79. data/lib/datadog/{tracing → core}/transport/http/builder.rb +37 -17
  80. data/lib/datadog/core/transport/response.rb +4 -0
  81. data/lib/datadog/di/code_tracker.rb +15 -8
  82. data/lib/datadog/di/component.rb +3 -0
  83. data/lib/datadog/di/configuration/settings.rb +14 -0
  84. data/lib/datadog/di/contrib.rb +2 -0
  85. data/lib/datadog/di/logger.rb +30 -0
  86. data/lib/datadog/di/probe.rb +3 -6
  87. data/lib/datadog/di/probe_manager.rb +5 -2
  88. data/lib/datadog/di/probe_notification_builder.rb +6 -0
  89. data/lib/datadog/di/probe_notifier_worker.rb +15 -4
  90. data/lib/datadog/di/redactor.rb +0 -1
  91. data/lib/datadog/di/remote.rb +29 -8
  92. data/lib/datadog/di/utils.rb +91 -0
  93. data/lib/datadog/di.rb +3 -0
  94. data/lib/datadog/profiling/component.rb +2 -8
  95. data/lib/datadog/profiling/load_native_extension.rb +1 -33
  96. data/lib/datadog/tracing/configuration/ext.rb +1 -0
  97. data/lib/datadog/tracing/contrib/aws/integration.rb +1 -1
  98. data/lib/datadog/tracing/contrib/extensions.rb +29 -3
  99. data/lib/datadog/tracing/contrib/graphql/configuration/error_extension_env_parser.rb +21 -0
  100. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +11 -0
  101. data/lib/datadog/tracing/contrib/graphql/ext.rb +5 -0
  102. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +102 -11
  103. data/lib/datadog/tracing/contrib/http/integration.rb +3 -0
  104. data/lib/datadog/tracing/contrib/rack/header_collection.rb +11 -1
  105. data/lib/datadog/tracing/contrib/rack/middlewares.rb +1 -1
  106. data/lib/datadog/tracing/contrib/span_attribute_schema.rb +6 -1
  107. data/lib/datadog/tracing/transport/http/api.rb +11 -2
  108. data/lib/datadog/tracing/transport/http/traces.rb +0 -3
  109. data/lib/datadog/tracing/transport/http.rb +12 -7
  110. data/lib/datadog/tracing/transport/serializable_trace.rb +8 -4
  111. data/lib/datadog/tracing/transport/traces.rb +25 -8
  112. data/lib/datadog/version.rb +1 -1
  113. metadata +51 -42
  114. data/ext/datadog_profiling_loader/datadog_profiling_loader.c +0 -142
  115. data/ext/datadog_profiling_loader/extconf.rb +0 -60
  116. data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +0 -46
  117. data/lib/datadog/appsec/contrib/patcher.rb +0 -12
  118. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +0 -69
  119. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +0 -47
  120. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +0 -53
  121. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +0 -53
  122. data/lib/datadog/appsec/contrib/sinatra/ext.rb +0 -14
  123. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +0 -48
  124. data/lib/datadog/appsec/monitor/reactive/set_user.rb +0 -45
  125. data/lib/datadog/appsec/processor/context.rb +0 -107
  126. data/lib/datadog/appsec/reactive/address_hash.rb +0 -22
  127. data/lib/datadog/appsec/reactive/engine.rb +0 -47
  128. data/lib/datadog/appsec/reactive/subscriber.rb +0 -19
  129. data/lib/datadog/core/remote/transport/http/api/instance.rb +0 -39
  130. data/lib/datadog/core/remote/transport/http/api/spec.rb +0 -21
  131. data/lib/datadog/core/remote/transport/http/builder.rb +0 -219
@@ -2,24 +2,9 @@
2
2
 
3
3
  require_relative '../../../encoding'
4
4
  require_relative '../../../transport/http/api/map'
5
-
6
- # TODO: Decouple standard transport/http/api/instance
7
- #
8
- # Separate classes are needed because transport/http/traces includes
9
- # Trace::API::Instance which closes over and uses a single spec, which is
10
- # negotiated as either /v3 or /v4 for the whole API at the spec level, but we
11
- # need an independent toplevel path at the endpoint level.
12
- #
13
- # Separate classes are needed because of `include Trace::API::Instance`.
14
- #
15
- # Below should be:
16
- # require_relative '../../../../datadog/core/transport/http/api/spec'
17
- require_relative 'api/spec'
18
-
19
- # TODO: only needed for Negotiation::API::Endpoint
5
+ require_relative '../../../transport/http/api/instance'
6
+ require_relative '../../../transport/http/api/spec'
20
7
  require_relative 'negotiation'
21
-
22
- # TODO: only needed for Config::API::Endpoint
23
8
  require_relative 'config'
24
9
 
25
10
  module Datadog
@@ -36,7 +21,7 @@ module Datadog
36
21
  module_function
37
22
 
38
23
  def defaults
39
- Datadog::Core::Transport::HTTP::API::Map[
24
+ Core::Transport::HTTP::API::Map[
40
25
  ROOT => Spec.new do |s|
41
26
  s.info = Negotiation::API::Endpoint.new(
42
27
  '/info',
@@ -50,6 +35,16 @@ module Datadog
50
35
  end,
51
36
  ]
52
37
  end
38
+
39
+ class Instance < Core::Transport::HTTP::API::Instance
40
+ include Config::API::Instance
41
+ include Negotiation::API::Instance
42
+ end
43
+
44
+ class Spec < Core::Transport::HTTP::API::Spec
45
+ include Config::API::Spec
46
+ include Negotiation::API::Spec
47
+ end
53
48
  end
54
49
  end
55
50
  end
@@ -8,22 +8,6 @@ require_relative '../../../utils/base64'
8
8
  require_relative '../../../transport/http/response'
9
9
  require_relative '../../../transport/http/api/endpoint'
10
10
 
11
- # TODO: Decouple standard transport/http/api/instance
12
- #
13
- # Separate classes are needed because transport/http/trace includes
14
- # Trace::API::Instance which closes over and uses a single spec, which is
15
- # negotiated as either /v3 or /v4 for the whole API at the spec level, but we
16
- # need an independent toplevel path at the endpoint level.
17
- #
18
- # Separate classes are needed because of `include Trace::API::Instance`.
19
- #
20
- # Below should be:
21
- # require_relative '../../../core/transport/http/api/instance'
22
- require_relative 'api/instance'
23
- # Below should be:
24
- # require_relative '../../../core/transport/http/api/spec'
25
- require_relative 'api/spec'
26
-
27
11
  module Datadog
28
12
  module Core
29
13
  module Remote
@@ -270,8 +254,6 @@ module Datadog
270
254
  # Add remote configuration behavior to transport components
271
255
  ###### overrides send_payload! which calls send_<endpoint>! kills any other possible endpoint!
272
256
  HTTP::Client.include(Config::Client)
273
- HTTP::API::Spec.include(Config::API::Spec)
274
- HTTP::API::Instance.include(Config::API::Instance)
275
257
  end
276
258
  end
277
259
  end
@@ -7,22 +7,6 @@ require_relative 'client'
7
7
  require_relative '../../../transport/http/response'
8
8
  require_relative '../../../transport/http/api/endpoint'
9
9
 
10
- # TODO: Decouple standard transport/http/api/instance
11
- #
12
- # Separate classes are needed because transport/http/trace includes
13
- # Trace::API::Instance which closes over and uses a single spec, which is
14
- # negotiated as either /v3 or /v4 for the whole API at the spec level, but we
15
- # need an independent toplevel path at the endpoint level.
16
- #
17
- # Separate classes are needed because of `include Trace::API::Instance`.
18
- #
19
- # Below should be:
20
- # require_relative '../../../../datadog/core/transport/http/api/instance'
21
- require_relative 'api/instance'
22
- # Below should be:
23
- # require_relative '../../../../datadog/core/transport/http/api/spec'
24
- require_relative 'api/spec'
25
-
26
10
  module Datadog
27
11
  module Core
28
12
  module Remote
@@ -43,6 +27,7 @@ module Datadog
43
27
  @version = options[:version]
44
28
  @endpoints = options[:endpoints]
45
29
  @config = options[:config]
30
+ @span_events = options[:span_events]
46
31
  end
47
32
  end
48
33
 
@@ -136,8 +121,6 @@ module Datadog
136
121
 
137
122
  # Add negotiation behavior to transport components
138
123
  HTTP::Client.include(Negotiation::Client)
139
- HTTP::API::Spec.include(Negotiation::API::Spec)
140
- HTTP::API::Instance.include(Negotiation::API::Instance)
141
124
  end
142
125
  end
143
126
  end
@@ -5,6 +5,7 @@ require 'uri'
5
5
  require_relative '../../environment/container'
6
6
  require_relative '../../environment/ext'
7
7
  require_relative '../../transport/ext'
8
+ require_relative '../../transport/http/builder'
8
9
  require_relative '../../transport/http/adapters/net'
9
10
  require_relative '../../transport/http/adapters/unix_socket'
10
11
  require_relative '../../transport/http/adapters/test'
@@ -19,14 +20,6 @@ require_relative '../../transport/http/adapters/test'
19
20
  # require_relative '../../transport/http/api'
20
21
  require_relative 'http/api'
21
22
 
22
- # TODO: Decouple transport/http/builder
23
- #
24
- # See http/builder
25
- #
26
- # Below should be:
27
- # require_relative '../../transport/http/builder'
28
- require_relative 'http/builder'
29
-
30
23
  # TODO: Decouple transport/http
31
24
  #
32
25
  # Because a new transport is required for every (API, Client, Transport)
@@ -53,7 +46,9 @@ module Datadog
53
46
 
54
47
  # Builds a new Transport::HTTP::Client
55
48
  def new(klass, &block)
56
- Builder.new(&block).to_transport(klass)
49
+ Core::Transport::HTTP::Builder.new(
50
+ api_instance_class: API::Instance, &block
51
+ ).to_transport(klass)
57
52
  end
58
53
 
59
54
  # Builds a new Transport::HTTP::Client with default settings
@@ -133,15 +128,15 @@ module Datadog
133
128
  end
134
129
 
135
130
  # Add adapters to registry
136
- Builder::REGISTRY.set(
131
+ Core::Transport::HTTP::Builder::REGISTRY.set(
137
132
  Datadog::Core::Transport::HTTP::Adapters::Net,
138
133
  Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
139
134
  )
140
- Builder::REGISTRY.set(
135
+ Core::Transport::HTTP::Builder::REGISTRY.set(
141
136
  Datadog::Core::Transport::HTTP::Adapters::Test,
142
137
  Datadog::Core::Transport::Ext::Test::ADAPTER
143
138
  )
144
- Builder::REGISTRY.set(
139
+ Core::Transport::HTTP::Builder::REGISTRY.set(
145
140
  Datadog::Core::Transport::HTTP::Adapters::UnixSocket,
146
141
  Datadog::Core::Configuration::Ext::Agent::UnixSocket::ADAPTER
147
142
  )
@@ -32,7 +32,19 @@ module Datadog
32
32
 
33
33
  # Negotiation response
34
34
  module Response
35
- attr_reader :version, :endpoints, :config
35
+ # @!attribute [r] version
36
+ # The version of the agent.
37
+ # @return [String]
38
+ # @!attribute [r] endpoints
39
+ # The HTTP endpoints the agent supports.
40
+ # @return [Array<String>]
41
+ # @!attribute [r] config
42
+ # The agent configuration. These are configured by the user when starting the agent, as well as any defaults.
43
+ # @return [Hash]
44
+ # @!attribute [r] span_events
45
+ # Whether the agent supports the top-level span events field in flushed spans.
46
+ # @return [Boolean,nil]
47
+ attr_reader :version, :endpoints, :config, :span_events
36
48
  end
37
49
 
38
50
  # Negotiation transport
@@ -122,6 +122,11 @@ module Datadog
122
122
  config.tracing.contrib.global_default_service_name.enabled,
123
123
  seq_id
124
124
  ),
125
+ conf_value(
126
+ 'DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED',
127
+ config.tracing.contrib.peer_service_defaults,
128
+ seq_id
129
+ ),
125
130
  ]
126
131
 
127
132
  peer_service_mapping_str = ''
@@ -49,7 +49,7 @@ module Datadog
49
49
 
50
50
  # Re-implements Net:HTTP with underlying Unix socket
51
51
  class HTTP < ::Net::HTTP
52
- DEFAULT_TIMEOUT = 1
52
+ DEFAULT_TIMEOUT = 30
53
53
 
54
54
  attr_reader \
55
55
  :filepath, # DEV(1.0): Rename to `uds_path`
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Datadog
4
- module Tracing
4
+ module Core
5
5
  module Transport
6
6
  module HTTP
7
7
  module API
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Datadog
4
- module Tracing
4
+ module Core
5
5
  module Transport
6
6
  module HTTP
7
7
  module API
@@ -1,13 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../../../core/configuration/agent_settings_resolver'
4
- require_relative '../../../core/transport/http/adapters/registry'
5
- require_relative '../../../core/transport/http/api/map'
6
- require_relative 'api/instance'
7
- require_relative 'client'
3
+ require_relative '../../configuration/agent_settings_resolver'
4
+ require_relative 'adapters/registry'
5
+ require_relative 'api/map'
8
6
 
9
7
  module Datadog
10
- module Tracing
8
+ module Core
11
9
  module Transport
12
10
  module HTTP
13
11
  # Builds new instances of Transport::HTTP::Client
@@ -15,13 +13,14 @@ module Datadog
15
13
  REGISTRY = Datadog::Core::Transport::HTTP::Adapters::Registry.new
16
14
 
17
15
  attr_reader \
16
+ :api_instance_class,
18
17
  :apis,
19
18
  :api_options,
20
19
  :default_adapter,
21
20
  :default_api,
22
21
  :default_headers
23
22
 
24
- def initialize
23
+ def initialize(api_instance_class:)
25
24
  # Global settings
26
25
  @default_adapter = nil
27
26
  @default_headers = {}
@@ -33,6 +32,8 @@ module Datadog
33
32
  # API settings
34
33
  @api_options = {}
35
34
 
35
+ @api_instance_class = api_instance_class
36
+
36
37
  yield(self) if block_given?
37
38
  end
38
39
 
@@ -82,11 +83,10 @@ module Datadog
82
83
  @default_api = key
83
84
  end
84
85
 
85
- def to_transport
86
+ def to_transport(klass)
86
87
  raise NoDefaultApiError if @default_api.nil?
87
88
 
88
- # DEV: Should not be specific to traces
89
- Transport::Traces::Transport.new(to_api_instances, @default_api)
89
+ klass.new(to_api_instances, @default_api)
90
90
  end
91
91
 
92
92
  def to_api_instances
@@ -117,28 +117,48 @@ module Datadog
117
117
  end
118
118
  end
119
119
 
120
- def api_instance_class
121
- API::Instance
122
- end
123
-
124
120
  # Raised when the API key does not match known APIs.
125
121
  class UnknownApiError < StandardError
122
+ attr_reader :key
123
+
126
124
  def initialize(key)
127
- super("Unknown transport API '#{key}'!")
125
+ super()
126
+
127
+ @key = key
128
+ end
129
+
130
+ def message
131
+ "Unknown transport API '#{key}'!"
128
132
  end
129
133
  end
130
134
 
131
135
  # Raised when the identifier cannot be matched to an adapter.
132
136
  class UnknownAdapterError < StandardError
137
+ attr_reader :type
138
+
133
139
  def initialize(type)
134
- super("Unknown transport adapter '#{type}'!")
140
+ super()
141
+
142
+ @type = type
143
+ end
144
+
145
+ def message
146
+ "Unknown transport adapter '#{type}'!"
135
147
  end
136
148
  end
137
149
 
138
150
  # Raised when an adapter cannot be resolved for an API instance.
139
151
  class NoAdapterForApiError < StandardError
152
+ attr_reader :key
153
+
140
154
  def initialize(key)
141
- super("No adapter resolved for transport API '#{key}'!")
155
+ super()
156
+
157
+ @key = key
158
+ end
159
+
160
+ def message
161
+ "No adapter resolved for transport API '#{key}'!"
142
162
  end
143
163
  end
144
164
 
@@ -55,6 +55,10 @@ module Datadog
55
55
  true
56
56
  end
57
57
 
58
+ def to_s
59
+ "#{super}, error_type:#{error.class} error:#{error}"
60
+ end
61
+
58
62
  def inspect
59
63
  "#{super}, error_type:#{error.class} error:#{error}"
60
64
  end
@@ -140,16 +140,23 @@ module Datadog
140
140
  exact = registry[suffix]
141
141
  return [suffix, exact] if exact
142
142
 
143
- inexact = []
144
- registry.each do |path, iseq|
145
- if Utils.path_matches_suffix?(path, suffix)
146
- inexact << [path, iseq]
143
+ suffix = suffix.dup
144
+ loop do
145
+ inexact = []
146
+ registry.each do |path, iseq|
147
+ if Utils.path_matches_suffix?(path, suffix)
148
+ inexact << [path, iseq]
149
+ end
147
150
  end
151
+ if inexact.length > 1
152
+ raise Error::MultiplePathsMatch, "Multiple paths matched requested suffix"
153
+ end
154
+ if inexact.any?
155
+ return inexact.first
156
+ end
157
+ return nil unless suffix.include?('/')
158
+ suffix.sub!(%r{.*/+}, '')
148
159
  end
149
- if inexact.length > 1
150
- raise Error::MultiplePathsMatch, "Multiple paths matched requested suffix"
151
- end
152
- inexact.first
153
160
  end
154
161
  end
155
162
 
@@ -74,8 +74,10 @@ module Datadog
74
74
  def initialize(settings, agent_settings, logger, code_tracker: nil, telemetry: nil)
75
75
  @settings = settings
76
76
  @agent_settings = agent_settings
77
+ logger = DI::Logger.new(settings, logger)
77
78
  @logger = logger
78
79
  @telemetry = telemetry
80
+ @code_tracker = code_tracker
79
81
  @redactor = Redactor.new(settings)
80
82
  @serializer = Serializer.new(settings, redactor, telemetry: telemetry)
81
83
  @instrumenter = Instrumenter.new(settings, serializer, logger, code_tracker: code_tracker, telemetry: telemetry)
@@ -90,6 +92,7 @@ module Datadog
90
92
  attr_reader :agent_settings
91
93
  attr_reader :logger
92
94
  attr_reader :telemetry
95
+ attr_reader :code_tracker
93
96
  attr_reader :instrumenter
94
97
  attr_reader :transport
95
98
  attr_reader :probe_notifier_worker
@@ -188,6 +188,20 @@ module Datadog
188
188
  o.type :bool
189
189
  o.default false
190
190
  end
191
+
192
+ # Enable logging of dynamic instrumentation activity.
193
+ # This is quite verbose.
194
+ option :trace_logging do |o|
195
+ o.type :bool
196
+ o.default false
197
+
198
+ # Use the same environment variable as the rest of
199
+ # dd-trace-rb logging for now. Could change to a
200
+ # dedicated environment variable in the future but
201
+ # will likely need a way to turn on remote config
202
+ # debugging (since DI uses RC for configuration).
203
+ o.env 'DD_TRACE_DEBUG'
204
+ end
191
205
  end
192
206
  end
193
207
  end
@@ -7,6 +7,7 @@ module Datadog
7
7
  module Contrib
8
8
  module_function def load_now_or_later
9
9
  if Datadog::Core::Contrib::Rails::Utils.railtie_supported?
10
+ Datadog.logger.debug('di: loading contrib/railtie')
10
11
  require_relative 'contrib/railtie'
11
12
  else
12
13
  load_now
@@ -18,6 +19,7 @@ module Datadog
18
19
  # dependencies are loaded (or potentially loaded).
19
20
  module_function def load_now
20
21
  if defined?(ActiveRecord::Base)
22
+ Datadog.logger.debug('di: loading contrib/active_record')
21
23
  require_relative 'contrib/active_record'
22
24
  end
23
25
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ module Datadog
6
+ module DI
7
+ # Logger facade to add the +trace+ method.
8
+ #
9
+ # @api private
10
+ class Logger
11
+ extend Forwardable # steep:ignore
12
+
13
+ def initialize(settings, target)
14
+ @settings = settings
15
+ @target = target
16
+ end
17
+
18
+ attr_reader :settings
19
+ attr_reader :target
20
+
21
+ def_delegators :target, :debug # steep:ignore
22
+
23
+ def trace(&block)
24
+ if settings.dynamic_instrumentation.internal.trace_logging
25
+ debug(&block)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -155,11 +155,8 @@ module Datadog
155
155
  # Returns whether the provided +path+ matches the user-designated
156
156
  # file (of a line probe).
157
157
  #
158
- # If file is an absolute path (i.e., it starts with a slash), the file
159
- # must be identical to path to match.
160
- #
161
- # If file is not an absolute path, the path matches if the file is its suffix,
162
- # at a path component boundary.
158
+ # Delegates to Utils.path_can_match_spec? which performs fuzzy
159
+ # matching. See the comments in utils.rb for details.
163
160
  def file_matches?(path)
164
161
  if path.nil?
165
162
  raise ArgumentError, "Cannot match against a nil path"
@@ -167,7 +164,7 @@ module Datadog
167
164
  unless file
168
165
  raise ArgumentError, "Probe does not have a file to match against"
169
166
  end
170
- Utils.path_matches_suffix?(path, file)
167
+ Utils.path_can_match_spec?(path, file)
171
168
  end
172
169
 
173
170
  # Instrumentation module for method probes.
@@ -111,9 +111,11 @@ module Datadog
111
111
  # Always remove from pending list here because it makes the
112
112
  # API smaller and shouldn't cause any actual problems.
113
113
  @pending_probes.delete(probe.id)
114
+ logger.trace { "di: installed #{probe.type} probe at #{probe.location} (#{probe.id})" }
114
115
  true
115
116
  rescue Error::DITargetNotDefined
116
117
  @pending_probes[probe.id] = probe
118
+ logger.trace { "di: could not install #{probe.type} probe at #{probe.location} (#{probe.id}) because its target is not defined, adding it to pending list" }
117
119
  false
118
120
  end
119
121
  rescue => exc
@@ -160,7 +162,7 @@ module Datadog
160
162
  raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
161
163
  # Silence all exceptions?
162
164
  # TODO should we propagate here and rescue upstream?
163
- logger.debug { "di: error removing probe #{probe.id}: #{exc.class}: #{exc}" }
165
+ logger.debug { "di: error removing #{probe.type} probe at #{probe.location} (#{probe.id}): #{exc.class}: #{exc}" }
164
166
  telemetry&.report(exc, description: "Error removing probe")
165
167
  end
166
168
  end
@@ -190,7 +192,7 @@ module Datadog
190
192
  rescue => exc
191
193
  raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
192
194
 
193
- logger.debug { "di: error installing probe after class is defined: #{exc.class}: #{exc}" }
195
+ logger.debug { "di: error installing #{probe.type} probe at #{probe.location} (#{probe.id}) after class is defined: #{exc.class}: #{exc}" }
194
196
  telemetry&.report(exc, description: "Error installing probe after class is defined")
195
197
  end
196
198
  end
@@ -228,6 +230,7 @@ module Datadog
228
230
  # backend (once per the probe's lifetime) and a snapshot corresponding
229
231
  # to the current invocation.
230
232
  def probe_executed_callback(probe:, **opts)
233
+ logger.trace { "di: executed #{probe.type} probe at #{probe.location} (#{probe.id})" }
231
234
  unless probe.emitting_notified?
232
235
  payload = probe_notification_builder.build_emitting(probe)
233
236
  probe_notifier_worker.add_status(payload)
@@ -32,6 +32,12 @@ module Datadog
32
32
  status: 'EMITTING',)
33
33
  end
34
34
 
35
+ def build_errored(probe, exc)
36
+ build_status(probe,
37
+ message: "Instrumentation for probe #{probe.id} failed: #{exc}",
38
+ status: 'ERROR',)
39
+ end
40
+
35
41
  # Duration is in seconds.
36
42
  def build_executed(probe,
37
43
  trace_point: nil, rv: nil, duration: nil, caller_locations: nil,
@@ -10,7 +10,7 @@ module Datadog
10
10
  # The loop inside the worker rescues all exceptions to prevent termination
11
11
  # due to unhandled exceptions raised by any downstream code.
12
12
  # This includes communication and protocol errors when sending the
13
- # payloads to the agent.
13
+ # events to the agent.
14
14
  #
15
15
  # The worker groups the data to send into batches. The goal is to perform
16
16
  # no more than one network operation per event type per second.
@@ -36,6 +36,7 @@ module Datadog
36
36
  @sleep_remaining = nil
37
37
  @wake_scheduled = false
38
38
  @thread = nil
39
+ @pid = nil
39
40
  @flush = 0
40
41
  end
41
42
 
@@ -44,7 +45,8 @@ module Datadog
44
45
  attr_reader :telemetry
45
46
 
46
47
  def start
47
- return if @thread
48
+ return if @thread && @pid == Process.pid
49
+ logger.trace { "di: starting probe notifier: pid #{$$}" }
48
50
  @thread = Thread.new do
49
51
  loop do
50
52
  # TODO If stop is requested, we stop immediately without
@@ -86,6 +88,7 @@ module Datadog
86
88
  wake.wait(more ? min_send_interval : nil)
87
89
  end
88
90
  end
91
+ @pid = Process.pid
89
92
  end
90
93
 
91
94
  # Stops the background thread.
@@ -94,6 +97,7 @@ module Datadog
94
97
  # to killing the thread using Thread#kill.
95
98
  def stop(timeout = 1)
96
99
  @stop_requested = true
100
+ logger.trace { "di: stopping probe notifier: pid #{$$}" }
97
101
  wake.signal
98
102
  if thread
99
103
  unless thread.join(timeout)
@@ -184,8 +188,9 @@ module Datadog
184
188
  @lock.synchronize do
185
189
  queue = send("#{event_type}_queue")
186
190
  if queue.length > settings.dynamic_instrumentation.internal.snapshot_queue_capacity
187
- logger.debug { "di: #{self.class.name}: dropping #{event_type} because queue is full" }
191
+ logger.debug { "di: #{self.class.name}: dropping #{event_type} event because queue is full" }
188
192
  else
193
+ logger.trace { "di: #{self.class.name}: queueing #{event_type} event" }
189
194
  queue << event
190
195
  end
191
196
  end
@@ -200,6 +205,10 @@ module Datadog
200
205
  wake.signal
201
206
  end
202
207
  end
208
+
209
+ # Worker could be not running if the process forked - check and
210
+ # start it again in this case.
211
+ start
203
212
  end
204
213
 
205
214
  # Determine how much longer the worker thread should sleep
@@ -232,8 +241,10 @@ module Datadog
232
241
  instance_variable_set("@#{event_type}_queue", [])
233
242
  @io_in_progress = batch.any? # steep:ignore
234
243
  end
244
+ logger.trace { "di: #{self.class.name}: checking #{event_type} queue - #{batch.length} entries" } # steep:ignore
235
245
  if batch.any? # steep:ignore
236
246
  begin
247
+ logger.trace { "di: sending #{batch.length} #{event_type} event(s) to agent" } # steep:ignore
237
248
  transport.public_send("send_#{event_type}", batch)
238
249
  time = Core::Utils::Time.get_time
239
250
  @lock.synchronize do
@@ -263,7 +274,7 @@ module Datadog
263
274
 
264
275
  def maybe_send
265
276
  rv = maybe_send_status
266
- rv || maybe_send_snapshot
277
+ maybe_send_snapshot || rv
267
278
  end
268
279
  end
269
280
  end
@@ -119,7 +119,6 @@ module Datadog
119
119
  "dburl",
120
120
  "encryptionkey",
121
121
  "encryptionkeyid",
122
- "env",
123
122
  "geolocation",
124
123
  "gpgkey",
125
124
  "ipaddress",