datadog 2.21.0 → 2.38.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 (623) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +574 -1
  3. data/ext/LIBDATADOG_DEVELOPMENT.md +3 -0
  4. data/ext/datadog_profiling_native_extension/clock_id.h +9 -1
  5. data/ext/datadog_profiling_native_extension/clock_id_from_mach.c +66 -0
  6. data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +3 -2
  7. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +301 -82
  8. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +4 -4
  9. data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +3 -2
  10. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +18 -4
  11. data/ext/datadog_profiling_native_extension/collectors_stack.c +63 -32
  12. data/ext/datadog_profiling_native_extension/collectors_stack.h +7 -2
  13. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +728 -436
  14. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +19 -6
  15. data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +239 -0
  16. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +65 -1
  17. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +40 -1
  18. data/ext/datadog_profiling_native_extension/encoded_profile.c +2 -1
  19. data/ext/datadog_profiling_native_extension/extconf.rb +41 -37
  20. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +4 -43
  21. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +15 -47
  22. data/ext/datadog_profiling_native_extension/heap_recorder.c +252 -103
  23. data/ext/datadog_profiling_native_extension/heap_recorder.h +12 -1
  24. data/ext/datadog_profiling_native_extension/http_transport.c +66 -68
  25. data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +3 -22
  26. data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +0 -5
  27. data/ext/datadog_profiling_native_extension/macos_sampler_thread.h +55 -0
  28. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +0 -13
  29. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +40 -43
  30. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +6 -0
  31. data/ext/datadog_profiling_native_extension/profiling.c +65 -19
  32. data/ext/datadog_profiling_native_extension/ruby_helpers.c +63 -46
  33. data/ext/datadog_profiling_native_extension/ruby_helpers.h +17 -5
  34. data/ext/datadog_profiling_native_extension/setup_signal_handler.c +32 -10
  35. data/ext/datadog_profiling_native_extension/setup_signal_handler.h +2 -1
  36. data/ext/datadog_profiling_native_extension/stack_recorder.c +110 -85
  37. data/ext/datadog_profiling_native_extension/stack_recorder.h +3 -1
  38. data/ext/datadog_profiling_native_extension/time_helpers.h +13 -7
  39. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +2 -1
  40. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +9 -4
  41. data/ext/libdatadog_api/crashtracker.c +16 -15
  42. data/ext/libdatadog_api/crashtracker_report_exception.c +126 -0
  43. data/ext/libdatadog_api/datadog_ruby_common.c +65 -1
  44. data/ext/libdatadog_api/datadog_ruby_common.h +40 -1
  45. data/ext/libdatadog_api/ddsketch.c +102 -0
  46. data/ext/libdatadog_api/di.c +203 -0
  47. data/ext/libdatadog_api/extconf.rb +18 -24
  48. data/ext/libdatadog_api/feature_flags.c +554 -0
  49. data/ext/libdatadog_api/feature_flags.h +5 -0
  50. data/ext/libdatadog_api/helpers.h +27 -0
  51. data/ext/libdatadog_api/init.c +13 -1
  52. data/ext/libdatadog_api/library_config.c +34 -25
  53. data/ext/libdatadog_api/process_discovery.c +19 -13
  54. data/ext/libdatadog_extconf_helpers.rb +94 -11
  55. data/lib/datadog/ai_guard/api_client.rb +84 -0
  56. data/lib/datadog/ai_guard/autoload.rb +10 -0
  57. data/lib/datadog/ai_guard/component.rb +44 -0
  58. data/lib/datadog/ai_guard/configuration/ext.rb +17 -0
  59. data/lib/datadog/ai_guard/configuration.rb +115 -0
  60. data/lib/datadog/ai_guard/contrib/auto_instrument.rb +24 -0
  61. data/lib/datadog/ai_guard/contrib/integration.rb +37 -0
  62. data/lib/datadog/ai_guard/contrib/rack/integration.rb +42 -0
  63. data/lib/datadog/ai_guard/contrib/rack/patcher.rb +26 -0
  64. data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +97 -0
  65. data/lib/datadog/ai_guard/contrib/rails/integration.rb +41 -0
  66. data/lib/datadog/ai_guard/contrib/rails/patcher.rb +97 -0
  67. data/lib/datadog/ai_guard/contrib/ruby_llm/chat_instrumentation.rb +80 -0
  68. data/lib/datadog/ai_guard/contrib/ruby_llm/integration.rb +41 -0
  69. data/lib/datadog/ai_guard/contrib/ruby_llm/patcher.rb +30 -0
  70. data/lib/datadog/ai_guard/evaluation/content_builder.rb +31 -0
  71. data/lib/datadog/ai_guard/evaluation/content_part.rb +36 -0
  72. data/lib/datadog/ai_guard/evaluation/message.rb +25 -0
  73. data/lib/datadog/ai_guard/evaluation/no_op_result.rb +36 -0
  74. data/lib/datadog/ai_guard/evaluation/request.rb +86 -0
  75. data/lib/datadog/ai_guard/evaluation/result.rb +45 -0
  76. data/lib/datadog/ai_guard/evaluation/tool_call.rb +18 -0
  77. data/lib/datadog/ai_guard/evaluation.rb +108 -0
  78. data/lib/datadog/ai_guard/ext.rb +29 -0
  79. data/lib/datadog/ai_guard.rb +181 -0
  80. data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +26 -0
  81. data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +66 -0
  82. data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +36 -0
  83. data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +26 -0
  84. data/lib/datadog/appsec/api_security/endpoint_collection.rb +10 -0
  85. data/lib/datadog/appsec/api_security/route_extractor.rb +38 -9
  86. data/lib/datadog/appsec/api_security/sampler.rb +7 -4
  87. data/lib/datadog/appsec/assets/blocked.html +10 -1
  88. data/lib/datadog/appsec/assets/blocked.json +1 -1
  89. data/lib/datadog/appsec/assets/blocked.text +3 -1
  90. data/lib/datadog/appsec/assets/waf_rules/README.md +30 -36
  91. data/lib/datadog/appsec/assets/waf_rules/recommended.json +359 -4
  92. data/lib/datadog/appsec/assets/waf_rules/strict.json +43 -2
  93. data/lib/datadog/appsec/assets.rb +1 -1
  94. data/lib/datadog/appsec/autoload.rb +1 -1
  95. data/lib/datadog/appsec/component.rb +16 -9
  96. data/lib/datadog/appsec/compressed_json.rb +3 -3
  97. data/lib/datadog/appsec/configuration.rb +427 -1
  98. data/lib/datadog/appsec/context.rb +51 -13
  99. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +3 -1
  100. data/lib/datadog/appsec/contrib/active_record/integration.rb +1 -1
  101. data/lib/datadog/appsec/contrib/active_record/patcher.rb +4 -1
  102. data/lib/datadog/appsec/contrib/aws_lambda/gateway/watcher.rb +75 -0
  103. data/lib/datadog/appsec/contrib/aws_lambda/integration.rb +39 -0
  104. data/lib/datadog/appsec/contrib/aws_lambda/patcher.rb +30 -0
  105. data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +144 -0
  106. data/lib/datadog/appsec/contrib/devise/integration.rb +1 -1
  107. data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +2 -1
  108. data/lib/datadog/appsec/contrib/excon/integration.rb +1 -1
  109. data/lib/datadog/appsec/contrib/excon/patcher.rb +3 -1
  110. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +152 -12
  111. data/lib/datadog/appsec/contrib/faraday/integration.rb +1 -1
  112. data/lib/datadog/appsec/contrib/faraday/patcher.rb +1 -1
  113. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +138 -12
  114. data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +74 -24
  115. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +4 -2
  116. data/lib/datadog/appsec/contrib/graphql/integration.rb +2 -1
  117. data/lib/datadog/appsec/contrib/rack/buffered_input.rb +83 -0
  118. data/lib/datadog/appsec/contrib/rack/ext.rb +1 -1
  119. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +52 -13
  120. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +40 -19
  121. data/lib/datadog/appsec/contrib/rack/input_peeker.rb +79 -0
  122. data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
  123. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +48 -33
  124. data/lib/datadog/appsec/contrib/rack/response_body.rb +36 -0
  125. data/lib/datadog/appsec/contrib/rails/gateway/request.rb +40 -1
  126. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +26 -5
  127. data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
  128. data/lib/datadog/appsec/contrib/rails/patcher.rb +38 -0
  129. data/lib/datadog/appsec/contrib/rails/patches/process_action_patch.rb +2 -0
  130. data/lib/datadog/appsec/contrib/rest_client/integration.rb +1 -1
  131. data/lib/datadog/appsec/contrib/rest_client/patcher.rb +3 -1
  132. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +167 -11
  133. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +43 -13
  134. data/lib/datadog/appsec/contrib/sinatra/integration.rb +1 -1
  135. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +4 -4
  136. data/lib/datadog/appsec/contrib/sinatra/patches/json_patch.rb +1 -1
  137. data/lib/datadog/appsec/counter_sampler.rb +25 -0
  138. data/lib/datadog/appsec/default_header_tags.rb +52 -0
  139. data/lib/datadog/appsec/event.rb +13 -31
  140. data/lib/datadog/appsec/ext.rb +3 -0
  141. data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +2 -3
  142. data/lib/datadog/appsec/instrumentation/gateway.rb +2 -15
  143. data/lib/datadog/appsec/metrics/collector.rb +43 -5
  144. data/lib/datadog/appsec/metrics/exporter.rb +16 -3
  145. data/lib/datadog/appsec/metrics/telemetry.rb +20 -3
  146. data/lib/datadog/appsec/metrics/telemetry_exporter.rb +20 -1
  147. data/lib/datadog/appsec/metrics.rb +5 -5
  148. data/lib/datadog/appsec/monitor/gateway/watcher.rb +8 -6
  149. data/lib/datadog/appsec/remote.rb +44 -29
  150. data/lib/datadog/appsec/response.rb +18 -4
  151. data/lib/datadog/appsec/route_normalizer/rails_route_pattern.rb +176 -0
  152. data/lib/datadog/appsec/route_normalizer/route_pattern.rb +378 -0
  153. data/lib/datadog/appsec/route_normalizer/route_text.rb +57 -0
  154. data/lib/datadog/appsec/route_normalizer.rb +80 -0
  155. data/lib/datadog/appsec/security_engine/engine.rb +26 -5
  156. data/lib/datadog/appsec/security_engine/result.rb +29 -9
  157. data/lib/datadog/appsec/security_engine/runner.rb +20 -10
  158. data/lib/datadog/appsec/security_event.rb +5 -7
  159. data/lib/datadog/appsec/trace_keeper.rb +18 -6
  160. data/lib/datadog/appsec/utils/http/body.rb +38 -0
  161. data/lib/datadog/appsec/utils/http/body_reader.rb +61 -0
  162. data/lib/datadog/appsec/utils/http/media_range.rb +2 -1
  163. data/lib/datadog/appsec/utils/http/media_type.rb +32 -26
  164. data/lib/datadog/appsec/utils/http/url_encoded.rb +52 -0
  165. data/lib/datadog/appsec.rb +6 -3
  166. data/lib/datadog/core/configuration/agentless_settings_resolver.rb +2 -2
  167. data/lib/datadog/core/configuration/base.rb +17 -5
  168. data/lib/datadog/core/configuration/components.rb +185 -17
  169. data/lib/datadog/core/configuration/components_state.rb +6 -1
  170. data/lib/datadog/core/configuration/config_helper.rb +11 -2
  171. data/lib/datadog/core/configuration/deprecations.rb +2 -2
  172. data/lib/datadog/core/configuration/option.rb +32 -6
  173. data/lib/datadog/core/configuration/option_definition.rb +42 -14
  174. data/lib/datadog/core/configuration/options.rb +49 -12
  175. data/lib/datadog/core/configuration/settings.rb +115 -16
  176. data/lib/datadog/core/configuration/stable_config.rb +10 -0
  177. data/lib/datadog/core/configuration/supported_configurations.rb +379 -300
  178. data/lib/datadog/core/configuration.rb +3 -3
  179. data/lib/datadog/core/contrib/rails/railtie.rb +32 -0
  180. data/lib/datadog/core/contrib/rails/utils.rb +7 -3
  181. data/lib/datadog/core/crashtracking/component.rb +73 -21
  182. data/lib/datadog/core/crashtracking/tag_builder.rb +6 -0
  183. data/lib/datadog/core/ddsketch.rb +19 -0
  184. data/lib/datadog/core/diagnostics/environment_logger.rb +3 -1
  185. data/lib/datadog/core/environment/agent_info.rb +65 -1
  186. data/lib/datadog/core/environment/cgroup.rb +52 -25
  187. data/lib/datadog/core/environment/container.rb +140 -46
  188. data/lib/datadog/core/environment/ext.rb +13 -0
  189. data/lib/datadog/core/environment/identity.rb +40 -4
  190. data/lib/datadog/core/environment/process.rb +122 -0
  191. data/lib/datadog/core/environment/socket.rb +13 -0
  192. data/lib/datadog/core/environment/yjit.rb +2 -1
  193. data/lib/datadog/core/error.rb +6 -6
  194. data/lib/datadog/core/evp.rb +11 -0
  195. data/lib/datadog/core/feature_flags.rb +61 -0
  196. data/lib/datadog/core/knuth_sampler.rb +59 -0
  197. data/lib/datadog/core/logger.rb +1 -1
  198. data/lib/datadog/core/metrics/client.rb +6 -6
  199. data/lib/datadog/core/metrics/logging.rb +1 -1
  200. data/lib/datadog/core/pin.rb +8 -8
  201. data/lib/datadog/core/process_discovery.rb +21 -18
  202. data/lib/datadog/core/rate_limiter.rb +11 -1
  203. data/lib/datadog/core/remote/client/capabilities.rb +49 -6
  204. data/lib/datadog/core/remote/client.rb +15 -7
  205. data/lib/datadog/core/remote/component.rb +64 -36
  206. data/lib/datadog/core/remote/configuration/content.rb +15 -2
  207. data/lib/datadog/core/remote/configuration/digest.rb +14 -7
  208. data/lib/datadog/core/remote/configuration/repository.rb +1 -1
  209. data/lib/datadog/core/remote/configuration/target.rb +13 -6
  210. data/lib/datadog/core/remote/transport/config.rb +9 -36
  211. data/lib/datadog/core/remote/transport/http/config.rb +15 -55
  212. data/lib/datadog/core/remote/transport/http/negotiation.rb +14 -44
  213. data/lib/datadog/core/remote/transport/http.rb +15 -24
  214. data/lib/datadog/core/remote/transport/negotiation.rb +8 -33
  215. data/lib/datadog/core/remote/worker.rb +25 -37
  216. data/lib/datadog/core/runtime/metrics.rb +11 -2
  217. data/lib/datadog/core/semaphore.rb +1 -4
  218. data/lib/datadog/core/tag_builder.rb +0 -4
  219. data/lib/datadog/core/tag_normalizer.rb +84 -0
  220. data/lib/datadog/core/telemetry/component.rb +59 -15
  221. data/lib/datadog/core/telemetry/emitter.rb +6 -6
  222. data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +2 -3
  223. data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +30 -0
  224. data/lib/datadog/core/telemetry/event/app_extended_heartbeat.rb +32 -0
  225. data/lib/datadog/core/telemetry/event/app_started.rb +177 -171
  226. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +27 -4
  227. data/lib/datadog/core/telemetry/event.rb +2 -7
  228. data/lib/datadog/core/telemetry/ext.rb +1 -0
  229. data/lib/datadog/core/telemetry/logger.rb +4 -2
  230. data/lib/datadog/core/telemetry/logging.rb +17 -5
  231. data/lib/datadog/core/telemetry/metrics_manager.rb +9 -0
  232. data/lib/datadog/core/telemetry/request.rb +17 -5
  233. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +8 -34
  234. data/lib/datadog/core/telemetry/transport/http.rb +21 -16
  235. data/lib/datadog/core/telemetry/transport/telemetry.rb +8 -17
  236. data/lib/datadog/core/telemetry/worker.rb +108 -32
  237. data/lib/datadog/core/transport/ext.rb +3 -0
  238. data/lib/datadog/core/transport/http/api/endpoint.rb +9 -4
  239. data/lib/datadog/core/transport/http/api/instance.rb +4 -21
  240. data/lib/datadog/core/transport/http/builder.rb +10 -6
  241. data/lib/datadog/core/transport/http/client.rb +80 -0
  242. data/lib/datadog/core/transport/http/response.rb +4 -0
  243. data/lib/datadog/core/transport/http.rb +24 -19
  244. data/lib/datadog/core/transport/parcel.rb +61 -9
  245. data/lib/datadog/core/transport/response.rb +16 -2
  246. data/lib/datadog/core/transport/transport.rb +90 -0
  247. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +2 -2
  248. data/lib/datadog/core/utils/{base64.rb → base64_codec.rb} +4 -3
  249. data/lib/datadog/core/utils/enumerable_compat.rb +29 -0
  250. data/lib/datadog/core/utils/fnv.rb +26 -0
  251. data/lib/datadog/core/utils/forking.rb +3 -1
  252. data/lib/datadog/core/utils/hash.rb +0 -23
  253. data/lib/datadog/{appsec/api_security → core/utils}/lru_cache.rb +10 -21
  254. data/lib/datadog/core/utils/network.rb +22 -1
  255. data/lib/datadog/core/utils/only_once.rb +1 -1
  256. data/lib/datadog/core/utils/only_once_successful.rb +8 -2
  257. data/lib/datadog/core/utils/safe_dup.rb +2 -2
  258. data/lib/datadog/core/utils/sequence.rb +2 -0
  259. data/lib/datadog/core/utils/spawn_monkey_patch.rb +68 -0
  260. data/lib/datadog/core/utils/time.rb +6 -2
  261. data/lib/datadog/core/utils.rb +3 -1
  262. data/lib/datadog/core/workers/async.rb +11 -2
  263. data/lib/datadog/core/workers/interval_loop.rb +51 -3
  264. data/lib/datadog/core/workers/polling.rb +2 -0
  265. data/lib/datadog/core/workers/queue.rb +96 -1
  266. data/lib/datadog/core/workers/runtime_metrics.rb +9 -1
  267. data/lib/datadog/core.rb +10 -3
  268. data/lib/datadog/data_streams/configuration.rb +50 -0
  269. data/lib/datadog/data_streams/ext.rb +11 -0
  270. data/lib/datadog/data_streams/extensions.rb +16 -0
  271. data/lib/datadog/data_streams/pathway_context.rb +169 -0
  272. data/lib/datadog/data_streams/processor.rb +511 -0
  273. data/lib/datadog/data_streams/transport/http/stats.rb +58 -0
  274. data/lib/datadog/data_streams/transport/http.rb +36 -0
  275. data/lib/datadog/data_streams/transport/stats.rb +39 -0
  276. data/lib/datadog/data_streams.rb +100 -0
  277. data/lib/datadog/di/base.rb +15 -7
  278. data/lib/datadog/di/boot.rb +7 -2
  279. data/lib/datadog/di/capture_expression.rb +21 -0
  280. data/lib/datadog/di/capture_expression_evaluator.rb +71 -0
  281. data/lib/datadog/di/capture_limits.rb +41 -0
  282. data/lib/datadog/di/code_tracker.rb +217 -15
  283. data/lib/datadog/di/component.rb +139 -51
  284. data/lib/datadog/di/configuration.rb +241 -2
  285. data/lib/datadog/di/context.rb +82 -0
  286. data/lib/datadog/di/contrib/active_record.rb +34 -5
  287. data/lib/datadog/di/el/compiler.rb +168 -0
  288. data/lib/datadog/di/el/evaluator.rb +159 -0
  289. data/lib/datadog/di/el/expression.rb +42 -0
  290. data/lib/datadog/di/el.rb +5 -0
  291. data/lib/datadog/di/error.rb +44 -0
  292. data/lib/datadog/di/fatal_exceptions.rb +26 -0
  293. data/lib/datadog/di/instrumenter.rb +623 -147
  294. data/lib/datadog/di/logger.rb +2 -2
  295. data/lib/datadog/di/probe.rb +122 -14
  296. data/lib/datadog/di/probe_builder.rb +124 -3
  297. data/lib/datadog/di/probe_file_loader/railtie.rb +1 -1
  298. data/lib/datadog/di/probe_file_loader.rb +12 -7
  299. data/lib/datadog/di/probe_manager.rb +195 -100
  300. data/lib/datadog/di/probe_notification_builder.rb +321 -90
  301. data/lib/datadog/di/probe_notifier_worker.rb +112 -36
  302. data/lib/datadog/di/probe_repository.rb +198 -0
  303. data/lib/datadog/di/proc_responder.rb +36 -0
  304. data/lib/datadog/di/redactor.rb +24 -2
  305. data/lib/datadog/di/remote.rb +258 -93
  306. data/lib/datadog/di/serializer.rb +310 -29
  307. data/lib/datadog/di/transport/diagnostics.rb +12 -42
  308. data/lib/datadog/di/transport/http/diagnostics.rb +4 -34
  309. data/lib/datadog/di/transport/http/input.rb +2 -34
  310. data/lib/datadog/di/transport/http.rb +43 -19
  311. data/lib/datadog/di/transport/input.rb +112 -38
  312. data/lib/datadog/di/utils.rb +42 -14
  313. data/lib/datadog/di.rb +204 -4
  314. data/lib/datadog/error_tracking/collector.rb +2 -1
  315. data/lib/datadog/error_tracking/component.rb +2 -2
  316. data/lib/datadog/error_tracking/configuration.rb +55 -2
  317. data/lib/datadog/error_tracking/filters.rb +2 -2
  318. data/lib/datadog/kit/appsec/events/v2.rb +60 -3
  319. data/lib/datadog/kit/enable_core_dumps.rb +1 -1
  320. data/lib/datadog/kit/tracing/method_tracer.rb +135 -0
  321. data/lib/datadog/open_feature/component.rb +100 -0
  322. data/lib/datadog/open_feature/configuration.rb +37 -0
  323. data/lib/datadog/open_feature/evaluation_engine.rb +70 -0
  324. data/lib/datadog/open_feature/exposures/batch_builder.rb +32 -0
  325. data/lib/datadog/open_feature/exposures/buffer.rb +43 -0
  326. data/lib/datadog/open_feature/exposures/deduplicator.rb +30 -0
  327. data/lib/datadog/open_feature/exposures/event.rb +60 -0
  328. data/lib/datadog/open_feature/exposures/reporter.rb +40 -0
  329. data/lib/datadog/open_feature/exposures/worker.rb +116 -0
  330. data/lib/datadog/open_feature/ext.rb +16 -0
  331. data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +286 -0
  332. data/lib/datadog/open_feature/flag_evaluation/writer.rb +433 -0
  333. data/lib/datadog/open_feature/hooks/flag_eval_evp_hook.rb +101 -0
  334. data/lib/datadog/open_feature/hooks/flag_eval_metrics_hook.rb +49 -0
  335. data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +149 -0
  336. data/lib/datadog/open_feature/native_evaluator.rb +60 -0
  337. data/lib/datadog/open_feature/noop_evaluator.rb +26 -0
  338. data/lib/datadog/open_feature/provider.rb +191 -0
  339. data/lib/datadog/open_feature/remote.rb +67 -0
  340. data/lib/datadog/open_feature/resolution_details.rb +35 -0
  341. data/lib/datadog/open_feature/transport.rb +121 -0
  342. data/lib/datadog/open_feature.rb +19 -0
  343. data/lib/datadog/opentelemetry/api/baggage.rb +1 -1
  344. data/lib/datadog/opentelemetry/configuration/settings.rb +226 -0
  345. data/lib/datadog/opentelemetry/ext.rb +9 -0
  346. data/lib/datadog/opentelemetry/logs.rb +98 -0
  347. data/lib/datadog/opentelemetry/metrics.rb +90 -0
  348. data/lib/datadog/opentelemetry/sdk/configurator.rb +65 -1
  349. data/lib/datadog/opentelemetry/sdk/id_generator.rb +16 -10
  350. data/lib/datadog/opentelemetry/sdk/logs_exporter.rb +30 -0
  351. data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +28 -0
  352. data/lib/datadog/opentelemetry/sdk/propagator.rb +9 -3
  353. data/lib/datadog/opentelemetry/sdk/span_processor.rb +4 -1
  354. data/lib/datadog/opentelemetry/sdk.rb +19 -0
  355. data/lib/datadog/opentelemetry/signal_configuration.rb +53 -0
  356. data/lib/datadog/opentelemetry.rb +4 -0
  357. data/lib/datadog/profiling/collectors/code_provenance.rb +71 -12
  358. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +52 -4
  359. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +13 -5
  360. data/lib/datadog/profiling/collectors/info.rb +18 -4
  361. data/lib/datadog/profiling/collectors/thread_context.rb +10 -5
  362. data/lib/datadog/profiling/component.rb +82 -40
  363. data/lib/datadog/profiling/exporter.rb +41 -12
  364. data/lib/datadog/profiling/ext/dir_monkey_patches.rb +24 -5
  365. data/lib/datadog/profiling/ext/exec_monkey_patch.rb +32 -0
  366. data/lib/datadog/profiling/ext.rb +0 -2
  367. data/lib/datadog/profiling/flush.rb +23 -11
  368. data/lib/datadog/profiling/http_transport.rb +21 -8
  369. data/lib/datadog/profiling/load_native_extension.rb +2 -2
  370. data/lib/datadog/profiling/profiler.rb +31 -14
  371. data/lib/datadog/profiling/scheduler.rb +10 -9
  372. data/lib/datadog/profiling/stack_recorder.rb +0 -8
  373. data/lib/datadog/profiling/tag_builder.rb +37 -3
  374. data/lib/datadog/profiling/tasks/exec.rb +8 -3
  375. data/lib/datadog/profiling/tasks/help.rb +1 -0
  376. data/lib/datadog/profiling/tasks/setup.rb +2 -2
  377. data/lib/datadog/profiling.rb +1 -3
  378. data/lib/datadog/ruby_version.rb +25 -0
  379. data/lib/datadog/single_step_instrument.rb +2 -2
  380. data/lib/datadog/symbol_database/component.rb +734 -0
  381. data/lib/datadog/symbol_database/configuration.rb +73 -0
  382. data/lib/datadog/symbol_database/extensions.rb +19 -0
  383. data/lib/datadog/symbol_database/extractor.rb +1110 -0
  384. data/lib/datadog/symbol_database/file_hash.rb +48 -0
  385. data/lib/datadog/symbol_database/logger.rb +43 -0
  386. data/lib/datadog/symbol_database/remote.rb +180 -0
  387. data/lib/datadog/symbol_database/scope.rb +102 -0
  388. data/lib/datadog/symbol_database/scope_batcher.rb +292 -0
  389. data/lib/datadog/symbol_database/service_version.rb +66 -0
  390. data/lib/datadog/symbol_database/symbol.rb +69 -0
  391. data/lib/datadog/symbol_database/transport/http/endpoint.rb +28 -0
  392. data/lib/datadog/symbol_database/transport/http.rb +45 -0
  393. data/lib/datadog/symbol_database/transport.rb +54 -0
  394. data/lib/datadog/symbol_database/uploader.rb +230 -0
  395. data/lib/datadog/symbol_database.rb +71 -0
  396. data/lib/datadog/tracing/buffer.rb +3 -3
  397. data/lib/datadog/tracing/component.rb +17 -17
  398. data/lib/datadog/tracing/configuration/dynamic.rb +2 -2
  399. data/lib/datadog/tracing/configuration/ext.rb +22 -0
  400. data/lib/datadog/tracing/configuration/settings.rb +96 -4
  401. data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +4 -1
  402. data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +4 -1
  403. data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +4 -1
  404. data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +4 -1
  405. data/lib/datadog/tracing/contrib/action_mailer/event.rb +4 -1
  406. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +10 -7
  407. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +28 -0
  408. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +3 -1
  409. data/lib/datadog/tracing/contrib/action_pack/utils.rb +1 -2
  410. data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +4 -1
  411. data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +5 -2
  412. data/lib/datadog/tracing/contrib/active_job/data_streams.rb +62 -0
  413. data/lib/datadog/tracing/contrib/active_job/events/discard.rb +5 -2
  414. data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +5 -2
  415. data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +5 -2
  416. data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +5 -2
  417. data/lib/datadog/tracing/contrib/active_job/events/perform.rb +5 -2
  418. data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +5 -2
  419. data/lib/datadog/tracing/contrib/active_job/log_injection.rb +21 -7
  420. data/lib/datadog/tracing/contrib/active_job/patcher.rb +17 -1
  421. data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +1 -1
  422. data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +3 -4
  423. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +2 -2
  424. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +1 -1
  425. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +2 -5
  426. data/lib/datadog/tracing/contrib/active_record/utils.rb +1 -1
  427. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +2 -5
  428. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +1 -4
  429. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +2 -2
  430. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +6 -8
  431. data/lib/datadog/tracing/contrib/component.rb +3 -3
  432. data/lib/datadog/tracing/contrib/configurable.rb +18 -3
  433. data/lib/datadog/tracing/contrib/configuration/resolver.rb +14 -4
  434. data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +1 -5
  435. data/lib/datadog/tracing/contrib/dalli/integration.rb +4 -1
  436. data/lib/datadog/tracing/contrib/dalli/quantize.rb +1 -1
  437. data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +2 -0
  438. data/lib/datadog/tracing/contrib/delayed_job/server_internal_tracer/worker.rb +1 -0
  439. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +2 -6
  440. data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +2 -2
  441. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +5 -1
  442. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +5 -6
  443. data/lib/datadog/tracing/contrib/ethon/ext.rb +1 -0
  444. data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +1 -8
  445. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +16 -5
  446. data/lib/datadog/tracing/contrib/excon/ext.rb +1 -0
  447. data/lib/datadog/tracing/contrib/excon/middleware.rb +3 -7
  448. data/lib/datadog/tracing/contrib/ext.rb +3 -1
  449. data/lib/datadog/tracing/contrib/extensions.rb +19 -2
  450. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +16 -9
  451. data/lib/datadog/tracing/contrib/faraday/ext.rb +1 -0
  452. data/lib/datadog/tracing/contrib/faraday/middleware.rb +3 -7
  453. data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +7 -3
  454. data/lib/datadog/tracing/contrib/grape/endpoint.rb +10 -7
  455. data/lib/datadog/tracing/contrib/grape/instrumentation.rb +13 -8
  456. data/lib/datadog/tracing/contrib/grape/patcher.rb +6 -1
  457. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +7 -0
  458. data/lib/datadog/tracing/contrib/graphql/ext.rb +1 -0
  459. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +75 -44
  460. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +5 -2
  461. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +3 -7
  462. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +3 -7
  463. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +2 -0
  464. data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
  465. data/lib/datadog/tracing/contrib/grpc.rb +1 -0
  466. data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +1 -0
  467. data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +1 -0
  468. data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +1 -0
  469. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +16 -5
  470. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +2 -0
  471. data/lib/datadog/tracing/contrib/http/ext.rb +1 -0
  472. data/lib/datadog/tracing/contrib/http/instrumentation.rb +4 -8
  473. data/lib/datadog/tracing/contrib/http/integration.rb +0 -2
  474. data/lib/datadog/tracing/contrib/http.rb +1 -0
  475. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +16 -5
  476. data/lib/datadog/tracing/contrib/httpclient/ext.rb +1 -0
  477. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +7 -7
  478. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +16 -5
  479. data/lib/datadog/tracing/contrib/httprb/ext.rb +1 -0
  480. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +4 -8
  481. data/lib/datadog/tracing/contrib/kafka/event.rb +1 -0
  482. data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +66 -0
  483. data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +66 -0
  484. data/lib/datadog/tracing/contrib/kafka/patcher.rb +14 -0
  485. data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +5 -1
  486. data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +2 -0
  487. data/lib/datadog/tracing/contrib/karafka/ext.rb +1 -0
  488. data/lib/datadog/tracing/contrib/karafka/framework.rb +30 -0
  489. data/lib/datadog/tracing/contrib/karafka/monitor.rb +11 -0
  490. data/lib/datadog/tracing/contrib/karafka/patcher.rb +35 -4
  491. data/lib/datadog/tracing/contrib/karafka.rb +1 -0
  492. data/lib/datadog/tracing/contrib/mongodb/parsers.rb +5 -5
  493. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +5 -8
  494. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +6 -0
  495. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +3 -6
  496. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +2 -6
  497. data/lib/datadog/tracing/contrib/opensearch/quantize.rb +2 -2
  498. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +6 -0
  499. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +15 -18
  500. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +6 -8
  501. data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +13 -0
  502. data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +6 -2
  503. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +24 -0
  504. data/lib/datadog/tracing/contrib/que/configuration/settings.rb +5 -2
  505. data/lib/datadog/tracing/contrib/que/ext.rb +1 -0
  506. data/lib/datadog/tracing/contrib/que/tracer.rb +1 -0
  507. data/lib/datadog/tracing/contrib/racecar/event.rb +1 -5
  508. data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +11 -1
  509. data/lib/datadog/tracing/contrib/rack/ext.rb +28 -0
  510. data/lib/datadog/tracing/contrib/rack/header_tagging.rb +23 -0
  511. data/lib/datadog/tracing/contrib/rack/middlewares.rb +62 -27
  512. data/lib/datadog/tracing/contrib/rack/patcher.rb +2 -2
  513. data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
  514. data/lib/datadog/tracing/contrib/rack/route_inference.rb +67 -0
  515. data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +119 -1
  516. data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +5 -2
  517. data/lib/datadog/tracing/contrib/rails/ext.rb +1 -0
  518. data/lib/datadog/tracing/contrib/rails/log_injection.rb +1 -1
  519. data/lib/datadog/tracing/contrib/rails/middlewares.rb +2 -2
  520. data/lib/datadog/tracing/contrib/rails/patcher.rb +0 -1
  521. data/lib/datadog/tracing/contrib/rails/runner.rb +3 -1
  522. data/lib/datadog/tracing/contrib/rake/instrumentation.rb +6 -4
  523. data/lib/datadog/tracing/contrib/redis/quantize.rb +1 -1
  524. data/lib/datadog/tracing/contrib/redis/tags.rb +1 -6
  525. data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +2 -0
  526. data/lib/datadog/tracing/contrib/registerable.rb +11 -0
  527. data/lib/datadog/tracing/contrib/resque/resque_job.rb +1 -0
  528. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +5 -2
  529. data/lib/datadog/tracing/contrib/rest_client/ext.rb +1 -0
  530. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +5 -6
  531. data/lib/datadog/tracing/contrib/roda/ext.rb +1 -0
  532. data/lib/datadog/tracing/contrib/roda/instrumentation.rb +7 -2
  533. data/lib/datadog/tracing/contrib/sequel/database.rb +1 -0
  534. data/lib/datadog/tracing/contrib/sequel/dataset.rb +1 -0
  535. data/lib/datadog/tracing/contrib/sequel/utils.rb +2 -7
  536. data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +1 -0
  537. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +1 -0
  538. data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +5 -1
  539. data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +2 -0
  540. data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
  541. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/heartbeat.rb +2 -0
  542. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/job_fetch.rb +1 -0
  543. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/redis_info.rb +1 -0
  544. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/scheduled_poller.rb +2 -0
  545. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/stop.rb +1 -0
  546. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +3 -2
  547. data/lib/datadog/tracing/contrib/sidekiq/utils.rb +1 -1
  548. data/lib/datadog/tracing/contrib/sidekiq.rb +1 -0
  549. data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +5 -1
  550. data/lib/datadog/tracing/contrib/sinatra/ext.rb +1 -0
  551. data/lib/datadog/tracing/contrib/sinatra/framework.rb +1 -1
  552. data/lib/datadog/tracing/contrib/sinatra/tracer.rb +1 -0
  553. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +4 -1
  554. data/lib/datadog/tracing/contrib/sneakers/integration.rb +15 -4
  555. data/lib/datadog/tracing/contrib/sneakers/tracer.rb +1 -0
  556. data/lib/datadog/tracing/contrib/status_range_matcher.rb +13 -1
  557. data/lib/datadog/tracing/contrib/stripe/request.rb +1 -1
  558. data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +1 -0
  559. data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +6 -0
  560. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +4 -6
  561. data/lib/datadog/tracing/contrib/utils/quantization/{hash.rb → hash_formatter.rb} +4 -2
  562. data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +31 -0
  563. data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +50 -0
  564. data/lib/datadog/tracing/contrib/waterdrop/ext.rb +18 -0
  565. data/lib/datadog/tracing/contrib/waterdrop/integration.rb +43 -0
  566. data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +46 -0
  567. data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +49 -0
  568. data/lib/datadog/tracing/contrib/waterdrop/producer.rb +50 -0
  569. data/lib/datadog/tracing/contrib/waterdrop.rb +42 -0
  570. data/lib/datadog/tracing/contrib.rb +9 -0
  571. data/lib/datadog/tracing/diagnostics/environment_logger.rb +4 -2
  572. data/lib/datadog/tracing/distributed/baggage.rb +64 -8
  573. data/lib/datadog/tracing/distributed/datadog.rb +13 -11
  574. data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +1 -14
  575. data/lib/datadog/tracing/distributed/propagation.rb +35 -3
  576. data/lib/datadog/tracing/distributed/trace_context.rb +85 -62
  577. data/lib/datadog/tracing/event.rb +1 -1
  578. data/lib/datadog/tracing/ext.rb +9 -0
  579. data/lib/datadog/tracing/metadata/ext.rb +23 -1
  580. data/lib/datadog/tracing/metadata/tagging.rb +2 -2
  581. data/lib/datadog/tracing/pipeline.rb +1 -1
  582. data/lib/datadog/tracing/remote.rb +36 -13
  583. data/lib/datadog/tracing/sampling/ext.rb +2 -0
  584. data/lib/datadog/tracing/sampling/priority_sampler.rb +16 -1
  585. data/lib/datadog/tracing/sampling/rate_sampler.rb +8 -19
  586. data/lib/datadog/tracing/sampling/rule.rb +1 -1
  587. data/lib/datadog/tracing/sampling/rule_sampler.rb +54 -25
  588. data/lib/datadog/tracing/sampling/span/rule_parser.rb +2 -2
  589. data/lib/datadog/tracing/span.rb +1 -1
  590. data/lib/datadog/tracing/span_event.rb +2 -2
  591. data/lib/datadog/tracing/span_operation.rb +34 -10
  592. data/lib/datadog/tracing/sync_writer.rb +0 -1
  593. data/lib/datadog/tracing/trace_digest.rb +7 -0
  594. data/lib/datadog/tracing/trace_operation.rb +123 -16
  595. data/lib/datadog/tracing/tracer.rb +82 -23
  596. data/lib/datadog/tracing/transport/http/client.rb +12 -26
  597. data/lib/datadog/tracing/transport/http/traces.rb +2 -50
  598. data/lib/datadog/tracing/transport/http.rb +15 -9
  599. data/lib/datadog/tracing/transport/io/client.rb +6 -9
  600. data/lib/datadog/tracing/transport/io/traces.rb +28 -34
  601. data/lib/datadog/tracing/transport/trace_formatter.rb +22 -0
  602. data/lib/datadog/tracing/transport/traces.rb +13 -81
  603. data/lib/datadog/tracing/workers.rb +2 -1
  604. data/lib/datadog/tracing/writer.rb +1 -1
  605. data/lib/datadog/version.rb +2 -2
  606. data/lib/datadog.rb +8 -1
  607. metadata +185 -36
  608. data/ext/datadog_profiling_native_extension/clock_id_noop.c +0 -21
  609. data/ext/libdatadog_api/macos_development.md +0 -26
  610. data/lib/datadog/appsec/configuration/settings.rb +0 -400
  611. data/lib/datadog/appsec/contrib/rails/ext.rb +0 -13
  612. data/lib/datadog/core/remote/transport/http/api.rb +0 -53
  613. data/lib/datadog/core/remote/transport/http/client.rb +0 -49
  614. data/lib/datadog/core/telemetry/transport/http/api.rb +0 -43
  615. data/lib/datadog/core/telemetry/transport/http/client.rb +0 -49
  616. data/lib/datadog/core/transport/http/api/spec.rb +0 -36
  617. data/lib/datadog/di/configuration/settings.rb +0 -212
  618. data/lib/datadog/di/transport/http/api.rb +0 -42
  619. data/lib/datadog/di/transport/http/client.rb +0 -47
  620. data/lib/datadog/error_tracking/configuration/settings.rb +0 -63
  621. data/lib/datadog/opentelemetry/api/baggage.rbs +0 -26
  622. data/lib/datadog/tracing/transport/http/api.rb +0 -44
  623. data/lib/datadog/tracing/workers/trace_writer.rb +0 -199
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'cgroup'
4
+ require_relative 'ext'
4
5
 
5
6
  module Datadog
6
7
  module Core
@@ -15,73 +16,166 @@ module Datadog
15
16
  CONTAINER_REGEX = /(?<container>#{UUID_PATTERN}|#{CONTAINER_PATTERN})(?:.scope)?$/.freeze
16
17
  FARGATE_14_CONTAINER_REGEX = /(?<container>[0-9a-f]{32}-[0-9]{1,10})/.freeze
17
18
 
18
- Descriptor = Struct.new(
19
+ # From https://github.com/torvalds/linux/blob/5859a2b1991101d6b978f3feb5325dad39421f29/include/linux/proc_ns.h#L41-L49
20
+ # Currently, the host namespace inode number is hardcoded.
21
+ # We use it to determine if we're running in the host namespace.
22
+ # This detection approach does not work when running in
23
+ # ["Docker-in-Docker"](https://www.docker.com/resources/docker-in-docker-containerized-ci-workflows-dockercon-2023/).
24
+ HOST_CGROUP_NAMESPACE_INODE = 0xEFFFFFFB
25
+
26
+ Entry = Struct.new(
19
27
  :platform,
28
+ :task_uid,
20
29
  :container_id,
21
- :task_uid
30
+ :inode
22
31
  )
23
32
 
24
33
  module_function
25
34
 
35
+ # Returns HTTP headers representing container information.
36
+ # These can used in any Datadog request that requires origin detection.
37
+ # This is the recommended method to call to get container information.
38
+ def to_headers
39
+ headers = {}
40
+ headers["Datadog-Container-ID"] = container_id if container_id
41
+ headers["Datadog-Entity-ID"] = entity_id if entity_id
42
+ headers["Datadog-External-Env"] = external_env if external_env
43
+ headers
44
+ end
45
+
46
+ # Container ID, prefixed with "ci-" or Inode, prefixed with "in-".
47
+ def entity_id
48
+ if container_id
49
+ "ci-#{container_id}"
50
+ elsif inode
51
+ "in-#{inode}"
52
+ end
53
+ end
54
+
55
+ # External data supplied by the Datadog Cluster Agent Admission Controller.
56
+ # @see {Ext::ENV_EXTERNAL_ENV} for more details.
57
+ def external_env
58
+ Datadog.configuration.container.external_env
59
+ end
60
+
61
+ # The container orchestration platform or runtime environment.
62
+ #
63
+ # Examples: Docker, Kubernetes, AWS Fargate, LXC, etc.
64
+ #
65
+ # @return [String, nil] The platform name (e.g., "docker", "kubepods", "fargate"), or nil if not containerized
26
66
  def platform
27
- descriptor.platform
67
+ entry.platform
28
68
  end
29
69
 
70
+ # The unique identifier of the current container in the container environment.
71
+ #
72
+ # @return [String, nil] The container ID, or nil if not running in a containerized environment
30
73
  def container_id
31
- descriptor.container_id
74
+ entry.container_id
32
75
  end
33
76
 
77
+ # The unique identifier of the task or pod containing this container.
78
+ #
79
+ # In Kubernetes, this is the Pod UID; in AWS ECS/Fargate, the task ID.
80
+ # Used to identify higher-level workloads beyond this container,
81
+ # enabling correlation across container restarts and multi-container applications.
82
+ #
83
+ # @return [String, nil] The task/pod UID, or nil if not available in the current environment
34
84
  def task_uid
35
- descriptor.task_uid
85
+ entry.task_uid
36
86
  end
37
87
 
38
- def descriptor
39
- @descriptor ||= Descriptor.new.tap do |descriptor|
40
- Cgroup.descriptors.each do |cgroup_descriptor|
41
- # Parse container data from cgroup descriptor
42
- path = cgroup_descriptor.path
43
- next if path.nil?
44
-
45
- # Split path into parts
46
- parts = path.split('/')
47
- parts.shift # Remove leading empty part
48
-
49
- # Read info from path
50
- next if parts.empty?
51
-
52
- platform = parts[0][PLATFORM_REGEX, :platform]
53
- container_id, task_uid = nil
54
-
55
- case parts.length
56
- when 0..1
57
- next
58
- when 2
59
- container_id = parts[-1][CONTAINER_REGEX, :container] \
60
- || parts[-1][FARGATE_14_CONTAINER_REGEX, :container]
61
- else
62
- if (container_id = parts[-1][CONTAINER_REGEX, :container])
88
+ # A unique identifier for the execution context (container or host namespace).
89
+ #
90
+ # Used as a fallback identifier when {#container_id} is unavailable.
91
+ #
92
+ # @return [Integer, nil] The namespace inode, or nil if unavailable
93
+ def inode
94
+ entry.inode
95
+ end
96
+
97
+ # Checks if the current process is running on the host cgroup namespace.
98
+ # This indicates that the process is not running inside a container.
99
+ # When unsure, we return `false` (not running on host).
100
+ def running_on_host?
101
+ return @running_on_host if defined?(@running_on_host)
102
+
103
+ @running_on_host = begin
104
+ if File.exist?('/proc/self/ns/cgroup')
105
+ File.stat('/proc/self/ns/cgroup').ino == HOST_CGROUP_NAMESPACE_INODE
106
+ else
107
+ false
108
+ end
109
+ rescue => e
110
+ Datadog.logger.debug(
111
+ "Error while checking cgroup namespace. Cause: #{e.class}: #{e.message} Location: #{Array(e.backtrace).first}"
112
+ )
113
+ false
114
+ end
115
+ end
116
+
117
+ # All cgroup entries have the same container identity.
118
+ # The first valid one is sufficient.
119
+ # v2 entries are preferred over v1.
120
+ def entry
121
+ return @entry if defined?(@entry)
122
+
123
+ # Scan all v2 entries first, only then falling back to v1 entries.
124
+ #
125
+ # To do this, we {Enumerable#partition} the list between v1 and v2,
126
+ # with a `true` predicate for v2 entries, making v2 first
127
+ # partition returned.
128
+ #
129
+ # All v2 entries have the `hierarchy` set to zero.
130
+ # v1 entries have a non-zero `hierarchy`.
131
+ entries = Cgroup.entries.partition { |d| d.hierarchy == '0' }.flatten(1)
132
+ entries.each do |entry_obj|
133
+ path = entry_obj.path
134
+ next unless path
135
+
136
+ # To ease handling, remove the emtpy leading "",
137
+ # as `path` starts with a "/".
138
+ path.delete_prefix!('/')
139
+ parts = path.split('/')
140
+
141
+ # With not path information, we can still use the inode
142
+ if parts.empty? && entry_obj.inode && !running_on_host?
143
+ return @entry = Entry.new(nil, nil, nil, entry_obj.inode)
144
+ end
145
+
146
+ platform = parts[0][PLATFORM_REGEX, :platform]
147
+
148
+ # Extract container_id and task_uid based on path structure
149
+ container_id = task_uid = nil
150
+ if parts.length >= 2
151
+ # Try standard container regex first
152
+ if (container_id = parts[-1][CONTAINER_REGEX, :container])
153
+ # For 3+ parts, also extract task_uid
154
+ if parts.length > 2
63
155
  task_uid = parts[-2][POD_REGEX, :pod] || parts[1][POD_REGEX, :pod]
64
- else
65
- container_id = parts[-1][FARGATE_14_CONTAINER_REGEX, :container]
66
156
  end
157
+ else
158
+ # Fall back to Fargate regex
159
+ container_id = parts[-1][FARGATE_14_CONTAINER_REGEX, :container]
67
160
  end
161
+ end
68
162
 
69
- # If container ID wasn't found, ignore.
70
- # Path might describe a non-container environment.
71
- next if container_id.nil?
72
-
73
- descriptor.platform = platform
74
- descriptor.container_id = container_id
75
- descriptor.task_uid = task_uid
76
-
77
- break
163
+ # container_id is a better container identifier than inode.
164
+ # We MUST only populate one of them, to avoid container identification ambiguity.
165
+ if container_id
166
+ return @entry = Entry.new(platform, task_uid, container_id)
167
+ elsif entry_obj.inode && !running_on_host?
168
+ return @entry = Entry.new(platform, task_uid, nil, entry_obj.inode)
78
169
  end
79
- rescue => e
80
- Datadog.logger.error(
81
- "Error while parsing container info. Cause: #{e.class.name} #{e.message} " \
82
- "Location: #{Array(e.backtrace).first}"
83
- )
84
170
  end
171
+
172
+ @entry = Entry.new # Empty entry if no valid cgroup entry is found
173
+ rescue => e
174
+ Datadog.logger.debug(
175
+ "Error while reading container entry. Cause: #{e.class}: #{e.message} Location: #{Array(e.backtrace).first}"
176
+ )
177
+ @entry = Entry.new unless defined?(@entry)
178
+ @entry
85
179
  end
86
180
  end
87
181
  end
@@ -17,6 +17,8 @@ module Datadog
17
17
 
18
18
  ENV_API_KEY = 'DD_API_KEY'
19
19
  ENV_ENVIRONMENT = 'DD_ENV'
20
+ ENV_EXTERNAL_ENV = 'DD_EXTERNAL_ENV'
21
+ ENV_HOSTNAME = 'DD_HOSTNAME'
20
22
  ENV_SERVICE = 'DD_SERVICE'
21
23
  ENV_SITE = 'DD_SITE'
22
24
  ENV_TAGS = 'DD_TAGS'
@@ -33,9 +35,20 @@ module Datadog
33
35
  LANG_INTERPRETER = "#{RUBY_ENGINE}-#{RUBY_PLATFORM}"
34
36
  LANG_PLATFORM = RUBY_PLATFORM
35
37
  LANG_VERSION = RUBY_VERSION
38
+ PROCESS_TYPE = 'script' # Out of the options [jar, script, class, executable], we consider Ruby to always be a script
36
39
  RUBY_ENGINE = ::RUBY_ENGINE # e.g. 'ruby', 'jruby', 'truffleruby'
37
40
  TAG_ENV = 'env'
41
+ TAG_ENTRYPOINT_BASEDIR = "entrypoint.basedir"
42
+ TAG_ENTRYPOINT_NAME = "entrypoint.name"
43
+ TAG_ENTRYPOINT_WORKDIR = "entrypoint.workdir"
44
+ TAG_ENTRYPOINT_TYPE = "entrypoint.type"
45
+ TAG_RAILS_APPLICATION = "rails.application"
46
+ TAG_PROCESS_TAGS = "_dd.tags.process"
38
47
  TAG_SERVICE = 'service'
48
+ # Service name was automatically populated by this library
49
+ TAG_SVC_AUTO = 'svc.auto'
50
+ # Service name was explicitly configured by the library user
51
+ TAG_SVC_USER = 'svc.user'
39
52
  TAG_VERSION = 'version'
40
53
 
41
54
  GEM_DATADOG_VERSION = Datadog::VERSION::STRING
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'securerandom'
4
4
 
5
+ require_relative '../configuration/config_helper'
5
6
  require_relative 'ext'
6
7
  require_relative '../utils/forking'
7
8
 
@@ -13,18 +14,39 @@ module Datadog
13
14
  module Identity
14
15
  extend Core::Utils::Forking
15
16
 
17
+ ENV_ROOT_SESSION_ID = '_DD_ROOT_RB_SESSION_ID'
18
+ ENV_PARENT_SESSION_ID = '_DD_PARENT_RB_SESSION_ID'
19
+
16
20
  module_function
17
21
 
18
- # Retrieves number of classes from runtime
22
+ @root_runtime_id = DATADOG_ENV[ENV_ROOT_SESSION_ID]&.freeze
23
+ @parent_runtime_id = DATADOG_ENV[ENV_PARENT_SESSION_ID]&.freeze
24
+
19
25
  def id
20
26
  @id ||= ::SecureRandom.uuid.freeze
21
27
 
22
- # Check if runtime has changed, e.g. forked.
23
- after_fork! { @id = ::SecureRandom.uuid.freeze }
28
+ after_fork! do
29
+ # Order matters: capture @id before overwriting
30
+ @parent_runtime_id = @id
31
+ @root_runtime_id ||= @id
32
+ @id = ::SecureRandom.uuid.freeze
33
+ end
24
34
 
25
35
  @id
26
36
  end
27
37
 
38
+ def root_runtime_id
39
+ @root_runtime_id
40
+ end
41
+
42
+ def parent_runtime_id
43
+ @parent_runtime_id
44
+ end
45
+
46
+ def runtime_propagation_envs
47
+ {ENV_ROOT_SESSION_ID => root_runtime_id || id, ENV_PARENT_SESSION_ID => id}.freeze
48
+ end
49
+
28
50
  def pid
29
51
  ::Process.pid
30
52
  end
@@ -54,7 +76,21 @@ module Datadog
54
76
  Core::Environment::Ext::GEM_DATADOG_VERSION
55
77
  end
56
78
 
57
- # Returns tracer version, comforming to https://semver.org/spec/v2.0.0.html
79
+ # Returns the tracer version in SemVer-2 form (https://semver.org/spec/v2.0.0.html).
80
+ #
81
+ # Converts the RubyGems-style version returned by {.gem_datadog_version}
82
+ # (dot-separated prerelease/build segments, e.g. "2.34.0.dev") into the
83
+ # SemVer-2 form expected by cross-language Datadog consumers (hyphen-separated
84
+ # prerelease, "+" build metadata, e.g. "2.34.0-dev").
85
+ #
86
+ # Called by reporters that emit a tracer version on the wire and must match
87
+ # the format used by other-language tracers:
88
+ # - process discovery memfd (`Core::ProcessDiscovery.get_metadata` → `tracer_version`)
89
+ # - telemetry payloads (`Core::Telemetry::Request#application`)
90
+ # - remote configuration client identification (`Core::Remote::Client#tracer_version`)
91
+ #
92
+ # Use {.gem_datadog_version} (not this method) when a RubyGems-style string is
93
+ # required (e.g. gem-internal contexts, gemspec interop).
58
94
  def gem_datadog_version_semver2
59
95
  major, minor, patch, rest = gem_datadog_version.split('.', 4)
60
96
 
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'ext'
4
+ require_relative '../tag_normalizer'
5
+
6
+ module Datadog
7
+ module Core
8
+ module Environment
9
+ # Retrieves process level information such that it can be attached to various payloads
10
+ #
11
+ # @api private
12
+ module Process
13
+ # Returns a comma-separated string of normalized key:value pairs.
14
+ # Includes svc.user or svc.auto based on whether the service was explicitly configured.
15
+ # @return [String]
16
+ def self.serialized
17
+ tags.join(',').freeze
18
+ end
19
+
20
+ # Returns an array of normalized key:value pair strings.
21
+ # Includes svc.user or svc.auto based on whether the service was explicitly configured.
22
+ # @return [Array<String>]
23
+ def self.tags
24
+ tags = []
25
+
26
+ workdir = TagNormalizer.normalize_process_value(entrypoint_workdir.to_s)
27
+ tags << "#{Environment::Ext::TAG_ENTRYPOINT_WORKDIR}:#{workdir}" unless workdir.empty?
28
+
29
+ entry_name = TagNormalizer.normalize_process_value(entrypoint_name.to_s)
30
+ tags << "#{Environment::Ext::TAG_ENTRYPOINT_NAME}:#{entry_name}" unless entry_name.empty?
31
+
32
+ basedir = TagNormalizer.normalize_process_value(entrypoint_basedir.to_s)
33
+ tags << "#{Environment::Ext::TAG_ENTRYPOINT_BASEDIR}:#{basedir}" unless basedir.empty?
34
+
35
+ tags << "#{Environment::Ext::TAG_ENTRYPOINT_TYPE}:#{TagNormalizer.normalize(entrypoint_type, remove_digit_start_char: false)}"
36
+
37
+ if defined?(@rails_application_name)
38
+ rails_name = TagNormalizer.normalize_process_value(@rails_application_name.to_s)
39
+ tags << "#{Environment::Ext::TAG_RAILS_APPLICATION}:#{rails_name}" unless rails_name.empty?
40
+ end
41
+
42
+ if defined?(@service_user_configured)
43
+ if @service_user_configured
44
+ tags << "#{Environment::Ext::TAG_SVC_USER}:true"
45
+ else
46
+ svc = TagNormalizer.normalize_process_value(@service_name.to_s)
47
+ tags << "#{Environment::Ext::TAG_SVC_AUTO}:#{svc}" unless svc.empty?
48
+ end
49
+ end
50
+
51
+ tags.freeze
52
+ end
53
+
54
+ # Called via after_set on option :service in settings.rb whenever the service value changes.
55
+ # @param name [String] the service name
56
+ # @param user_configured [Boolean] whether the service was explicitly set by the user
57
+ # @return [void]
58
+ def self.set_service(name, user_configured:)
59
+ @service_name = name
60
+ @service_user_configured = user_configured
61
+ end
62
+
63
+ # Sets the rails application name from other places in code
64
+ # @param name [String] the rails application name
65
+ # @return [void]
66
+ def self.rails_application_name=(name)
67
+ @rails_application_name = name
68
+ end
69
+
70
+ # Returns the last segment of the working directory of the process
71
+ # Example: /app/myapp -> myapp
72
+ # @return [String] the last segment of the working directory
73
+ def self.entrypoint_workdir
74
+ return @entrypoint_workdir if defined?(@entrypoint_workdir)
75
+
76
+ @entrypoint_workdir = File.basename(Dir.pwd)
77
+ end
78
+
79
+ # Returns the entrypoint type of the process
80
+ # In Ruby, the entrypoint type is always 'script'
81
+ # @return [String] the type of the process, which is fixed in Ruby
82
+ def self.entrypoint_type
83
+ Environment::Ext::PROCESS_TYPE
84
+ end
85
+
86
+ # Returns the basename of the script being run
87
+ # Example 1: /bin/mybin -> mybin
88
+ # Example 2: ruby /test/myapp.rb -> myapp.rb
89
+ # @return [String] the basename of the script
90
+ #
91
+ # @note Determining true entrypoint name is rather complicated. This method
92
+ # is the initial implementation but it does not produce optimal output in all cases.
93
+ # For example, all Rails applications launched via `rails server` get `rails`
94
+ # as their entrypoint name.
95
+ # We might improve the behavior in the future if there is customer demand for it.
96
+ def self.entrypoint_name
97
+ return @entrypoint_name if defined?(@entrypoint_name)
98
+
99
+ @entrypoint_name = File.basename($0)
100
+ end
101
+
102
+ # Returns the last segment of the directory containing the script
103
+ # Example 1: /bin/mybin -> bin
104
+ # Example 2: ruby /test/myapp.rb -> test
105
+ # @return [String] the last segment of the base directory of the script
106
+ #
107
+ # @note As with entrypoint name, determining true entrypoint directory is complicated.
108
+ # This method has an initial implementation that does not necessarily return good
109
+ # results in all cases. For example, for Rails applications launched via `rails server`
110
+ # the entrypoint basedir is `bin` which is not very helpful.
111
+ # We might improve this in the future if there is customer demand.
112
+ def self.entrypoint_basedir
113
+ return @entrypoint_basedir if defined?(@entrypoint_basedir)
114
+
115
+ @entrypoint_basedir = File.basename(File.expand_path(File.dirname($0)))
116
+ end
117
+
118
+ private_class_method :entrypoint_workdir, :entrypoint_type, :entrypoint_name, :entrypoint_basedir
119
+ end
120
+ end
121
+ end
122
+ end
@@ -18,6 +18,19 @@ module Datadog
18
18
 
19
19
  @hostname ||= ::Socket.gethostname.freeze
20
20
  end
21
+
22
+ # Returns the resolved hostname when `report_hostname` is enabled:
23
+ # the configured DD_HOSTNAME if set, otherwise the system hostname.
24
+ # Returns nil when `report_hostname` is disabled or no hostname is available.
25
+ def resolved_hostname(settings)
26
+ return nil unless settings.tracing.report_hostname
27
+
28
+ configured = settings.hostname
29
+ return configured if configured && !configured.empty?
30
+
31
+ resolved_hostname = hostname
32
+ resolved_hostname if resolved_hostname && !resolved_hostname.empty?
33
+ end
21
34
  end
22
35
  end
23
36
  end
@@ -54,7 +54,8 @@ module Datadog
54
54
 
55
55
  # Ratio of YJIT-executed instructions
56
56
  def ratio_in_yjit
57
- ::RubyVM::YJIT.runtime_stats[:ratio_in_yjit]
57
+ stats = ::RubyVM::YJIT.runtime_stats
58
+ stats[:ratio_in_yjit] if stats.key?(:ratio_in_yjit)
58
59
  end
59
60
 
60
61
  def available?
@@ -13,12 +13,12 @@ module Datadog
13
13
  case value
14
14
  # A Ruby {Exception} is the most common parameter type.
15
15
  when Exception then new(value.class, value.message, full_backtrace(value))
16
- # steep:ignore:start
17
- # Steep doesn't like an array with up to 3 elements to be passed here: it thinks the array is unbounded.
18
- when Array then new(*value)
19
- # Steep can not follow the logic inside the lambda, thus it doesn't know `value` responds to `:message`.
20
- when ->(v) { v.respond_to?(:message) } then new(value.class, value.message)
21
- # steep:ignore:end
16
+ # Steep: Steep doesn't like an array with up to 3 elements to be passed here: it thinks the array is unbounded.
17
+ when Array then new(*value) # steep:ignore UnexpectedPositionalArgument
18
+ when ->(v) { v.respond_to?(:message) }
19
+ # Steep: Steep can not follow the logic inside the lambda, thus it doesn't know `value` responds to `:message`.
20
+ # @type var value: _ContainsMessage
21
+ new(value.class, value.message)
22
22
  when String then new(nil, value)
23
23
  when Error then value
24
24
  else Error.new # Blank error
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Core
5
+ module EVP
6
+ SUBDOMAIN_HEADER_NAME = 'X-Datadog-EVP-Subdomain'
7
+ EVENT_PLATFORM_INTAKE_SUBDOMAIN = 'event-platform-intake'
8
+ PAYLOAD_SIZE_LIMIT_BYTES = 5 * 1024 * 1024
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Datadog
6
+ module Core
7
+ # Feature flags evaluation using libdatadog
8
+ # The classes in this module are defined as C extensions in ext/libdatadog_api/feature_flags.c
9
+ #
10
+ # @api private
11
+ module FeatureFlags
12
+ # A top-level error raised by the extension
13
+ class Error < StandardError # rubocop:disable Lint/EmptyClass
14
+ end
15
+
16
+ # Configuration for feature flags evaluation
17
+ # This class is defined in the C extension
18
+ class Configuration # rubocop:disable Lint/EmptyClass
19
+ end
20
+
21
+ # Resolution details for a feature flag evaluation
22
+ # Base class is defined in the C extension, with Ruby methods added here
23
+ class ResolutionDetails
24
+ attr_writer :value
25
+
26
+ # Get the resolved value, with JSON parsing for object types
27
+ #
28
+ # @return [Object] The resolved value (parsed from JSON if object type)
29
+ # @raise [Datadog::Core::FeatureFlags::Error] If JSON parsing fails
30
+ def value
31
+ return @value if defined?(@value)
32
+
33
+ # NOTE: Raw value method call doesn't support memoization right now
34
+ value = raw_value
35
+
36
+ # NOTE: Lazy parsing of the JSON is a temporary solution and will be
37
+ # moved into C extension
38
+ @value = json?(value) ? JSON.parse(value) : value
39
+ rescue JSON::ParserError => e
40
+ raise Error, "Failed to parse JSON value: #{e.class}: #{e.message}"
41
+ end
42
+
43
+ # Check if the resolution resulted in an error
44
+ #
45
+ # @return [Boolean] True if there was an error
46
+ def error?
47
+ reason == 'ERROR'
48
+ end
49
+
50
+ private
51
+
52
+ # NOTE: A JSON raw string will be returned by the `libdatadog` as
53
+ # a Ruby String class with a flag type `:object`, otherwise it's
54
+ # just a string.
55
+ def json?(value)
56
+ flag_type == :object && value.is_a?(String)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Core
5
+ # Deterministic sampler using Knuth multiplicative hash algorithm.
6
+ #
7
+ # This sampler provides consistent sampling decisions based on an input value,
8
+ # ensuring the same input always produces the same sampling decision for a given rate.
9
+ #
10
+ # The algorithm multiplies the input by a large prime (Knuth factor), takes modulo
11
+ # to constrain to a fixed range, and compares against a threshold derived from the sample rate.
12
+ #
13
+ # @api private
14
+ # @see https://en.wikipedia.org/wiki/Hash_function#Multiplicative_hashing
15
+ class KnuthSampler
16
+ # Maximum unsigned 64-bit integer for uniform distribution across 64-bit input space.
17
+ UINT64_MAX = (1 << 64) - 1
18
+ UINT64_MODULO = 1 << 64
19
+
20
+ # Golden ratio constant for optimal distribution.
21
+ # @see https://en.wikipedia.org/wiki/Hash_function#Fibonacci_hashing
22
+ DEFAULT_KNUTH_FACTOR = 11400714819323198485
23
+
24
+ attr_reader :rate
25
+
26
+ # @param rate [Float] Sampling rate between +0.0+ and +1.0+ (inclusive).
27
+ # +0.0+ means no samples are kept; +1.0+ means all samples are kept.
28
+ # Invalid values fall back to +1.0+ (sample everything).
29
+ # @param knuth_factor [Integer] Multiplicative constant for hashing.
30
+ # Different factors produce different sampling distributions.
31
+ def initialize(rate = 1.0, knuth_factor: DEFAULT_KNUTH_FACTOR)
32
+ @knuth_factor = knuth_factor
33
+
34
+ rate = rate.to_f
35
+ # Not using `between?` here: it raises on NaN instead of falling back to 1.0 below.
36
+ # No current caller passes NaN, but this guards against it defensively for future ones.
37
+ unless rate >= 0.0 && rate <= 1.0 # rubocop:disable Style/ComparableBetween
38
+ Datadog.logger.warn("Sample rate #{rate} is not between 0.0 and 1.0, falling back to 1.0")
39
+ rate = 1.0
40
+ end
41
+
42
+ @rate = rate
43
+ @threshold = @rate * UINT64_MAX
44
+ end
45
+
46
+ # Determines if the given input should be sampled.
47
+ #
48
+ # This method is deterministic: the same input value always produces
49
+ # the same result for a given sample rate and configuration.
50
+ #
51
+ # @param input [Integer] Value to determine sampling decision.
52
+ # Typically a trace ID or incrementing counter.
53
+ # @return [Boolean] +true+ if input should be sampled, +false+ otherwise
54
+ def sample?(input)
55
+ ((input * @knuth_factor) % UINT64_MODULO) <= @threshold
56
+ end
57
+ end
58
+ end
59
+ end
@@ -28,7 +28,7 @@ module Datadog
28
28
 
29
29
  if message.nil?
30
30
  if block
31
- super do
31
+ super(severity, nil, progname) do
32
32
  "[#{self.progname}] #{where}#{yield}"
33
33
  end
34
34
  else