datadog 2.7.1 → 2.17.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 (417) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +310 -1
  3. data/ext/datadog_profiling_native_extension/clock_id.h +2 -2
  4. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +66 -56
  5. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
  6. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +1 -1
  7. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +16 -16
  8. data/ext/datadog_profiling_native_extension/collectors_stack.c +10 -10
  9. data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
  10. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +314 -145
  11. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +1 -4
  12. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +10 -0
  13. data/ext/datadog_profiling_native_extension/encoded_profile.c +79 -0
  14. data/ext/datadog_profiling_native_extension/encoded_profile.h +8 -0
  15. data/ext/datadog_profiling_native_extension/extconf.rb +7 -8
  16. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +2 -0
  17. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +0 -8
  18. data/ext/datadog_profiling_native_extension/heap_recorder.c +61 -174
  19. data/ext/datadog_profiling_native_extension/heap_recorder.h +2 -2
  20. data/ext/datadog_profiling_native_extension/http_transport.c +64 -98
  21. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +68 -1
  22. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +10 -1
  23. data/ext/datadog_profiling_native_extension/profiling.c +19 -8
  24. data/ext/datadog_profiling_native_extension/ruby_helpers.c +8 -8
  25. data/ext/datadog_profiling_native_extension/stack_recorder.c +84 -131
  26. data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -2
  27. data/ext/datadog_profiling_native_extension/time_helpers.h +1 -1
  28. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +47 -0
  29. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +31 -0
  30. data/ext/libdatadog_api/crashtracker.c +17 -15
  31. data/ext/libdatadog_api/crashtracker.h +5 -0
  32. data/ext/libdatadog_api/datadog_ruby_common.c +1 -4
  33. data/ext/libdatadog_api/datadog_ruby_common.h +10 -0
  34. data/ext/libdatadog_api/init.c +15 -0
  35. data/ext/libdatadog_api/library_config.c +122 -0
  36. data/ext/libdatadog_api/library_config.h +19 -0
  37. data/ext/libdatadog_api/macos_development.md +3 -3
  38. data/ext/libdatadog_api/process_discovery.c +117 -0
  39. data/ext/libdatadog_api/process_discovery.h +5 -0
  40. data/ext/libdatadog_extconf_helpers.rb +1 -1
  41. data/lib/datadog/appsec/actions_handler/serializable_backtrace.rb +89 -0
  42. data/lib/datadog/appsec/actions_handler.rb +49 -0
  43. data/lib/datadog/appsec/anonymizer.rb +16 -0
  44. data/lib/datadog/appsec/api_security/lru_cache.rb +49 -0
  45. data/lib/datadog/appsec/api_security.rb +9 -0
  46. data/lib/datadog/appsec/assets/waf_rules/README.md +50 -5
  47. data/lib/datadog/appsec/assets/waf_rules/processors.json +239 -10
  48. data/lib/datadog/appsec/assets/waf_rules/recommended.json +355 -157
  49. data/lib/datadog/appsec/assets/waf_rules/scanners.json +926 -17
  50. data/lib/datadog/appsec/assets/waf_rules/strict.json +62 -32
  51. data/lib/datadog/appsec/autoload.rb +1 -1
  52. data/lib/datadog/appsec/component.rb +41 -33
  53. data/lib/datadog/appsec/compressed_json.rb +40 -0
  54. data/lib/datadog/appsec/configuration/settings.rb +152 -25
  55. data/lib/datadog/appsec/context.rb +74 -0
  56. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +92 -0
  57. data/lib/datadog/appsec/contrib/active_record/integration.rb +41 -0
  58. data/lib/datadog/appsec/contrib/active_record/patcher.rb +101 -0
  59. data/lib/datadog/appsec/contrib/auto_instrument.rb +1 -1
  60. data/lib/datadog/appsec/contrib/devise/configuration.rb +52 -0
  61. data/lib/datadog/appsec/contrib/devise/data_extractor.rb +78 -0
  62. data/lib/datadog/appsec/contrib/devise/ext.rb +22 -0
  63. data/lib/datadog/appsec/contrib/devise/integration.rb +1 -2
  64. data/lib/datadog/appsec/contrib/devise/patcher.rb +33 -25
  65. data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +102 -0
  66. data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +69 -0
  67. data/lib/datadog/appsec/contrib/devise/{patcher/rememberable_patch.rb → patches/skip_signin_tracking_patch.rb} +3 -3
  68. data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +106 -0
  69. data/lib/datadog/appsec/contrib/excon/integration.rb +41 -0
  70. data/lib/datadog/appsec/contrib/excon/patcher.rb +28 -0
  71. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +42 -0
  72. data/lib/datadog/appsec/contrib/faraday/connection_patch.rb +22 -0
  73. data/lib/datadog/appsec/contrib/faraday/integration.rb +42 -0
  74. data/lib/datadog/appsec/contrib/faraday/patcher.rb +53 -0
  75. data/lib/datadog/appsec/contrib/faraday/rack_builder_patch.rb +22 -0
  76. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +41 -0
  77. data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +1 -7
  78. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +17 -30
  79. data/lib/datadog/appsec/contrib/graphql/integration.rb +1 -1
  80. data/lib/datadog/appsec/contrib/graphql/patcher.rb +0 -3
  81. data/lib/datadog/appsec/contrib/rack/ext.rb +34 -0
  82. data/lib/datadog/appsec/contrib/rack/gateway/response.rb +3 -3
  83. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +78 -98
  84. data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
  85. data/lib/datadog/appsec/contrib/rack/patcher.rb +0 -3
  86. data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +10 -11
  87. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +52 -68
  88. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +16 -33
  89. data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
  90. data/lib/datadog/appsec/contrib/rails/patcher.rb +25 -38
  91. data/lib/datadog/appsec/contrib/rest_client/integration.rb +45 -0
  92. data/lib/datadog/appsec/contrib/rest_client/patcher.rb +28 -0
  93. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +38 -0
  94. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +31 -68
  95. data/lib/datadog/appsec/contrib/sinatra/integration.rb +1 -1
  96. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +5 -31
  97. data/lib/datadog/appsec/event.rb +96 -135
  98. data/lib/datadog/appsec/ext.rb +12 -3
  99. data/lib/datadog/appsec/instrumentation/gateway/argument.rb +7 -2
  100. data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +24 -0
  101. data/lib/datadog/appsec/instrumentation/gateway.rb +17 -22
  102. data/lib/datadog/appsec/metrics/collector.rb +38 -0
  103. data/lib/datadog/appsec/metrics/exporter.rb +35 -0
  104. data/lib/datadog/appsec/metrics/telemetry.rb +23 -0
  105. data/lib/datadog/appsec/metrics.rb +13 -0
  106. data/lib/datadog/appsec/monitor/gateway/watcher.rb +52 -32
  107. data/lib/datadog/appsec/processor/rule_loader.rb +26 -31
  108. data/lib/datadog/appsec/processor/rule_merger.rb +7 -6
  109. data/lib/datadog/appsec/processor.rb +5 -4
  110. data/lib/datadog/appsec/remote.rb +26 -12
  111. data/lib/datadog/appsec/response.rb +19 -85
  112. data/lib/datadog/appsec/security_engine/result.rb +67 -0
  113. data/lib/datadog/appsec/security_engine/runner.rb +88 -0
  114. data/lib/datadog/appsec/security_engine.rb +9 -0
  115. data/lib/datadog/appsec/security_event.rb +39 -0
  116. data/lib/datadog/appsec/utils.rb +0 -2
  117. data/lib/datadog/appsec.rb +23 -10
  118. data/lib/datadog/auto_instrument.rb +3 -0
  119. data/lib/datadog/core/buffer/random.rb +18 -2
  120. data/lib/datadog/core/configuration/agent_settings_resolver.rb +42 -14
  121. data/lib/datadog/core/configuration/agentless_settings_resolver.rb +176 -0
  122. data/lib/datadog/core/configuration/components.rb +76 -32
  123. data/lib/datadog/core/configuration/components_state.rb +23 -0
  124. data/lib/datadog/core/configuration/ext.rb +5 -1
  125. data/lib/datadog/core/configuration/option.rb +79 -43
  126. data/lib/datadog/core/configuration/option_definition.rb +6 -4
  127. data/lib/datadog/core/configuration/options.rb +3 -3
  128. data/lib/datadog/core/configuration/settings.rb +100 -41
  129. data/lib/datadog/core/configuration/stable_config.rb +23 -0
  130. data/lib/datadog/core/configuration.rb +43 -11
  131. data/lib/datadog/{tracing → core}/contrib/rails/utils.rb +1 -3
  132. data/lib/datadog/core/crashtracking/component.rb +4 -13
  133. data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
  134. data/lib/datadog/core/encoding.rb +17 -1
  135. data/lib/datadog/core/environment/agent_info.rb +78 -0
  136. data/lib/datadog/core/environment/cgroup.rb +10 -12
  137. data/lib/datadog/core/environment/container.rb +38 -40
  138. data/lib/datadog/core/environment/ext.rb +6 -6
  139. data/lib/datadog/core/environment/git.rb +1 -0
  140. data/lib/datadog/core/environment/identity.rb +3 -3
  141. data/lib/datadog/core/environment/platform.rb +3 -3
  142. data/lib/datadog/core/environment/variable_helpers.rb +1 -1
  143. data/lib/datadog/core/error.rb +11 -9
  144. data/lib/datadog/core/logger.rb +2 -2
  145. data/lib/datadog/core/metrics/client.rb +27 -27
  146. data/lib/datadog/core/metrics/logging.rb +5 -5
  147. data/lib/datadog/core/process_discovery.rb +32 -0
  148. data/lib/datadog/core/rate_limiter.rb +4 -2
  149. data/lib/datadog/core/remote/client/capabilities.rb +6 -0
  150. data/lib/datadog/core/remote/client.rb +107 -92
  151. data/lib/datadog/core/remote/component.rb +18 -19
  152. data/lib/datadog/core/remote/configuration/digest.rb +7 -7
  153. data/lib/datadog/core/remote/configuration/path.rb +1 -1
  154. data/lib/datadog/core/remote/configuration/repository.rb +2 -1
  155. data/lib/datadog/core/remote/negotiation.rb +9 -9
  156. data/lib/datadog/core/remote/transport/config.rb +4 -3
  157. data/lib/datadog/core/remote/transport/http/api.rb +13 -18
  158. data/lib/datadog/core/remote/transport/http/client.rb +5 -4
  159. data/lib/datadog/core/remote/transport/http/config.rb +27 -55
  160. data/lib/datadog/core/remote/transport/http/negotiation.rb +8 -51
  161. data/lib/datadog/core/remote/transport/http.rb +25 -94
  162. data/lib/datadog/core/remote/transport/negotiation.rb +17 -4
  163. data/lib/datadog/core/remote/worker.rb +10 -7
  164. data/lib/datadog/core/runtime/metrics.rb +12 -5
  165. data/lib/datadog/core/telemetry/component.rb +84 -49
  166. data/lib/datadog/core/telemetry/emitter.rb +23 -11
  167. data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +65 -0
  168. data/lib/datadog/core/telemetry/event/app_closing.rb +18 -0
  169. data/lib/datadog/core/telemetry/event/app_dependencies_loaded.rb +33 -0
  170. data/lib/datadog/core/telemetry/event/app_heartbeat.rb +18 -0
  171. data/lib/datadog/core/telemetry/event/app_integrations_change.rb +58 -0
  172. data/lib/datadog/core/telemetry/event/app_started.rb +179 -0
  173. data/lib/datadog/core/telemetry/event/base.rb +40 -0
  174. data/lib/datadog/core/telemetry/event/distributions.rb +18 -0
  175. data/lib/datadog/core/telemetry/event/generate_metrics.rb +43 -0
  176. data/lib/datadog/core/telemetry/event/log.rb +76 -0
  177. data/lib/datadog/core/telemetry/event/message_batch.rb +42 -0
  178. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +43 -0
  179. data/lib/datadog/core/telemetry/event.rb +17 -383
  180. data/lib/datadog/core/telemetry/ext.rb +1 -0
  181. data/lib/datadog/core/telemetry/http/adapters/net.rb +12 -97
  182. data/lib/datadog/core/telemetry/logger.rb +1 -1
  183. data/lib/datadog/core/telemetry/logging.rb +2 -2
  184. data/lib/datadog/core/telemetry/metric.rb +28 -6
  185. data/lib/datadog/core/telemetry/request.rb +4 -4
  186. data/lib/datadog/core/telemetry/transport/http/api.rb +43 -0
  187. data/lib/datadog/core/telemetry/transport/http/client.rb +49 -0
  188. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +92 -0
  189. data/lib/datadog/core/telemetry/transport/http.rb +63 -0
  190. data/lib/datadog/core/telemetry/transport/telemetry.rb +51 -0
  191. data/lib/datadog/core/telemetry/worker.rb +128 -25
  192. data/lib/datadog/core/transport/http/adapters/test.rb +2 -1
  193. data/lib/datadog/core/transport/http/adapters/unix_socket.rb +1 -1
  194. data/lib/datadog/{tracing → core}/transport/http/api/instance.rb +18 -1
  195. data/lib/datadog/core/transport/http/api/spec.rb +36 -0
  196. data/lib/datadog/{tracing → core}/transport/http/builder.rb +53 -31
  197. data/lib/datadog/core/transport/http.rb +75 -0
  198. data/lib/datadog/core/transport/response.rb +4 -0
  199. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +6 -6
  200. data/lib/datadog/core/utils/duration.rb +32 -32
  201. data/lib/datadog/core/utils/forking.rb +2 -2
  202. data/lib/datadog/core/utils/network.rb +6 -6
  203. data/lib/datadog/core/utils/only_once_successful.rb +16 -5
  204. data/lib/datadog/core/utils/time.rb +20 -0
  205. data/lib/datadog/core/utils/truncation.rb +21 -0
  206. data/lib/datadog/core/vendor/multipart-post/multipart/post/composite_read_io.rb +1 -1
  207. data/lib/datadog/core/vendor/multipart-post/multipart/post/multipartable.rb +8 -8
  208. data/lib/datadog/core/vendor/multipart-post/multipart/post/parts.rb +7 -7
  209. data/lib/datadog/core/worker.rb +1 -1
  210. data/lib/datadog/core/workers/async.rb +29 -12
  211. data/lib/datadog/core/workers/interval_loop.rb +12 -1
  212. data/lib/datadog/core/workers/runtime_metrics.rb +2 -2
  213. data/lib/datadog/core.rb +8 -0
  214. data/lib/datadog/di/base.rb +115 -0
  215. data/lib/datadog/di/boot.rb +34 -0
  216. data/lib/datadog/di/code_tracker.rb +26 -15
  217. data/lib/datadog/di/component.rb +23 -14
  218. data/lib/datadog/di/configuration/settings.rb +25 -1
  219. data/lib/datadog/di/contrib/active_record.rb +1 -0
  220. data/lib/datadog/di/contrib/railtie.rb +15 -0
  221. data/lib/datadog/di/contrib.rb +28 -0
  222. data/lib/datadog/di/error.rb +5 -0
  223. data/lib/datadog/di/instrumenter.rb +111 -20
  224. data/lib/datadog/di/logger.rb +30 -0
  225. data/lib/datadog/di/preload.rb +18 -0
  226. data/lib/datadog/di/probe.rb +14 -7
  227. data/lib/datadog/di/probe_builder.rb +1 -0
  228. data/lib/datadog/di/probe_manager.rb +11 -5
  229. data/lib/datadog/di/probe_notification_builder.rb +34 -8
  230. data/lib/datadog/di/probe_notifier_worker.rb +52 -26
  231. data/lib/datadog/di/redactor.rb +0 -1
  232. data/lib/datadog/di/remote.rb +147 -0
  233. data/lib/datadog/di/serializer.rb +14 -7
  234. data/lib/datadog/di/transport/diagnostics.rb +62 -0
  235. data/lib/datadog/di/transport/http/api.rb +42 -0
  236. data/lib/datadog/di/transport/http/client.rb +47 -0
  237. data/lib/datadog/di/transport/http/diagnostics.rb +65 -0
  238. data/lib/datadog/di/transport/http/input.rb +67 -0
  239. data/lib/datadog/di/transport/http.rb +57 -0
  240. data/lib/datadog/di/transport/input.rb +62 -0
  241. data/lib/datadog/di/utils.rb +103 -0
  242. data/lib/datadog/di.rb +14 -76
  243. data/lib/datadog/error_tracking/collector.rb +87 -0
  244. data/lib/datadog/error_tracking/component.rb +167 -0
  245. data/lib/datadog/error_tracking/configuration/settings.rb +63 -0
  246. data/lib/datadog/error_tracking/configuration.rb +11 -0
  247. data/lib/datadog/error_tracking/ext.rb +18 -0
  248. data/lib/datadog/error_tracking/extensions.rb +16 -0
  249. data/lib/datadog/error_tracking/filters.rb +77 -0
  250. data/lib/datadog/error_tracking.rb +18 -0
  251. data/lib/datadog/kit/appsec/events.rb +15 -3
  252. data/lib/datadog/kit/identity.rb +9 -5
  253. data/lib/datadog/opentelemetry/api/baggage.rb +90 -0
  254. data/lib/datadog/opentelemetry/api/baggage.rbs +26 -0
  255. data/lib/datadog/opentelemetry/api/context.rb +16 -2
  256. data/lib/datadog/opentelemetry/sdk/trace/span.rb +1 -1
  257. data/lib/datadog/opentelemetry.rb +2 -1
  258. data/lib/datadog/profiling/collectors/code_provenance.rb +1 -1
  259. data/lib/datadog/profiling/collectors/info.rb +3 -0
  260. data/lib/datadog/profiling/collectors/thread_context.rb +1 -1
  261. data/lib/datadog/profiling/component.rb +60 -76
  262. data/lib/datadog/profiling/encoded_profile.rb +11 -0
  263. data/lib/datadog/profiling/exporter.rb +3 -4
  264. data/lib/datadog/profiling/ext.rb +0 -2
  265. data/lib/datadog/profiling/flush.rb +5 -8
  266. data/lib/datadog/profiling/http_transport.rb +6 -85
  267. data/lib/datadog/profiling/load_native_extension.rb +1 -33
  268. data/lib/datadog/profiling/scheduler.rb +8 -1
  269. data/lib/datadog/profiling/stack_recorder.rb +4 -4
  270. data/lib/datadog/profiling/tag_builder.rb +1 -5
  271. data/lib/datadog/profiling.rb +6 -2
  272. data/lib/datadog/tracing/analytics.rb +1 -1
  273. data/lib/datadog/tracing/component.rb +16 -12
  274. data/lib/datadog/tracing/configuration/ext.rb +8 -1
  275. data/lib/datadog/tracing/configuration/settings.rb +22 -10
  276. data/lib/datadog/tracing/context_provider.rb +1 -1
  277. data/lib/datadog/tracing/contrib/action_cable/integration.rb +5 -2
  278. data/lib/datadog/tracing/contrib/action_mailer/integration.rb +6 -2
  279. data/lib/datadog/tracing/contrib/action_pack/integration.rb +5 -2
  280. data/lib/datadog/tracing/contrib/action_view/integration.rb +5 -2
  281. data/lib/datadog/tracing/contrib/active_job/integration.rb +5 -2
  282. data/lib/datadog/tracing/contrib/active_record/integration.rb +7 -3
  283. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +7 -2
  284. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +36 -1
  285. data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +4 -0
  286. data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +14 -4
  287. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +10 -0
  288. data/lib/datadog/tracing/contrib/active_support/integration.rb +5 -2
  289. data/lib/datadog/tracing/contrib/auto_instrument.rb +2 -2
  290. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +10 -0
  291. data/lib/datadog/tracing/contrib/aws/integration.rb +3 -0
  292. data/lib/datadog/tracing/contrib/aws/parsed_context.rb +5 -1
  293. data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +3 -0
  294. data/lib/datadog/tracing/contrib/configuration/settings.rb +1 -1
  295. data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +4 -0
  296. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
  297. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -5
  298. data/lib/datadog/tracing/contrib/excon/middleware.rb +5 -3
  299. data/lib/datadog/tracing/contrib/ext.rb +1 -0
  300. data/lib/datadog/tracing/contrib/extensions.rb +29 -3
  301. data/lib/datadog/tracing/contrib/faraday/middleware.rb +5 -3
  302. data/lib/datadog/tracing/contrib/graphql/configuration/error_extension_env_parser.rb +21 -0
  303. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +11 -0
  304. data/lib/datadog/tracing/contrib/graphql/ext.rb +5 -0
  305. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +102 -11
  306. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +7 -1
  307. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +3 -0
  308. data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +0 -15
  309. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +4 -1
  310. data/lib/datadog/tracing/contrib/http/instrumentation.rb +6 -10
  311. data/lib/datadog/tracing/contrib/http/integration.rb +3 -0
  312. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -16
  313. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +7 -15
  314. data/lib/datadog/tracing/contrib/httprb/integration.rb +3 -0
  315. data/lib/datadog/tracing/contrib/kafka/integration.rb +3 -0
  316. data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +27 -0
  317. data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +48 -0
  318. data/lib/datadog/tracing/contrib/karafka/ext.rb +27 -0
  319. data/lib/datadog/tracing/contrib/karafka/integration.rb +45 -0
  320. data/lib/datadog/tracing/contrib/karafka/monitor.rb +66 -0
  321. data/lib/datadog/tracing/contrib/karafka/patcher.rb +71 -0
  322. data/lib/datadog/tracing/contrib/karafka.rb +37 -0
  323. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +8 -0
  324. data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -0
  325. data/lib/datadog/tracing/contrib/mongodb/integration.rb +3 -0
  326. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +18 -1
  327. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +17 -0
  328. data/lib/datadog/tracing/contrib/opensearch/ext.rb +9 -0
  329. data/lib/datadog/tracing/contrib/opensearch/integration.rb +3 -0
  330. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +5 -1
  331. data/lib/datadog/tracing/contrib/patcher.rb +5 -2
  332. data/lib/datadog/tracing/contrib/presto/integration.rb +3 -0
  333. data/lib/datadog/tracing/contrib/rack/header_collection.rb +11 -1
  334. data/lib/datadog/tracing/contrib/rack/integration.rb +2 -2
  335. data/lib/datadog/tracing/contrib/rack/middlewares.rb +1 -1
  336. data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
  337. data/lib/datadog/tracing/contrib/rails/framework.rb +2 -2
  338. data/lib/datadog/tracing/contrib/rails/patcher.rb +1 -1
  339. data/lib/datadog/tracing/contrib/rest_client/integration.rb +3 -0
  340. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +5 -3
  341. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +6 -1
  342. data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +3 -0
  343. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +1 -1
  344. data/lib/datadog/tracing/contrib/span_attribute_schema.rb +6 -1
  345. data/lib/datadog/tracing/contrib/support.rb +28 -0
  346. data/lib/datadog/tracing/contrib.rb +1 -0
  347. data/lib/datadog/tracing/correlation.rb +9 -2
  348. data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
  349. data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
  350. data/lib/datadog/tracing/distributed/baggage.rb +131 -0
  351. data/lib/datadog/tracing/distributed/datadog.rb +4 -2
  352. data/lib/datadog/tracing/distributed/propagation.rb +25 -4
  353. data/lib/datadog/tracing/distributed/propagation_policy.rb +42 -0
  354. data/lib/datadog/tracing/metadata/errors.rb +4 -4
  355. data/lib/datadog/tracing/metadata/ext.rb +5 -0
  356. data/lib/datadog/tracing/metadata/metastruct.rb +36 -0
  357. data/lib/datadog/tracing/metadata/metastruct_tagging.rb +42 -0
  358. data/lib/datadog/tracing/metadata.rb +2 -0
  359. data/lib/datadog/tracing/sampling/rate_sampler.rb +2 -1
  360. data/lib/datadog/tracing/sampling/span/rule.rb +0 -1
  361. data/lib/datadog/tracing/span.rb +22 -5
  362. data/lib/datadog/tracing/span_event.rb +124 -4
  363. data/lib/datadog/tracing/span_operation.rb +52 -16
  364. data/lib/datadog/tracing/sync_writer.rb +9 -5
  365. data/lib/datadog/tracing/trace_digest.rb +9 -2
  366. data/lib/datadog/tracing/trace_operation.rb +44 -24
  367. data/lib/datadog/tracing/trace_segment.rb +6 -4
  368. data/lib/datadog/tracing/tracer.rb +60 -12
  369. data/lib/datadog/tracing/transport/http/api.rb +5 -4
  370. data/lib/datadog/tracing/transport/http/client.rb +5 -4
  371. data/lib/datadog/tracing/transport/http/traces.rb +13 -44
  372. data/lib/datadog/tracing/transport/http.rb +13 -70
  373. data/lib/datadog/tracing/transport/serializable_trace.rb +31 -7
  374. data/lib/datadog/tracing/transport/trace_formatter.rb +7 -0
  375. data/lib/datadog/tracing/transport/traces.rb +47 -13
  376. data/lib/datadog/tracing/utils.rb +1 -1
  377. data/lib/datadog/tracing/workers/trace_writer.rb +8 -5
  378. data/lib/datadog/tracing/workers.rb +5 -4
  379. data/lib/datadog/tracing/writer.rb +10 -6
  380. data/lib/datadog/tracing.rb +16 -3
  381. data/lib/datadog/version.rb +2 -2
  382. data/lib/datadog.rb +2 -0
  383. metadata +143 -50
  384. data/ext/datadog_profiling_loader/datadog_profiling_loader.c +0 -142
  385. data/ext/datadog_profiling_loader/extconf.rb +0 -60
  386. data/lib/datadog/appsec/contrib/devise/event.rb +0 -57
  387. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +0 -77
  388. data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +0 -54
  389. data/lib/datadog/appsec/contrib/devise/resource.rb +0 -35
  390. data/lib/datadog/appsec/contrib/devise/tracking.rb +0 -57
  391. data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +0 -46
  392. data/lib/datadog/appsec/contrib/patcher.rb +0 -12
  393. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +0 -69
  394. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +0 -47
  395. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +0 -53
  396. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +0 -53
  397. data/lib/datadog/appsec/contrib/sinatra/ext.rb +0 -14
  398. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +0 -48
  399. data/lib/datadog/appsec/monitor/reactive/set_user.rb +0 -45
  400. data/lib/datadog/appsec/processor/actions.rb +0 -49
  401. data/lib/datadog/appsec/processor/context.rb +0 -107
  402. data/lib/datadog/appsec/reactive/address_hash.rb +0 -22
  403. data/lib/datadog/appsec/reactive/engine.rb +0 -47
  404. data/lib/datadog/appsec/reactive/operation.rb +0 -68
  405. data/lib/datadog/appsec/reactive/subscriber.rb +0 -19
  406. data/lib/datadog/appsec/scope.rb +0 -58
  407. data/lib/datadog/appsec/utils/trace_operation.rb +0 -15
  408. data/lib/datadog/core/crashtracking/agent_base_url.rb +0 -21
  409. data/lib/datadog/core/remote/transport/http/api/instance.rb +0 -39
  410. data/lib/datadog/core/remote/transport/http/api/spec.rb +0 -21
  411. data/lib/datadog/core/remote/transport/http/builder.rb +0 -219
  412. data/lib/datadog/core/telemetry/http/env.rb +0 -20
  413. data/lib/datadog/core/telemetry/http/ext.rb +0 -28
  414. data/lib/datadog/core/telemetry/http/response.rb +0 -70
  415. data/lib/datadog/core/telemetry/http/transport.rb +0 -90
  416. data/lib/datadog/di/transport.rb +0 -81
  417. data/lib/datadog/tracing/transport/http/api/spec.rb +0 -19
@@ -14,20 +14,22 @@ module Datadog
14
14
  # resources and installed tracepoints upon shutdown.
15
15
  class Component
16
16
  class << self
17
- def build(settings, agent_settings, telemetry: nil)
17
+ def build(settings, agent_settings, logger, telemetry: nil)
18
18
  return unless settings.respond_to?(:dynamic_instrumentation) && settings.dynamic_instrumentation.enabled
19
19
 
20
20
  unless settings.respond_to?(:remote) && settings.remote.enabled
21
- Datadog.logger.debug("Dynamic Instrumentation could not be enabled because Remote Configuration Management is not available. To enable Remote Configuration, see https://docs.datadoghq.com/agent/remote_config")
21
+ logger.warn("di: dynamic instrumentation could not be enabled because Remote Configuration Management is not available. To enable Remote Configuration, see https://docs.datadoghq.com/agent/remote_config")
22
22
  return
23
23
  end
24
24
 
25
- return unless environment_supported?(settings)
25
+ return unless environment_supported?(settings, logger)
26
26
 
27
- new(settings, agent_settings, Datadog.logger, code_tracker: DI.code_tracker, telemetry: telemetry)
27
+ new(settings, agent_settings, logger, code_tracker: DI.code_tracker, telemetry: telemetry).tap do |component|
28
+ DI.add_current_component(component)
29
+ end
28
30
  end
29
31
 
30
- def build!(settings, agent_settings, telemetry: nil)
32
+ def build!(settings, agent_settings, logger, telemetry: nil)
31
33
  unless settings.respond_to?(:dynamic_instrumentation) && settings.dynamic_instrumentation.enabled
32
34
  raise "Requested DI component but DI is not enabled in settings"
33
35
  end
@@ -36,27 +38,31 @@ module Datadog
36
38
  raise "Requested DI component but remote config is not enabled in settings"
37
39
  end
38
40
 
39
- unless environment_supported?(settings)
41
+ unless environment_supported?(settings, logger)
40
42
  raise "DI does not support the environment (development or Ruby version too low or not MRI)"
41
43
  end
42
44
 
43
- new(settings, agent_settings, Datadog.logger, code_tracker: DI.code_tracker, telemetry: telemetry)
45
+ new(settings, agent_settings, logger, code_tracker: DI.code_tracker, telemetry: telemetry)
44
46
  end
45
47
 
46
48
  # Checks whether the runtime environment is supported by
47
49
  # dynamic instrumentation. Currently we only require that, if Rails
48
50
  # is used, that Rails environment is not development because
49
51
  # DI does not currently support code unloading and reloading.
50
- def environment_supported?(settings)
52
+ def environment_supported?(settings, logger)
51
53
  # TODO add tests?
52
54
  unless settings.dynamic_instrumentation.internal.development
53
55
  if Datadog::Core::Environment::Execution.development?
54
- Datadog.logger.debug("Not enabling dynamic instrumentation because we are in development environment")
56
+ logger.warn("di: development environment detected; not enabling dynamic instrumentation")
55
57
  return false
56
58
  end
57
59
  end
58
- if RUBY_ENGINE != 'ruby' || RUBY_VERSION < '2.6'
59
- Datadog.logger.debug("Not enabling dynamic instrumentation because of unsupported Ruby version")
60
+ if RUBY_ENGINE != 'ruby'
61
+ logger.warn("di: cannot enable dynamic instrumentation: MRI is required, but running on #{RUBY_ENGINE}")
62
+ return false
63
+ end
64
+ if RUBY_VERSION < '2.6'
65
+ logger.warn("di: cannot enable dynamic instrumentation: Ruby 2.6+ is required, but running on #{RUBY_VERSION}")
60
66
  return false
61
67
  end
62
68
  true
@@ -66,13 +72,14 @@ module Datadog
66
72
  def initialize(settings, agent_settings, logger, code_tracker: nil, telemetry: nil)
67
73
  @settings = settings
68
74
  @agent_settings = agent_settings
75
+ logger = DI::Logger.new(settings, logger)
69
76
  @logger = logger
70
77
  @telemetry = telemetry
78
+ @code_tracker = code_tracker
71
79
  @redactor = Redactor.new(settings)
72
80
  @serializer = Serializer.new(settings, redactor, telemetry: telemetry)
73
81
  @instrumenter = Instrumenter.new(settings, serializer, logger, code_tracker: code_tracker, telemetry: telemetry)
74
- @transport = Transport.new(agent_settings)
75
- @probe_notifier_worker = ProbeNotifierWorker.new(settings, transport, logger, telemetry: telemetry)
82
+ @probe_notifier_worker = ProbeNotifierWorker.new(settings, logger, agent_settings: agent_settings, telemetry: telemetry)
76
83
  @probe_notification_builder = ProbeNotificationBuilder.new(settings, serializer)
77
84
  @probe_manager = ProbeManager.new(settings, instrumenter, probe_notification_builder, probe_notifier_worker, logger, telemetry: telemetry)
78
85
  probe_notifier_worker.start
@@ -82,8 +89,8 @@ module Datadog
82
89
  attr_reader :agent_settings
83
90
  attr_reader :logger
84
91
  attr_reader :telemetry
92
+ attr_reader :code_tracker
85
93
  attr_reader :instrumenter
86
- attr_reader :transport
87
94
  attr_reader :probe_notifier_worker
88
95
  attr_reader :probe_notification_builder
89
96
  attr_reader :probe_manager
@@ -99,6 +106,8 @@ module Datadog
99
106
  # was replaced by a new instance, the new instance of it wouldn't have
100
107
  # any of the already loaded code tracked.
101
108
  def shutdown!(replacement = nil)
109
+ DI.remove_current_component(self)
110
+
102
111
  probe_manager.clear_hooks
103
112
  probe_manager.close
104
113
  probe_notifier_worker.stop
@@ -166,10 +166,20 @@ module Datadog
166
166
  # being sent out by the probe notifier worker) and creates a
167
167
  # possibility of dropping payloads if the queue gets too long.
168
168
  option :min_send_interval do |o|
169
- o.type :int
169
+ o.type :float
170
170
  o.default 3
171
171
  end
172
172
 
173
+ # Number of snapshots that can be stored in the probe
174
+ # notifier worker queue. Larger capacity runs the risk of
175
+ # creating snapshots that exceed the agent's request size
176
+ # limit. Smaller capacity increases the risk of dropping
177
+ # snapshots.
178
+ option :snapshot_queue_capacity do |o|
179
+ o.type :int
180
+ o.default 100
181
+ end
182
+
173
183
  # Enable dynamic instrumentation in development environments.
174
184
  # Currently DI does not fully implement support for code
175
185
  # unloading and reloading, and is not supported in
@@ -178,6 +188,20 @@ module Datadog
178
188
  o.type :bool
179
189
  o.default false
180
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
181
205
  end
182
206
  end
183
207
  end
@@ -5,6 +5,7 @@ Datadog::DI::Serializer.register(condition: lambda { |value| ActiveRecord::Base
5
5
  # steep:ignore:start
6
6
  value_to_serialize = {
7
7
  attributes: value.attributes,
8
+ new_record: value.new_record?,
8
9
  }
9
10
  serializer.serialize_value(value_to_serialize, depth: depth ? depth - 1 : nil, type: value.class)
10
11
  # steep:ignore:end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module DI
5
+ module Contrib
6
+ # Railtie class initializes dynamic instrumentation contrib code
7
+ # in Rails environments.
8
+ class Railtie < Rails::Railtie
9
+ initializer 'datadog.dynamic_instrumentation.initialize' do |app|
10
+ Contrib.load_now
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../core/contrib/rails/utils'
4
+
5
+ module Datadog
6
+ module DI
7
+ module Contrib
8
+ module_function def load_now_or_later
9
+ if Datadog::Core::Contrib::Rails::Utils.railtie_supported?
10
+ Datadog.logger.debug('di: loading contrib/railtie')
11
+ require_relative 'contrib/railtie'
12
+ else
13
+ load_now
14
+ end
15
+ end
16
+
17
+ # This method can be called more than once, to attempt to load
18
+ # DI components that depend on third-party libraries after additional
19
+ # dependencies are loaded (or potentially loaded).
20
+ module_function def load_now
21
+ if defined?(ActiveRecord::Base)
22
+ Datadog.logger.debug('di: loading contrib/active_record')
23
+ require_relative 'contrib/active_record'
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -27,6 +27,11 @@ module Datadog
27
27
  class DITargetNotDefined < Error
28
28
  end
29
29
 
30
+ # Attempting to instrument a line and the file containing the line
31
+ # was loaded prior to code tracking being enabled.
32
+ class DITargetNotInRegistry < Error
33
+ end
34
+
30
35
  # Raised when trying to install a probe whose installation failed
31
36
  # earlier in the same process. This exception should contain the
32
37
  # original exception report from initial installation attempt.
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # rubocop:disable Lint/AssignmentInCondition
3
+ require_relative '../core/utils/time'
4
4
 
5
- require 'benchmark'
5
+ # rubocop:disable Lint/AssignmentInCondition
6
6
 
7
7
  module Datadog
8
8
  module DI
@@ -92,34 +92,88 @@ module Datadog
92
92
  cls = symbolize_class_name(probe.type_name)
93
93
  serializer = self.serializer
94
94
  method_name = probe.method_name
95
- target_method = cls.instance_method(method_name)
96
- loc = target_method.source_location
95
+ loc = begin
96
+ cls.instance_method(method_name).source_location
97
+ rescue NameError
98
+ # The target method is not defined.
99
+ # This could be because it will be explicitly defined later
100
+ # (since classes can be reopened in Ruby)
101
+ # or the method is virtual (provided by a method_missing handler).
102
+ # In these cases we do not have a source location for the
103
+ # target method here.
104
+ end
97
105
  rate_limiter = probe.rate_limiter
106
+ settings = self.settings
98
107
 
99
108
  mod = Module.new do
100
- define_method(method_name) do |*args, **kwargs| # steep:ignore
109
+ define_method(method_name) do |*args, **kwargs, &target_block| # steep:ignore
101
110
  if rate_limiter.nil? || rate_limiter.allow?
102
111
  # Arguments may be mutated by the method, therefore
103
112
  # they need to be serialized prior to method invocation.
104
113
  entry_args = if probe.capture_snapshot?
105
- serializer.serialize_args(args, kwargs)
114
+ serializer.serialize_args(args, kwargs,
115
+ depth: probe.max_capture_depth || settings.dynamic_instrumentation.max_capture_depth,
116
+ attribute_count: probe.max_capture_attribute_count || settings.dynamic_instrumentation.max_capture_attribute_count)
106
117
  end
107
- rv = nil
108
- duration = Benchmark.realtime do # steep:ignore
109
- rv = super(*args, **kwargs)
118
+ start_time = Core::Utils::Time.get_time
119
+ # Under Ruby 2.6 we cannot just call super(*args, **kwargs)
120
+ # for methods defined via method_missing.
121
+ rv = if args.any?
122
+ if kwargs.any?
123
+ super(*args, **kwargs, &target_block)
124
+ else
125
+ super(*args, &target_block)
126
+ end
127
+ elsif kwargs.any?
128
+ super(**kwargs, &target_block)
129
+ else
130
+ super(&target_block)
110
131
  end
132
+ duration = Core::Utils::Time.get_time - start_time
111
133
  # The method itself is not part of the stack trace because
112
134
  # we are getting the stack trace from outside of the method.
113
135
  # Add the method in manually as the top frame.
114
- method_frame = Location.new(loc.first, loc.last, method_name)
115
- caller_locs = [method_frame] + caller_locations # steep:ignore
136
+ method_frame = if loc
137
+ [Location.new(loc.first, loc.last, method_name)]
138
+ else
139
+ # For virtual and lazily-defined methods, we do not have
140
+ # the original source location here, and they won't be
141
+ # included in the stack trace currently.
142
+ # TODO when begin/end trace points are added for local
143
+ # variable capture in method probes, we should be able
144
+ # to obtain actual method execution location and use
145
+ # that location here.
146
+ []
147
+ end
148
+ caller_locs = method_frame + caller_locations # steep:ignore
116
149
  # TODO capture arguments at exit
117
150
  # & is to stop steep complaints, block is always present here.
118
151
  block&.call(probe: probe, rv: rv, duration: duration, caller_locations: caller_locs,
119
152
  serialized_entry_args: entry_args)
120
153
  rv
121
154
  else
122
- super(*args, **kwargs)
155
+ # stop standard from trying to mess up my code
156
+ _ = 42
157
+
158
+ # The necessity to invoke super in each of these specific
159
+ # ways is very difficult to test.
160
+ # Existing tests, even though I wrote many, still don't
161
+ # cause a failure if I replace all of the below with a
162
+ # simple super(*args, **kwargs, &target_block).
163
+ # But, let's be safe and go through the motions in case
164
+ # there is actually a legitimate need for the breakdown.
165
+ # TODO figure out how to test this properly.
166
+ if args.any?
167
+ if kwargs.any?
168
+ super(*args, **kwargs, &target_block)
169
+ else
170
+ super(*args, &target_block)
171
+ end
172
+ elsif kwargs.any?
173
+ super(**kwargs, &target_block)
174
+ else
175
+ super(&target_block)
176
+ end
123
177
  end
124
178
  end
125
179
  end
@@ -191,11 +245,12 @@ module Datadog
191
245
  #
192
246
  # If the requested file is not in code tracker's registry,
193
247
  # or the code tracker does not exist at all,
194
- # do not attempt to instrumnet now.
248
+ # do not attempt to instrument now.
195
249
  # The caller should add the line to the list of pending lines
196
250
  # to instrument and install the hook when the file in
197
251
  # question is loaded (and hopefully, by then code tracking
198
252
  # is active, otherwise the line will never be instrumented.)
253
+ raise_if_probe_in_loaded_features(probe)
199
254
  raise Error::DITargetNotDefined, "File not in code tracker registry: #{probe.file}"
200
255
  end
201
256
  end
@@ -203,6 +258,7 @@ module Datadog
203
258
  # Same as previous comment, if untargeted trace points are not
204
259
  # explicitly defined, and we do not have code tracking, do not
205
260
  # instrument the method.
261
+ raise_if_probe_in_loaded_features(probe)
206
262
  raise Error::DITargetNotDefined, "File not in code tracker registry: #{probe.file}"
207
263
  end
208
264
 
@@ -222,12 +278,25 @@ module Datadog
222
278
  # overhead of targeted trace points is minimal, don't worry about
223
279
  # this optimization just yet and create a trace point for each probe.
224
280
 
225
- tp = TracePoint.new(:line) do |tp|
281
+ types = if iseq
282
+ # When targeting trace points we can target the 'end' line of a method.
283
+ # However, by adding the :return trace point we lose diagnostics
284
+ # for lines that contain no executable code (e.g. comments only)
285
+ # and thus cannot actually be instrumented.
286
+ [:line, :return, :b_return]
287
+ else
288
+ [:line]
289
+ end
290
+ tp = TracePoint.new(*types) do |tp|
226
291
  begin
227
292
  # If trace point is not targeted, we must verify that the invocation
228
293
  # is the file & line that we want, because untargeted trace points
229
294
  # are invoked for *each* line of Ruby executed.
230
- if iseq || tp.lineno == probe.line_no && probe.file_matches?(tp.path)
295
+ # TODO find out exactly when the path in trace point is relative.
296
+ # Looks like this is the case when line trace point is not targeted?
297
+ if iseq || tp.lineno == probe.line_no && (
298
+ probe.file == tp.path || probe.file_matches?(tp.path)
299
+ )
231
300
  if rate_limiter.nil? || rate_limiter.allow?
232
301
  # & is to stop steep complaints, block is always present here.
233
302
  block&.call(probe: probe, trace_point: tp, caller_locations: caller_locations)
@@ -235,13 +304,13 @@ module Datadog
235
304
  end
236
305
  rescue => exc
237
306
  raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
238
- logger.warn("Unhandled exception in line trace point: #{exc.class}: #{exc}")
307
+ logger.debug { "di: unhandled exception in line trace point: #{exc.class}: #{exc}" }
239
308
  telemetry&.report(exc, description: "Unhandled exception in line trace point")
240
309
  # TODO test this path
241
310
  end
242
311
  rescue => exc
243
- raise if settings.dynamic_instrumentation.propagate_all_exceptions
244
- logger.warn("Unhandled exception in line trace point: #{exc.class}: #{exc}")
312
+ raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
313
+ logger.debug { "di: unhandled exception in line trace point: #{exc.class}: #{exc}" }
245
314
  telemetry&.report(exc, description: "Unhandled exception in line trace point")
246
315
  # TODO test this path
247
316
  end
@@ -266,7 +335,9 @@ module Datadog
266
335
  else
267
336
  tp.enable
268
337
  end
338
+ # TracePoint#enable returns false when it succeeds.
269
339
  end
340
+ true
270
341
  end
271
342
 
272
343
  def unhook_line(probe)
@@ -285,7 +356,7 @@ module Datadog
285
356
  hook_line(probe, &block)
286
357
  else
287
358
  # TODO add test coverage for this path
288
- logger.warn("Unknown probe type to hook: #{probe}")
359
+ logger.debug { "di: unknown probe type to hook: #{probe}" }
289
360
  end
290
361
  end
291
362
 
@@ -296,7 +367,7 @@ module Datadog
296
367
  unhook_line(probe)
297
368
  else
298
369
  # TODO add test coverage for this path
299
- logger.warn("Unknown probe type to unhook: #{probe}")
370
+ logger.debug { "di: unknown probe type to unhook: #{probe}" }
300
371
  end
301
372
  end
302
373
 
@@ -304,6 +375,26 @@ module Datadog
304
375
 
305
376
  attr_reader :lock
306
377
 
378
+ def raise_if_probe_in_loaded_features(probe)
379
+ return unless probe.file
380
+
381
+ # If the probe file is in the list of loaded files
382
+ # (as per $LOADED_FEATURES, using either exact or suffix match),
383
+ # raise an error indicating that
384
+ # code tracker is missing the loaded file because the file
385
+ # won't be loaded again (DI only works in production environments
386
+ # that do not normally reload code).
387
+ if $LOADED_FEATURES.include?(probe.file)
388
+ raise Error::DITargetNotInRegistry, "File loaded but is not in code tracker registry: #{probe.file}"
389
+ end
390
+ # Ths is an expensive check
391
+ $LOADED_FEATURES.each do |path|
392
+ if Utils.path_matches_suffix?(path, probe.file)
393
+ raise Error::DITargetNotInRegistry, "File matching probe path (#{probe.file}) was loaded and is not in code tracker registry: #{path}"
394
+ end
395
+ end
396
+ end
397
+
307
398
  # TODO test that this resolves qualified names e.g. A::B
308
399
  def symbolize_class_name(cls_name)
309
400
  Object.const_get(cls_name)
@@ -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
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Require 'datadog/di/preload' early in the application boot process to
4
+ # enable dynamic instrumentation for third-party libraries used by the
5
+ # application.
6
+
7
+ require_relative 'base'
8
+
9
+ # Code tracking is required for line probes to work; see the comments
10
+ # on the activate_tracking methods in di.rb for further details.
11
+ #
12
+ # Unlike di.rb which conditionally activates tracking only if the
13
+ # DD_DYNAMIC_INSTRUMENTATION_ENABLED environment variable is set, this file
14
+ # always activates tracking. This is because this file is explicitly loaded
15
+ # by customer applications for the purpose of enabling code tracking
16
+ # early in application boot process (i.e., before datadog library itself
17
+ # is loaded).
18
+ Datadog::DI.activate_tracking
@@ -36,7 +36,9 @@ module Datadog
36
36
 
37
37
  def initialize(id:, type:,
38
38
  file: nil, line_no: nil, type_name: nil, method_name: nil,
39
- template: nil, capture_snapshot: false, max_capture_depth: nil, rate_limit: nil)
39
+ template: nil, capture_snapshot: false, max_capture_depth: nil,
40
+ max_capture_attribute_count: nil,
41
+ rate_limit: nil)
40
42
  # Perform some sanity checks here to detect unexpected attribute
41
43
  # combinations, in order to not do them in subsequent code.
42
44
  unless KNOWN_TYPES.include?(type)
@@ -64,6 +66,7 @@ module Datadog
64
66
  @template = template
65
67
  @capture_snapshot = !!capture_snapshot
66
68
  @max_capture_depth = max_capture_depth
69
+ @max_capture_attribute_count = max_capture_attribute_count
67
70
 
68
71
  # These checks use instance methods that have more complex logic
69
72
  # than checking a single argument value. To avoid duplicating
@@ -91,6 +94,10 @@ module Datadog
91
94
  # the global default will be used.
92
95
  attr_reader :max_capture_depth
93
96
 
97
+ # Configured maximum capture attribute count. Can be nil in which case
98
+ # the global default will be used.
99
+ attr_reader :max_capture_attribute_count
100
+
94
101
  # Rate limit in effect, in invocations per second. Always present.
95
102
  attr_reader :rate_limit
96
103
 
@@ -148,16 +155,16 @@ module Datadog
148
155
  # Returns whether the provided +path+ matches the user-designated
149
156
  # file (of a line probe).
150
157
  #
151
- # If file is an absolute path (i.e., it starts with a slash), the file
152
- # must be identical to path to match.
153
- #
154
- # If file is not an absolute path, the path matches if the file is its suffix,
155
- # 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.
156
160
  def file_matches?(path)
161
+ if path.nil?
162
+ raise ArgumentError, "Cannot match against a nil path"
163
+ end
157
164
  unless file
158
165
  raise ArgumentError, "Probe does not have a file to match against"
159
166
  end
160
- Utils.path_matches_suffix?(path, file)
167
+ Utils.path_can_match_spec?(path, file)
161
168
  end
162
169
 
163
170
  # Instrumentation module for method probes.
@@ -37,6 +37,7 @@ module Datadog
37
37
  template: config["template"],
38
38
  capture_snapshot: !!config["captureSnapshot"],
39
39
  max_capture_depth: config["capture"]&.[]("maxReferenceDepth"),
40
+ max_capture_attribute_count: config["capture"]&.[]("maxFieldCount"),
40
41
  rate_limit: config["sampling"]&.[]("snapshotsPerSecond"),
41
42
  )
42
43
  rescue KeyError => exc
@@ -32,7 +32,7 @@ module Datadog
32
32
  install_pending_method_probes(tp.self)
33
33
  rescue => exc
34
34
  raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
35
- logger.warn("Unhandled exception in definition trace point: #{exc.class}: #{exc}")
35
+ logger.debug { "di: unhandled exception in definition trace point: #{exc.class}: #{exc}" }
36
36
  telemetry&.report(exc, description: "Unhandled exception in definition trace point")
37
37
  # TODO test this path
38
38
  end
@@ -111,16 +111,18 @@ 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
120
122
  # In "propagate all exceptions" mode we will try to instrument again.
121
123
  raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
122
124
 
123
- logger.warn("Error processing probe configuration: #{exc.class}: #{exc}")
125
+ logger.debug { "di: error processing probe configuration: #{exc.class}: #{exc}" }
124
126
  telemetry&.report(exc, description: "Error processing probe configuration")
125
127
  # TODO report probe as failed to agent since we won't attempt to
126
128
  # install it again.
@@ -160,8 +162,8 @@ 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.warn("Error removing probe #{probe.id}: #{exc.class}: #{exc}")
164
- telemetry&.report(exc, description: "Error removing probe #{probe.id}")
165
+ logger.debug { "di: error removing #{probe.type} probe at #{probe.location} (#{probe.id}): #{exc.class}: #{exc}" }
166
+ telemetry&.report(exc, description: "Error removing probe")
165
167
  end
166
168
  end
167
169
  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.warn("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
@@ -206,6 +208,9 @@ module Datadog
206
208
  # point, which is invoked for each required or loaded file
207
209
  # (and also for eval'd code, but those invocations are filtered out).
208
210
  def install_pending_line_probes(path)
211
+ if path.nil?
212
+ raise ArgumentError, "path must not be nil"
213
+ end
209
214
  @lock.synchronize do
210
215
  @pending_probes.values.each do |probe|
211
216
  if probe.line?
@@ -225,6 +230,7 @@ module Datadog
225
230
  # backend (once per the probe's lifetime) and a snapshot corresponding
226
231
  # to the current invocation.
227
232
  def probe_executed_callback(probe:, **opts)
233
+ logger.trace { "di: executed #{probe.type} probe at #{probe.location} (#{probe.id})" }
228
234
  unless probe.emitting_notified?
229
235
  payload = probe_notification_builder.build_emitting(probe)
230
236
  probe_notifier_worker.add_status(payload)