datadog 2.46.0 → 2.48.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 (286) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +56 -2
  3. data/LICENSE-3rdparty.csv +1 -0
  4. data/ext/datadog_profiling_native_extension/collectors_stack.c +143 -86
  5. data/ext/datadog_profiling_native_extension/collectors_stack.h +9 -1
  6. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +6 -1
  7. data/ext/datadog_profiling_native_extension/extconf.rb +7 -13
  8. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +3 -3
  9. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +67 -14
  10. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +8 -1
  11. data/ext/datadog_profiling_native_extension/profiling.c +1 -1
  12. data/ext/libdatadog_api/extconf.rb +9 -7
  13. data/ext/libdatadog_api/trace_exporter.c +34 -7
  14. data/ext/libdatadog_extconf_helpers.rb +2 -2
  15. data/lib/datadog/ai_guard/component.rb +1 -1
  16. data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +1 -9
  17. data/lib/datadog/ai_guard/contrib/rails/patcher.rb +1 -1
  18. data/lib/datadog/ai_guard/contrib/ruby_llm/message_adapter.rb +1 -1
  19. data/lib/datadog/ai_guard/contrib/ruby_llm/redaction_change_set.rb +3 -3
  20. data/lib/datadog/ai_guard/evaluation/client.rb +3 -3
  21. data/lib/datadog/ai_guard/evaluation.rb +2 -2
  22. data/lib/datadog/ai_guard/http_client.rb +3 -2
  23. data/lib/datadog/ai_guard/redaction.rb +1 -1
  24. data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +1 -1
  25. data/lib/datadog/appsec/assets/waf_rules/README.md +3 -3
  26. data/lib/datadog/appsec/assets/waf_rules/recommended.json +5366 -1517
  27. data/lib/datadog/appsec/assets/waf_rules/strict.json +2 -2
  28. data/lib/datadog/appsec/autoload.rb +1 -1
  29. data/lib/datadog/appsec/component.rb +1 -1
  30. data/lib/datadog/appsec/compressed_json.rb +1 -1
  31. data/lib/datadog/appsec/configuration.rb +3 -3
  32. data/lib/datadog/appsec/context.rb +1 -1
  33. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +11 -1
  34. data/lib/datadog/appsec/contrib/active_record/patcher.rb +12 -4
  35. data/lib/datadog/appsec/contrib/aws_lambda/gateway/watcher.rb +2 -2
  36. data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +1 -1
  37. data/lib/datadog/appsec/contrib/devise/configuration.rb +1 -1
  38. data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +1 -1
  39. data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +1 -1
  40. data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +1 -1
  41. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +1 -1
  42. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +1 -1
  43. data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +7 -7
  44. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +1 -1
  45. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +3 -3
  46. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +5 -5
  47. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +31 -4
  48. data/lib/datadog/appsec/contrib/rails/patcher.rb +2 -2
  49. data/lib/datadog/appsec/contrib/rails/patches/render_to_body_patch.rb +8 -7
  50. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +1 -1
  51. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +17 -5
  52. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +1 -1
  53. data/lib/datadog/appsec/contrib/sinatra/patches/json_patch.rb +8 -7
  54. data/lib/datadog/appsec/metrics/collector.rb +5 -5
  55. data/lib/datadog/appsec/metrics/telemetry_exporter.rb +3 -3
  56. data/lib/datadog/appsec/monitor/gateway/watcher.rb +2 -2
  57. data/lib/datadog/appsec/processor/rule_loader.rb +1 -1
  58. data/lib/datadog/appsec/response.rb +1 -1
  59. data/lib/datadog/appsec/security_engine/engine.rb +8 -7
  60. data/lib/datadog/appsec/security_engine/runner.rb +2 -2
  61. data/lib/datadog/appsec/trace_keeper.rb +1 -1
  62. data/lib/datadog/appsec.rb +1 -1
  63. data/lib/datadog/core/configuration/agent_settings_resolver.rb +14 -13
  64. data/lib/datadog/core/configuration/agentless_settings_resolver.rb +2 -2
  65. data/lib/datadog/core/configuration/components.rb +12 -11
  66. data/lib/datadog/core/configuration/components_state.rb +8 -1
  67. data/lib/datadog/core/configuration/settings.rb +5 -2
  68. data/lib/datadog/core/configuration/supported_configurations.rb +3 -0
  69. data/lib/datadog/core/configuration.rb +2 -2
  70. data/lib/datadog/core/crashtracking/component.rb +1 -1
  71. data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
  72. data/lib/datadog/core/environment/cgroup.rb +2 -2
  73. data/lib/datadog/core/environment/container.rb +3 -3
  74. data/lib/datadog/core/metrics/client.rb +6 -6
  75. data/lib/datadog/core/process_discovery.rb +1 -1
  76. data/lib/datadog/core/remote/client.rb +44 -3
  77. data/lib/datadog/core/remote/dispatcher.rb +34 -3
  78. data/lib/datadog/core/remote/tie/tracing.rb +4 -3
  79. data/lib/datadog/core/remote/transport/http.rb +2 -2
  80. data/lib/datadog/core/runtime/metrics.rb +14 -14
  81. data/lib/datadog/core/semaphore.rb +3 -1
  82. data/lib/datadog/core/telemetry/event/app_started.rb +9 -9
  83. data/lib/datadog/core/telemetry/logger.rb +1 -1
  84. data/lib/datadog/core/telemetry/logging.rb +1 -1
  85. data/lib/datadog/core/telemetry/request.rb +9 -3
  86. data/lib/datadog/core/telemetry/transport/http.rb +2 -2
  87. data/lib/datadog/core/telemetry/worker.rb +1 -1
  88. data/lib/datadog/core/transport/http/adapters/net.rb +1 -1
  89. data/lib/datadog/core/transport/http/adapters/unix_socket.rb +1 -1
  90. data/lib/datadog/core/transport/http/builder.rb +1 -1
  91. data/lib/datadog/core/transport/http.rb +3 -3
  92. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +2 -2
  93. data/lib/datadog/core/workers/async.rb +1 -1
  94. data/lib/datadog/core/workers/runtime_metrics.rb +2 -2
  95. data/lib/datadog/data_streams/pathway_context.rb +1 -1
  96. data/lib/datadog/data_streams/processor.rb +48 -27
  97. data/lib/datadog/data_streams/transport/http.rb +1 -1
  98. data/lib/datadog/data_streams.rb +16 -0
  99. data/lib/datadog/di/capture_expression_evaluator.rb +48 -11
  100. data/lib/datadog/di/component.rb +73 -2
  101. data/lib/datadog/di/configuration.rb +19 -0
  102. data/lib/datadog/di/contrib/active_record.rb +1 -1
  103. data/lib/datadog/di/el/compiler.rb +4 -4
  104. data/lib/datadog/di/el/evaluator.rb +247 -43
  105. data/lib/datadog/di/el/expression.rb +36 -6
  106. data/lib/datadog/di/error.rb +16 -0
  107. data/lib/datadog/di/guardrails_telemetry/reason.rb +3 -2
  108. data/lib/datadog/di/instrumenter.rb +39 -10
  109. data/lib/datadog/di/probe_notification_builder.rb +58 -10
  110. data/lib/datadog/di/probe_notifier_worker.rb +1 -1
  111. data/lib/datadog/di/remote.rb +46 -2
  112. data/lib/datadog/di/serializer.rb +47 -13
  113. data/lib/datadog/di.rb +27 -0
  114. data/lib/datadog/error_tracking/component.rb +1 -1
  115. data/lib/datadog/error_tracking/configuration.rb +1 -1
  116. data/lib/datadog/kit/appsec/events/v2.rb +6 -6
  117. data/lib/datadog/kit/appsec/events.rb +1 -1
  118. data/lib/datadog/kit/enable_core_dumps.rb +1 -1
  119. data/lib/datadog/kit/identity.rb +1 -1
  120. data/lib/datadog/open_feature/activation.rb +26 -1
  121. data/lib/datadog/open_feature/agentless/configuration_source.rb +94 -15
  122. data/lib/datadog/open_feature/component.rb +22 -2
  123. data/lib/datadog/open_feature/configuration/agentless_endpoint.rb +6 -0
  124. data/lib/datadog/open_feature/configuration.rb +10 -4
  125. data/lib/datadog/open_feature/evaluation_engine.rb +62 -4
  126. data/lib/datadog/open_feature/exposures/buffer.rb +4 -0
  127. data/lib/datadog/open_feature/exposures/reporter.rb +17 -4
  128. data/lib/datadog/open_feature/exposures/worker.rb +37 -6
  129. data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +5 -5
  130. data/lib/datadog/open_feature/flag_evaluation/writer.rb +1 -1
  131. data/lib/datadog/open_feature/hooks/debug_logging_hook.rb +56 -0
  132. data/lib/datadog/open_feature/hooks/evaluation_telemetry_opt_out_hook.rb +25 -0
  133. data/lib/datadog/open_feature/hooks/span_enrichment_hook.rb +2 -2
  134. data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +1 -1
  135. data/lib/datadog/open_feature/native_evaluator.rb +1 -1
  136. data/lib/datadog/open_feature/noop_evaluator.rb +1 -1
  137. data/lib/datadog/open_feature/provider.rb +69 -12
  138. data/lib/datadog/open_feature/remote.rb +8 -1
  139. data/lib/datadog/open_feature/resolution_details.rb +2 -2
  140. data/lib/datadog/open_feature/transport.rb +6 -6
  141. data/lib/datadog/opentelemetry/api/context.rb +3 -3
  142. data/lib/datadog/opentelemetry/logs.rb +5 -5
  143. data/lib/datadog/opentelemetry/metrics.rb +3 -3
  144. data/lib/datadog/opentelemetry/sdk/propagator.rb +3 -3
  145. data/lib/datadog/opentelemetry/sdk/span_processor.rb +2 -2
  146. data/lib/datadog/opentelemetry/sdk/trace/span.rb +1 -1
  147. data/lib/datadog/profiling/collectors/code_provenance.rb +3 -3
  148. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +4 -4
  149. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -1
  150. data/lib/datadog/profiling/collectors/info.rb +37 -6
  151. data/lib/datadog/profiling/collectors/thread_context.rb +1 -1
  152. data/lib/datadog/profiling/component.rb +41 -39
  153. data/lib/datadog/profiling/exporter.rb +4 -6
  154. data/lib/datadog/profiling/http_transport.rb +3 -3
  155. data/lib/datadog/profiling/profiler.rb +2 -2
  156. data/lib/datadog/profiling/scheduler.rb +2 -2
  157. data/lib/datadog/profiling/tag_builder.rb +1 -1
  158. data/lib/datadog/symbol_database/extractor.rb +8 -8
  159. data/lib/datadog/symbol_database/uploader.rb +1 -1
  160. data/lib/datadog/tracing/buffer.rb +3 -3
  161. data/lib/datadog/tracing/client_ip.rb +1 -1
  162. data/lib/datadog/tracing/component.rb +15 -10
  163. data/lib/datadog/tracing/configuration/dynamic/option.rb +2 -2
  164. data/lib/datadog/tracing/configuration/ext.rb +2 -0
  165. data/lib/datadog/tracing/configuration/settings.rb +14 -3
  166. data/lib/datadog/tracing/context.rb +1 -1
  167. data/lib/datadog/tracing/context_provider.rb +8 -0
  168. data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +2 -2
  169. data/lib/datadog/tracing/contrib/active_job/data_streams.rb +27 -2
  170. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +2 -2
  171. data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +1 -1
  172. data/lib/datadog/tracing/contrib/active_record/utils.rb +1 -1
  173. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +1 -1
  174. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +1 -1
  175. data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +2 -2
  176. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +2 -2
  177. data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +1 -1
  178. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +1 -1
  179. data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +1 -1
  180. data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +1 -1
  181. data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +2 -2
  182. data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +1 -1
  183. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +3 -3
  184. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +1 -1
  185. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +17 -12
  186. data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +1 -1
  187. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +1 -1
  188. data/lib/datadog/tracing/contrib/excon/middleware.rb +16 -9
  189. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +1 -1
  190. data/lib/datadog/tracing/contrib/faraday/middleware.rb +14 -8
  191. data/lib/datadog/tracing/contrib/grape/endpoint.rb +4 -4
  192. data/lib/datadog/tracing/contrib/graphql/patcher.rb +1 -1
  193. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +3 -3
  194. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +1 -1
  195. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +2 -2
  196. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +1 -1
  197. data/lib/datadog/tracing/contrib/grpc.rb +1 -1
  198. data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +1 -1
  199. data/lib/datadog/tracing/contrib/hanami/plugin.rb +1 -1
  200. data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +1 -1
  201. data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +1 -1
  202. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +1 -1
  203. data/lib/datadog/tracing/contrib/http/instrumentation.rb +21 -6
  204. data/lib/datadog/tracing/contrib/http.rb +1 -1
  205. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +1 -1
  206. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +14 -8
  207. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +1 -1
  208. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +14 -8
  209. data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +2 -2
  210. data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +2 -2
  211. data/lib/datadog/tracing/contrib/karafka/monitor.rb +1 -1
  212. data/lib/datadog/tracing/contrib/karafka/patcher.rb +1 -1
  213. data/lib/datadog/tracing/contrib/karafka.rb +1 -1
  214. data/lib/datadog/tracing/contrib/lograge/patcher.rb +1 -1
  215. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +1 -1
  216. data/lib/datadog/tracing/contrib/mongodb/parsers.rb +1 -1
  217. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +1 -1
  218. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +1 -1
  219. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +3 -3
  220. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +2 -2
  221. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +3 -3
  222. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +1 -1
  223. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +4 -4
  224. data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +1 -1
  225. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +4 -4
  226. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +1 -1
  227. data/lib/datadog/tracing/contrib/que/tracer.rb +1 -1
  228. data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +1 -1
  229. data/lib/datadog/tracing/contrib/racecar/events/batch.rb +1 -1
  230. data/lib/datadog/tracing/contrib/racecar/events/message.rb +1 -1
  231. data/lib/datadog/tracing/contrib/rack/middlewares.rb +3 -3
  232. data/lib/datadog/tracing/contrib/rack/patcher.rb +1 -1
  233. data/lib/datadog/tracing/contrib/rails/framework.rb +7 -7
  234. data/lib/datadog/tracing/contrib/rails/log_injection.rb +1 -1
  235. data/lib/datadog/tracing/contrib/rails/runner.rb +4 -4
  236. data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +1 -1
  237. data/lib/datadog/tracing/contrib/redis/quantize.rb +1 -1
  238. data/lib/datadog/tracing/contrib/redis/tags.rb +1 -1
  239. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +1 -1
  240. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +17 -10
  241. data/lib/datadog/tracing/contrib/sequel/database.rb +1 -1
  242. data/lib/datadog/tracing/contrib/sequel/dataset.rb +1 -1
  243. data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +1 -1
  244. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +2 -2
  245. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +2 -2
  246. data/lib/datadog/tracing/contrib/sidekiq.rb +1 -1
  247. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +1 -1
  248. data/lib/datadog/tracing/contrib/status_range_env_parser.rb +1 -1
  249. data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +1 -1
  250. data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +1 -1
  251. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +3 -3
  252. data/lib/datadog/tracing/contrib/utils/quantization/http.rb +102 -0
  253. data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +2 -2
  254. data/lib/datadog/tracing/contrib/waterdrop.rb +1 -1
  255. data/lib/datadog/tracing/diagnostics/environment_logger.rb +1 -1
  256. data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
  257. data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
  258. data/lib/datadog/tracing/distributed/baggage.rb +3 -3
  259. data/lib/datadog/tracing/distributed/datadog.rb +3 -3
  260. data/lib/datadog/tracing/distributed/propagation.rb +7 -7
  261. data/lib/datadog/tracing/distributed/trace_context.rb +1 -1
  262. data/lib/datadog/tracing/distributed/trace_state/open_telemetry.rb +1 -1
  263. data/lib/datadog/tracing/otel_thread_context.rb +3 -3
  264. data/lib/datadog/tracing/pipeline.rb +1 -1
  265. data/lib/datadog/tracing/remote.rb +50 -19
  266. data/lib/datadog/tracing/sampling/priority_sampler.rb +1 -1
  267. data/lib/datadog/tracing/sampling/rule.rb +1 -1
  268. data/lib/datadog/tracing/sampling/rule_sampler.rb +1 -1
  269. data/lib/datadog/tracing/sampling/span/rule_parser.rb +2 -2
  270. data/lib/datadog/tracing/span_operation.rb +1 -1
  271. data/lib/datadog/tracing/trace_digest.rb +1 -1
  272. data/lib/datadog/tracing/trace_operation.rb +6 -6
  273. data/lib/datadog/tracing/tracer.rb +6 -6
  274. data/lib/datadog/tracing/transport/http/telemetry.rb +1 -1
  275. data/lib/datadog/tracing/transport/http.rb +2 -2
  276. data/lib/datadog/tracing/transport/io.rb +1 -1
  277. data/lib/datadog/tracing/transport/native.rb +3 -3
  278. data/lib/datadog/tracing/transport/statistics.rb +2 -2
  279. data/lib/datadog/tracing/transport/telemetry.rb +3 -1
  280. data/lib/datadog/tracing/transport/trace_formatter.rb +12 -12
  281. data/lib/datadog/tracing/transport/traces.rb +1 -1
  282. data/lib/datadog/tracing/utils.rb +1 -1
  283. data/lib/datadog/tracing/workers.rb +1 -1
  284. data/lib/datadog/version.rb +1 -1
  285. metadata +9 -8
  286. data/lib/datadog/appsec/utils/hash_coercion.rb +0 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 90e55c02331cafb4d96cd0dedf6edb09fc5a6c7f993ffd611d8ca13f12d42cdb
4
- data.tar.gz: a99ea41f5975708838075815674c78e47a46ef8368188186d2e20653a8372b19
3
+ metadata.gz: ac4a0fce689b8c65bbe4c00847dbaf3e84bf7eda13ea48fc40cab57d5332a04f
4
+ data.tar.gz: dbf9526b321135b7e9e014578a5abe92a89e339a4ba2d9f7997718194e76a302
5
5
  SHA512:
6
- metadata.gz: 4061492c8bba7bf1238b6442d9275bbd7172978ecdbe4d4a92b53f0c67c2ca2d7b20947aaa42247fdc37ccbe81502710b4d69733e420e18fcd1e13d6e27b9864
7
- data.tar.gz: 6fe366c5fcb305780a575c830bc77967be48605478071c1d16975242a95cb5c178b81dac776306f5b082b27770140174d29ad0c4dd7df3c9522b4a048883303f
6
+ metadata.gz: dbbbc2ca84a95852a6614ba6cbc21c0fc68c4badef35c34dc29059ef6feffb0307ac0d19ffc955d8b7ac3f807007d4ea9577490dee99e0bb9f98f4d158ac8093
7
+ data.tar.gz: 3ec630b843cd8e57b14a227afe815c1e07f8a5c5bcbbffd62a41a19c57c5f204e8302059dd9bce0c7d89d1667f7a93ae6219686ec55aef5961ee23082ff56f26
data/CHANGELOG.md CHANGED
@@ -2,6 +2,45 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [2.48.0] - 2026-11-03
6
+
7
+ ### Added
8
+
9
+ * Dynamic Instrumentation: Limit condition, capture-expression, and template evaluation CPU time with `DD_DYNAMIC_INSTRUMENTATION_EVALUATION_TIMEOUT_MS` (default `50`); over-budget evaluation is reported as an evaluation error. ([#6223][])
10
+ * Open Feature: Add onboarding diagnostics for configuration delivery, provider readiness, flag evaluations, and exposures with `DD_TRACE_DEBUG=true`. Evaluation logs include raw data that may contain personal or sensitive information. ([#6519][])
11
+
12
+ ### Changed
13
+
14
+ * Core: Require C11 (`-std=gnu11`) support to build native extensions on Linux. ([#6596][])
15
+ * Profiling: Show class and module names in profiler stack frames by default, e.g. `Foo::Bar#baz` instead of `baz`, making methods easier to identify. ([#6537][])
16
+ * Dynamic Instrumentation: Lower the per-call limit of the `matches` expression operator from 500 ms to 50 ms of wall time; a slow regular expression in a probe now delays the instrumented method by at most 50 ms per call and reports an evaluation error. ([#6223][])
17
+ * Data Streams: Start a new pathway when a consume and the produce that follows it run on different threads; to keep one pathway across the hand-off, pass the context with `set_produce_checkpoint` and `set_consume_checkpoint`. ([#6532][])
18
+
19
+ ### Fixed
20
+
21
+ * Tracing: Fix the `_dd.rc.client_id` span tag occasionally carrying the client id of a different remote-configuration connection during component reconnection. ([#6601][])
22
+ * AppSec: Fix missing SQL injection detection in applications using `ActiveRecord` 8.0 and later. ([#6581][])
23
+ * AI Guard: Fix a rare crash when building the AI Guard client endpoint while the Datadog site setting changes concurrently. ([#6601][])
24
+ * Data Streams: Fix full-pathway latency inflated by minutes, and messages linked to the wrong pathway, in multi-threaded or forking apps such as `Karafka` consumers and `ActiveJob` workers. ([#6532][])
25
+
26
+ ## [2.47.0] - 2026-10-26
27
+
28
+ ### Added
29
+
30
+ * Tracing: Add quantized request paths to outbound HTTP client resource names, such as `GET /users/*`; enable with `DD_TRACE_HTTP_CLIENT_RESOURCE_NAME_QUANTIZE=true`. ([#6298][])
31
+ * Open Feature: Let evaluations opt out of flag evaluation events, metrics, and span tags with `dd_evaluation_telemetry_opt_out: true` in the evaluation context; enable it with `DD_FEATURE_FLAGS_EVALUATION_TELEMETRY_PER_SUBJECT_OPT_OUT_ENABLED=true`. ([#6486][])
32
+
33
+ ### Changed
34
+
35
+ * AppSec: Update `libddwaf` to 1.30.0.1.0. ([#6548][])
36
+
37
+ ### Fixed
38
+
39
+ * Core: Fix forked processes, such as Puma and Unicorn workers, reporting no runtime metrics when the parent process traced before forking. ([#6500][]) ([@dduugg][])
40
+ * Profiling: Fix the "no signals" workaround being enabled when `mysql2` uses MariaDB Connector/C 3.x. ([#6543][])
41
+ * AppSec: Fix ruleset updates with Remote Configuration. ([#6547][])
42
+ * AppSec: Fix duplicate JSON serialization of Rails and Sinatra response objects when application security is enabled. ([#6548][])
43
+
5
44
  ## [2.46.0] - 2026-10-19
6
45
 
7
46
  ### Added
@@ -3851,7 +3890,9 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
3851
3890
  Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3852
3891
 
3853
3892
 
3854
- [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.46.0...master
3893
+ [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.48.0...master
3894
+ [2.48.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.47.0...v2.48.0
3895
+ [2.47.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.46.0...v2.47.0
3855
3896
  [2.46.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.45.0...v2.46.0
3856
3897
  [2.45.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.44.0...v2.45.0
3857
3898
  [2.44.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.43.0...v2.44.0
@@ -5687,6 +5728,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
5687
5728
  [#6213]: https://github.com/DataDog/dd-trace-rb/issues/6213
5688
5729
  [#6219]: https://github.com/DataDog/dd-trace-rb/issues/6219
5689
5730
  [#6220]: https://github.com/DataDog/dd-trace-rb/issues/6220
5731
+ [#6223]: https://github.com/DataDog/dd-trace-rb/issues/6223
5690
5732
  [#6232]: https://github.com/DataDog/dd-trace-rb/issues/6232
5691
5733
  [#6234]: https://github.com/DataDog/dd-trace-rb/issues/6234
5692
5734
  [#6242]: https://github.com/DataDog/dd-trace-rb/issues/6242
@@ -5694,6 +5736,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
5694
5736
  [#6261]: https://github.com/DataDog/dd-trace-rb/issues/6261
5695
5737
  [#6286]: https://github.com/DataDog/dd-trace-rb/issues/6286
5696
5738
  [#6291]: https://github.com/DataDog/dd-trace-rb/issues/6291
5739
+ [#6298]: https://github.com/DataDog/dd-trace-rb/issues/6298
5697
5740
  [#6316]: https://github.com/DataDog/dd-trace-rb/issues/6316
5698
5741
  [#6320]: https://github.com/DataDog/dd-trace-rb/issues/6320
5699
5742
  [#6339]: https://github.com/DataDog/dd-trace-rb/issues/6339
@@ -5721,7 +5764,18 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
5721
5764
  [#6474]: https://github.com/DataDog/dd-trace-rb/issues/6474
5722
5765
  [#6481]: https://github.com/DataDog/dd-trace-rb/issues/6481
5723
5766
  [#6485]: https://github.com/DataDog/dd-trace-rb/issues/6485
5767
+ [#6486]: https://github.com/DataDog/dd-trace-rb/issues/6486
5724
5768
  [#6488]: https://github.com/DataDog/dd-trace-rb/issues/6488
5769
+ [#6500]: https://github.com/DataDog/dd-trace-rb/issues/6500
5770
+ [#6519]: https://github.com/DataDog/dd-trace-rb/issues/6519
5771
+ [#6532]: https://github.com/DataDog/dd-trace-rb/issues/6532
5772
+ [#6537]: https://github.com/DataDog/dd-trace-rb/issues/6537
5773
+ [#6543]: https://github.com/DataDog/dd-trace-rb/issues/6543
5774
+ [#6547]: https://github.com/DataDog/dd-trace-rb/issues/6547
5775
+ [#6548]: https://github.com/DataDog/dd-trace-rb/issues/6548
5776
+ [#6581]: https://github.com/DataDog/dd-trace-rb/issues/6581
5777
+ [#6596]: https://github.com/DataDog/dd-trace-rb/issues/6596
5778
+ [#6601]: https://github.com/DataDog/dd-trace-rb/issues/6601
5725
5779
  [@AdrianLC]: https://github.com/AdrianLC
5726
5780
  [@Azure7111]: https://github.com/Azure7111
5727
5781
  [@BabyGroot]: https://github.com/BabyGroot
@@ -5878,4 +5932,4 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
5878
5932
  [@y-yagi]: https://github.com/y-yagi
5879
5933
  [@yujideveloper]: https://github.com/yujideveloper
5880
5934
  [@yukimurasawa]: https://github.com/yukimurasawa
5881
- [@zachmccormick]: https://github.com/zachmccormick
5935
+ [@zachmccormick]: https://github.com/zachmccormick
data/LICENSE-3rdparty.csv CHANGED
@@ -5,3 +5,4 @@
5
5
  "lib/datadog/tracing/contrib/active_record/vendor","https://github.com/rails/rails/","MIT","Copyright (c) 2005-2018 David Heinemeier Hansson"
6
6
  "lib/datadog/tracing/contrib/utils/quantization/http.rb","https://github.com/ruby/uri","BSD-2-Clause","Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved."
7
7
  "msgpack","https://rubygems.org/gems/msgpack","Apache-2.0","Copyright (c) 2008-2015 Sadayuki Furuhashi"
8
+ "rubocop/custom_cops/trailing_comma_in_arguments_cop.rb","https://github.com/rubocop/rubocop","MIT","Copyright (c) 2012-25 Bozhidar Batsov"
@@ -41,7 +41,7 @@ static const char *get_or_compute_native_filename(void *function, st_table *nati
41
41
  static void initialize_static_ruby_actual_filename(VALUE profiling_module);
42
42
  static void add_truncated_frames_placeholder(ddog_prof_Location *locations);
43
43
  static void record_placeholder_stack_in_native_code(VALUE recorder_instance, sample_values values, sample_labels labels);
44
- static void maybe_trim_template_random_ids(ddog_CharSlice *name_slice, ddog_CharSlice *filename_slice);
44
+ static void maybe_trim_template_random_ids(ddog_CharSlice *frame_name, ddog_CharSlice filename, bool frame_name_in_scratch_buffer);
45
45
 
46
46
  // NULL if we weren't able to get the native filename for the Ruby VM.
47
47
  // On a static Ruby without libruby.so, `get_or_compute_native_filename` returns `ruby_native_filename` but
@@ -180,7 +180,7 @@ static VALUE _native_sample(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self) {
180
180
  sample_locations locations;
181
181
  sample_locations_initialize(&locations, max_frames_requested, show_classes == Qtrue);
182
182
  sampling_buffer buffer;
183
- sampling_buffer_initialize(&buffer, max_frames_requested);
183
+ sampling_buffer_initialize(&buffer, max_frames_requested, show_classes == Qtrue);
184
184
 
185
185
  ddog_prof_Slice_Label slice_labels = {.ptr = labels, .len = labels_count};
186
186
 
@@ -239,6 +239,83 @@ static VALUE native_sample_ensure(VALUE args) {
239
239
 
240
240
  #define CHARSLICE_EQUALS(must_be_a_literal, charslice) (strlen("" must_be_a_literal) == charslice.len && strncmp(must_be_a_literal, charslice.ptr, charslice.len) == 0)
241
241
 
242
+ // The method name on its own, without any class/module name
243
+ static inline ddog_CharSlice unqualified_name(const rb_callable_method_entry_t *cme, const rb_iseq_t *iseq) {
244
+ VALUE name = ddtrace_location_base_label(cme, iseq);
245
+ return (name == Qfalse) ? DDOG_CHARSLICE_C("") : char_slice_from_ruby_string(name);
246
+ }
247
+
248
+ // When there's only wall-time in a sample, this means that the thread was not active in the sampled period, so we try
249
+ // to tell what it was doing instead.
250
+ //
251
+ // TODO: `method` is the unqualified method name
252
+ // because we don't always use qualified method names yet,
253
+ // and the checks below need something stable to compare to until we always do.
254
+ static void categorize_sample_state(
255
+ sample_labels labels,
256
+ frame_info frame,
257
+ ddog_CharSlice method,
258
+ DDTRACE_UNUSED ddog_CharSlice filename
259
+ ) {
260
+ ddog_prof_Label *state_label = labels.state_label;
261
+
262
+ // Did the caller already provide the state?
263
+ if (labels.is_gvl_waiting_state) {
264
+ state_label->str = DDOG_CHARSLICE_C("waiting for gvl");
265
+
266
+ // Otherwise, we try to categorize what the thread was doing based on what we observe at the top of the stack. This is a very rough
267
+ // approximation, and in the future we hope to replace this with a more accurate approach (such as using the
268
+ // GVL instrumentation API.)
269
+ } else if (!frame.is_ruby_frame) {
270
+ // We know that known versions of Ruby implement these using native code; thus if we find a method with the
271
+ // same name that is not native code, we ignore it, as it's probably a user method that coincidentally
272
+ // has the same name. Thus, even though "matching just by method name" is kinda weak,
273
+ // "matching by method name" + is native code seems actually to be good enough for a lot of cases.
274
+
275
+ if (CHARSLICE_EQUALS("sleep", method)) { // Expected to be Kernel.sleep
276
+ state_label->str = DDOG_CHARSLICE_C("sleeping");
277
+ } else if (CHARSLICE_EQUALS("select", method)) { // Expected to be Kernel.select
278
+ state_label->str = DDOG_CHARSLICE_C("waiting");
279
+ } else if (
280
+ CHARSLICE_EQUALS("synchronize", method) || // Expected to be Monitor/Mutex#synchronize on Ruby 2 & 3, and Monitor#synchronize on 4 (Mutex becomes <internal:thread_sync>)
281
+ #ifdef NO_PRIMITIVE_MUTEX_AND_CONDITION_VARIABLE // Ruby < 4
282
+ CHARSLICE_EQUALS("lock", method) || // Expected to be Mutex#lock
283
+ #endif
284
+ CHARSLICE_EQUALS("join", method) // Expected to be Thread#join
285
+ ) {
286
+ state_label->str = DDOG_CHARSLICE_C("blocked");
287
+ } else if (CHARSLICE_EQUALS("wait_readable", method)) { // Expected to be IO#wait_readable
288
+ state_label->str = DDOG_CHARSLICE_C("network");
289
+ } else if (CHARSLICE_EQUALS("_native_idle_sampling_loop", method)) { // Expected to be Datadog::Profiler::Collectors::IdleSamplingHelper#_native_idle_sampling_loop
290
+ state_label->str = DDOG_CHARSLICE_C("waiting");
291
+ } else if (CHARSLICE_EQUALS("_native_sampling_loop", method)) { // Expected to be Datadog::Profiler::Collectors::CpuAndWallTimeWorker#_native_sampling_loop
292
+ state_label->str = DDOG_CHARSLICE_C("sleeping");
293
+ }
294
+ #ifdef NO_PRIMITIVE_POP // Ruby < 3.2
295
+ else if (CHARSLICE_EQUALS("pop", method)) { // Expected to be Queue/SizedQueue#pop
296
+ state_label->str = DDOG_CHARSLICE_C("waiting");
297
+ }
298
+ #endif
299
+ } else {
300
+ #ifndef NO_PRIMITIVE_POP // Ruby >= 3.2
301
+ if (CHARSLICE_EQUALS("<internal:thread_sync>", filename)) {
302
+ if (CHARSLICE_EQUALS("pop", method)) { // Expected to be Queue/SizedQueue#pop
303
+ state_label->str = DDOG_CHARSLICE_C("waiting");
304
+ }
305
+ #ifndef NO_PRIMITIVE_MUTEX_AND_CONDITION_VARIABLE // Ruby >= 4
306
+ else if (CHARSLICE_EQUALS("synchronize", method) || CHARSLICE_EQUALS("lock", method)) { // Expected to be Mutex#lock/synchronize
307
+ state_label->str = DDOG_CHARSLICE_C("blocked");
308
+ } else if (CHARSLICE_EQUALS("sleep", method)) { // Expected to be Mutex#sleep
309
+ state_label->str = DDOG_CHARSLICE_C("sleeping");
310
+ } else if (CHARSLICE_EQUALS("wait", method)) { // Expected to be ConditionVariable#wait
311
+ state_label->str = DDOG_CHARSLICE_C("waiting");
312
+ }
313
+ #endif
314
+ }
315
+ #endif
316
+ }
317
+ }
318
+
242
319
  // Idea: Should we release the global vm lock (GVL) after we get the data from `rb_profile_frames`? That way other Ruby threads
243
320
  // could continue making progress while the sample was ingested into the profile.
244
321
  //
@@ -354,91 +431,45 @@ void sample_thread(
354
431
  );
355
432
  }
356
433
 
357
- VALUE name = ddtrace_location_base_label(cme, iseq);
358
- // TODO: name_slice is currently the unqualified method name
359
- // because we don't always use qualified method names yet, so we don't always compute it,
360
- // and checks below need to compare to something stable until we always qualified method names.
361
- ddog_CharSlice name_slice = (name == Qfalse) ? DDOG_CHARSLICE_C("") : char_slice_from_ruby_string(name);
434
+ // This frame kept the name we composed for it in an earlier sample, so there's nothing to compose or trim again
435
+ char *cached_name = buffer->cached_names == NULL ? NULL : buffer->cached_names + (i * MAX_CACHED_FRAME_NAME);
436
+ // The length is only ever set together with the name it describes, and frames start out zeroed
437
+ bool name_is_cached = frame.cached_name_len > 0;
362
438
 
363
- ddog_CharSlice qualified_name = DDOG_CHARSLICE_C("");
364
- if (show_classes) {
439
+ ddog_CharSlice frame_name;
440
+ // We only keep a name we managed to compose: ddtrace_location_label() also fails when this stack used up the
441
+ // scratch buffer, and keeping the unqualified name it falls back to would stick to the frame even once there's
442
+ // room for it again.
443
+ bool name_is_cacheable = false;
444
+ if (name_is_cached) {
445
+ frame_name = (ddog_CharSlice) {.ptr = cached_name, .len = frame.cached_name_len};
446
+ } else if (show_classes) {
365
447
  ssize_t written = ddtrace_location_label(cme, iseq, qualified_name_buf, qualified_name_buf_size);
366
448
  if (written > 0) {
367
- qualified_name = (ddog_CharSlice) {.ptr = qualified_name_buf, .len = written};
449
+ frame_name = (ddog_CharSlice) {.ptr = qualified_name_buf, .len = written};
368
450
  qualified_name_buf += written;
369
451
  qualified_name_buf_size -= written;
452
+ name_is_cacheable = true;
370
453
  } else {
371
- qualified_name = name_slice; // just the method name
454
+ frame_name = unqualified_name(cme, iseq); // just the method name
372
455
  }
456
+ } else {
457
+ frame_name = unqualified_name(cme, iseq);
373
458
  }
374
459
 
375
- // When there's only wall-time in a sample, this means that the thread was not active in the sampled period.
376
460
  if (top_of_the_stack && only_wall_time) {
377
- // Did the caller already provide the state?
378
- if (labels.is_gvl_waiting_state) {
379
- state_label->str = DDOG_CHARSLICE_C("waiting for gvl");
380
-
381
- // Otherwise, we try to categorize what the thread was doing based on what we observe at the top of the stack. This is a very rough
382
- // approximation, and in the future we hope to replace this with a more accurate approach (such as using the
383
- // GVL instrumentation API.)
384
- } else if (!frame.is_ruby_frame) {
385
- // We know that known versions of Ruby implement these using native code; thus if we find a method with the
386
- // same name that is not native code, we ignore it, as it's probably a user method that coincidentally
387
- // has the same name. Thus, even though "matching just by method name" is kinda weak,
388
- // "matching by method name" + is native code seems actually to be good enough for a lot of cases.
389
-
390
- if (CHARSLICE_EQUALS("sleep", name_slice)) { // Expected to be Kernel.sleep
391
- state_label->str = DDOG_CHARSLICE_C("sleeping");
392
- } else if (CHARSLICE_EQUALS("select", name_slice)) { // Expected to be Kernel.select
393
- state_label->str = DDOG_CHARSLICE_C("waiting");
394
- } else if (
395
- CHARSLICE_EQUALS("synchronize", name_slice) || // Expected to be Monitor/Mutex#synchronize on Ruby 2 & 3, and Monitor#synchronize on 4 (Mutex becomes <internal:thread_sync>)
396
- #ifdef NO_PRIMITIVE_MUTEX_AND_CONDITION_VARIABLE // Ruby < 4
397
- CHARSLICE_EQUALS("lock", name_slice) || // Expected to be Mutex#lock
398
- #endif
399
- CHARSLICE_EQUALS("join", name_slice) // Expected to be Thread#join
400
- ) {
401
- state_label->str = DDOG_CHARSLICE_C("blocked");
402
- } else if (CHARSLICE_EQUALS("wait_readable", name_slice)) { // Expected to be IO#wait_readable
403
- state_label->str = DDOG_CHARSLICE_C("network");
404
- } else if (CHARSLICE_EQUALS("_native_idle_sampling_loop", name_slice)) { // Expected to be Datadog::Profiler::Collectors::IdleSamplingHelper#_native_idle_sampling_loop
405
- state_label->str = DDOG_CHARSLICE_C("waiting");
406
- } else if (CHARSLICE_EQUALS("_native_sampling_loop", name_slice)) { // Expected to be Datadog::Profiler::Collectors::CpuAndWallTimeWorker#_native_sampling_loop
407
- state_label->str = DDOG_CHARSLICE_C("sleeping");
408
- }
409
- #ifdef NO_PRIMITIVE_POP // Ruby < 3.2
410
- else if (CHARSLICE_EQUALS("pop", name_slice)) { // Expected to be Queue/SizedQueue#pop
411
- state_label->str = DDOG_CHARSLICE_C("waiting");
412
- }
413
- #endif
414
- } else {
415
- #ifndef NO_PRIMITIVE_POP // Ruby >= 3.2
416
- if (CHARSLICE_EQUALS("<internal:thread_sync>", filename_slice)) {
417
- if (CHARSLICE_EQUALS("pop", name_slice)) { // Expected to be Queue/SizedQueue#pop
418
- state_label->str = DDOG_CHARSLICE_C("waiting");
419
- }
420
- #ifndef NO_PRIMITIVE_MUTEX_AND_CONDITION_VARIABLE // Ruby >= 4
421
- else if (CHARSLICE_EQUALS("synchronize", name_slice) || CHARSLICE_EQUALS("lock", name_slice)) { // Expected to be Mutex#lock/synchronize
422
- state_label->str = DDOG_CHARSLICE_C("blocked");
423
- } else if (CHARSLICE_EQUALS("sleep", name_slice)) { // Expected to be Mutex#sleep
424
- state_label->str = DDOG_CHARSLICE_C("sleeping");
425
- } else if (CHARSLICE_EQUALS("wait", name_slice)) { // Expected to be ConditionVariable#wait
426
- state_label->str = DDOG_CHARSLICE_C("waiting");
427
- }
428
- #endif
429
- }
430
- #endif
431
- }
461
+ categorize_sample_state(labels, frame, unqualified_name(cme, iseq), filename_slice);
432
462
  }
433
463
 
434
- ddog_CharSlice frame_name;
435
- if (show_classes) {
436
- frame_name = qualified_name;
437
- } else {
438
- frame_name = name_slice;
439
- }
464
+ if (!name_is_cached) {
465
+ maybe_trim_template_random_ids(&frame_name, filename_slice, name_is_cacheable);
440
466
 
441
- maybe_trim_template_random_ids(&frame_name, &filename_slice);
467
+ // Keep this name for as long as the frame stays in the buffer
468
+ if (cached_name != NULL && name_is_cacheable && frame_name.len <= MAX_CACHED_FRAME_NAME) {
469
+ memcpy(cached_name, frame_name.ptr, frame_name.len);
470
+ buffer->stack_buffer[i].cached_name_len = frame_name.len;
471
+ }
472
+ }
442
473
 
443
474
  int libdatadog_stores_stacks_flipped_from_rb_profile_frames_index = top_of_stack_position - i;
444
475
 
@@ -548,33 +579,56 @@ static const char *get_or_compute_native_filename(void *function, st_table *nati
548
579
  // the extra "_".)
549
580
  //
550
581
  // This method trims these suffixes, so that we keep less data + the names correctly aggregate together.
551
- static void maybe_trim_template_random_ids(ddog_CharSlice *name_slice, ddog_CharSlice *filename_slice) {
582
+ //
583
+ // The ids end `frame_name`, or sit right before DDTRACE_BLOCK_SUFFIX
584
+ // ("Foo#_app_views_articles_index_html_erb__123_456 (block)"); in that case we move the suffix left over the ids.
585
+ // That write needs a name we composed ourselves, which is what `frame_name_in_scratch_buffer` tells us.
586
+ static void maybe_trim_template_random_ids(
587
+ ddog_CharSlice *frame_name,
588
+ ddog_CharSlice filename,
589
+ bool frame_name_in_scratch_buffer
590
+ ) {
552
591
  // Check filename doesn't end with ".rb"; templates are usually along the lines of .html.erb/.html.haml/...
553
- if (filename_slice->len < 3 || memcmp(filename_slice->ptr + filename_slice->len - 3, ".rb", 3) == 0) return;
592
+ if (filename.len < 3 || memcmp(filename.ptr + filename.len - 3, ".rb", 3) == 0) return;
593
+
594
+ if (frame_name->len > 1024) return;
595
+ if (frame_name->len == 0) return;
596
+
597
+ static const char block_suffix[] = DDTRACE_BLOCK_SUFFIX;
598
+ size_t block_suffix_len = sizeof(block_suffix) - 1;
554
599
 
555
- if (name_slice->len > 1024) return;
556
- if (name_slice->len == 0) return;
600
+ size_t len = frame_name->len;
601
+ bool has_block_suffix =
602
+ frame_name_in_scratch_buffer &&
603
+ len > block_suffix_len &&
604
+ memcmp(frame_name->ptr + len - block_suffix_len, block_suffix, block_suffix_len) == 0;
605
+ if (has_block_suffix) len -= block_suffix_len;
557
606
 
558
- int pos = ((int) name_slice->len) - 1;
607
+ int pos = ((int) len) - 1;
559
608
 
560
609
  // Let's match on something__number_number:
561
610
  // Find start of id suffix from the end...
562
- if (name_slice->ptr[pos] < '0' || name_slice->ptr[pos] > '9') return;
611
+ if (frame_name->ptr[pos] < '0' || frame_name->ptr[pos] > '9') return;
563
612
 
564
613
  // ...now match a bunch of numbers and interspersed underscores
565
614
  for (int underscores = 0; pos >= 0 && underscores < 2; pos--) {
566
- if (name_slice->ptr[pos] == '_') underscores++;
567
- else if (name_slice->ptr[pos] < '0' || name_slice->ptr[pos] > '9') return;
615
+ if (frame_name->ptr[pos] == '_') underscores++;
616
+ else if (frame_name->ptr[pos] < '0' || frame_name->ptr[pos] > '9') return;
568
617
  }
569
618
 
570
619
  // Make sure there's something left before the underscores (hence the <= instead of <) + match the last underscore
571
- if (pos <= 0 || name_slice->ptr[pos] != '_') return;
620
+ if (pos <= 0 || frame_name->ptr[pos] != '_') return;
572
621
 
573
622
  // Does it have the optional third underscore? If so, remove it as well
574
- if (pos > 1 && name_slice->ptr[pos-1] == '_') pos--;
623
+ if (pos > 1 && frame_name->ptr[pos-1] == '_') pos--;
575
624
 
576
625
  // If we got here, we matched on our pattern. Let's slice the length of the string to exclude it.
577
- name_slice->len = pos;
626
+ if (has_block_suffix) {
627
+ memcpy((char *) frame_name->ptr + pos, block_suffix, block_suffix_len);
628
+ frame_name->len = pos + block_suffix_len;
629
+ } else {
630
+ frame_name->len = pos;
631
+ }
578
632
  }
579
633
 
580
634
  static void add_truncated_frames_placeholder(ddog_prof_Location *locations) {
@@ -680,7 +734,7 @@ uint16_t sampling_buffer_check_max_frames(int max_frames) {
680
734
  return max_frames;
681
735
  }
682
736
 
683
- void sampling_buffer_initialize(sampling_buffer *buffer, uint16_t max_frames) {
737
+ void sampling_buffer_initialize(sampling_buffer *buffer, uint16_t max_frames, bool cache_names) {
684
738
  sampling_buffer_check_max_frames(max_frames);
685
739
 
686
740
  buffer->max_frames = max_frames;
@@ -688,16 +742,19 @@ void sampling_buffer_initialize(sampling_buffer *buffer, uint16_t max_frames) {
688
742
  buffer->pending_sample = false;
689
743
  buffer->is_marking = false;
690
744
  buffer->pending_sample_result = 0;
745
+ buffer->cached_names = cache_names ? ruby_xcalloc(max_frames, MAX_CACHED_FRAME_NAME) : NULL;
691
746
  }
692
747
 
693
748
  void sampling_buffer_free(sampling_buffer *buffer) {
694
749
  ruby_xfree(buffer->stack_buffer);
750
+ ruby_xfree(buffer->cached_names);
695
751
 
696
752
  buffer->max_frames = 0;
697
753
  buffer->stack_buffer = NULL;
698
754
  buffer->pending_sample = false;
699
755
  buffer->is_marking = false;
700
756
  buffer->pending_sample_result = 0;
757
+ buffer->cached_names = NULL;
701
758
  }
702
759
 
703
760
  void sampling_buffer_mark(sampling_buffer *buffer) {
@@ -8,6 +8,10 @@
8
8
  #define MAX_FRAMES_LIMIT 3000
9
9
  #define MAX_FRAMES_LIMIT_AS_STRING "3000"
10
10
 
11
+ // Longest qualified frame name we keep per frame in `sampling_buffer`. Longer names are still reported, they just get
12
+ // composed again on every sample; this bounds the per-thread memory the cache costs (max_frames * this).
13
+ #define MAX_CACHED_FRAME_NAME 96
14
+
11
15
  // Per thread, where we store the stack sample
12
16
  typedef struct {
13
17
  uint16_t max_frames;
@@ -15,6 +19,10 @@ typedef struct {
15
19
  bool pending_sample;
16
20
  bool is_marking; // Used to avoid recording a sample when marking (marking can happen outside of GC as well)
17
21
  int pending_sample_result;
22
+ // Qualified frame names from the last sample, MAX_CACHED_FRAME_NAME bytes per frame (NULL when not qualifying names).
23
+ // A frame keeps its name for as long as it stays in `stack_buffer`, which is most of the time: between two samples
24
+ // of a thread, usually only the frames close to the top of the stack change.
25
+ char *cached_names;
18
26
  } sampling_buffer;
19
27
 
20
28
  // 1 per ThreadContext so effectively global.
@@ -55,7 +63,7 @@ void sample_locations_initialize(sample_locations *locations, uint16_t max_frame
55
63
  void sample_locations_free(sample_locations *locations);
56
64
 
57
65
  uint16_t sampling_buffer_check_max_frames(int max_frames);
58
- void sampling_buffer_initialize(sampling_buffer *buffer, uint16_t max_frames);
66
+ void sampling_buffer_initialize(sampling_buffer *buffer, uint16_t max_frames, bool cache_names);
59
67
  void sampling_buffer_free(sampling_buffer *buffer);
60
68
  void sampling_buffer_mark(sampling_buffer *buffer);
61
69
  static inline bool sampling_buffer_needs_marking(sampling_buffer *buffer) {
@@ -122,6 +122,10 @@ static ID otel_fiber_context_storage_id; // id of :@opentelemetry_context in Rub
122
122
  // in settings.rb. See `initialize_context` for details on why this is needed/used.
123
123
  static uint16_t latest_max_frames = 400;
124
124
 
125
+ // Same as `latest_max_frames`, for deciding whether new sampling buffers need room to cache qualified frame names.
126
+ // Should be kept in sync with the default for DD_PROFILING_EXPERIMENTAL_SHOW_CLASSES_ENABLED in settings.rb.
127
+ static bool latest_show_classes = true;
128
+
125
129
  // Global tracepoint for RUBY_EVENT_THREAD_BEGIN. Created and enabled once when the first ThreadContext collector is initialized.
126
130
  static VALUE thread_begin_tracepoint = Qnil;
127
131
 
@@ -1265,7 +1269,7 @@ static void initialize_context(VALUE thread, per_thread_context *thread_context,
1265
1269
  // We always create per_thread_context's with latest_max_frames; that value is kept in sync with the
1266
1270
  // active profiler's max_frames by the global reset that runs when profiling starts
1267
1271
  // so we expect to always see here the latest correct value to be used.
1268
- sampling_buffer_initialize(&thread_context->sampling_buffer, latest_max_frames);
1272
+ sampling_buffer_initialize(&thread_context->sampling_buffer, latest_max_frames, latest_show_classes);
1269
1273
 
1270
1274
  snprintf(thread_context->thread_id, THREAD_ID_LIMIT_CHARS, "%"PRIu64" (%lu)", native_thread_id_for(thread), (unsigned long) thread_id_for(thread));
1271
1275
  thread_context->thread_id_char_slice = (ddog_CharSlice) {.ptr = thread_context->thread_id, .len = strlen(thread_context->thread_id)};
@@ -1327,6 +1331,7 @@ void thread_context_collector_reset_all_per_thread_contexts(VALUE self_instance)
1327
1331
  }
1328
1332
 
1329
1333
  latest_max_frames = state->locations.len;
1334
+ latest_show_classes = state->show_classes;
1330
1335
 
1331
1336
  long current_monotonic_wall_time_ns = monotonic_wall_time_now_ns();
1332
1337
 
@@ -20,7 +20,7 @@ def skip_building_extension!(reason)
20
20
  Datadog::Profiling::NativeExtensionHelpers::Supported.failure_banner_for(
21
21
  **reason,
22
22
  fail_install: fail_install_if_missing_extension,
23
- )
23
+ ),
24
24
  )
25
25
 
26
26
  File.write(
@@ -32,7 +32,7 @@ def skip_building_extension!(reason)
32
32
  require "mkmf"
33
33
  Logging.message(
34
34
  "[datadog] Failure cause: " \
35
- "#{Datadog::Profiling::NativeExtensionHelpers::Supported.render_skipped_reason_file(**reason)}\n"
35
+ "#{Datadog::Profiling::NativeExtensionHelpers::Supported.render_skipped_reason_file(**reason)}\n",
36
36
  )
37
37
  else
38
38
  File.write("Makefile", "all install clean: # dummy makefile that does nothing")
@@ -63,7 +63,7 @@ $stderr.puts(
63
63
  | Thanks for using datadog! You rock! |
64
64
  +------------------------------------------------------------------------------+
65
65
 
66
- )
66
+ ),
67
67
  )
68
68
 
69
69
  # NOTE: we MUST NOT require 'mkmf' before we check the #skip_building_extension? because the require triggers checks
@@ -89,12 +89,10 @@ append_cflags "-Werror" if ENV["DATADOG_GEM_CI"] == "true"
89
89
  # header lands upstream in libdatadog/libdatadog-rb. Remove this once that ships.
90
90
  append_cflags "-Wno-error=typedef-redefinition" if ENV["DATADOG_GEM_CI"] == "true"
91
91
 
92
- # Older gcc releases may not default to C99 and we need to ask for this. This is also used:
93
- # * by upstream Ruby -- search for gnu99 in the codebase
94
- # * by msgpack, another datadog gem dependency
95
- # (https://github.com/msgpack/msgpack-ruby/blob/18ce08f6d612fe973843c366ac9a0b74c4e50599/ext/msgpack/extconf.rb#L8)
96
- # @ivoanjo: We could probably start using C11/gnu11 for non macOS-too but it's somewhat hard to validate so I chickened out for now
97
- append_cflags RUBY_PLATFORM.include?("darwin") ? "-std=gnu11" : "-std=gnu99"
92
+ unless try_cflags("-std=gnu11") && have_type("atomic_int", ["stdatomic.h"])
93
+ skip_building_extension!(Datadog::Profiling::NativeExtensionHelpers::Supported::COMPILER_C11_MISSING)
94
+ end
95
+ $CFLAGS += " -std=gnu11"
98
96
 
99
97
  # Gets really noisy when we include the private VM headers, let's omit it (TODO: Use #pragma GCC diagnostic instead?)
100
98
  append_cflags "-Wno-unused-function"
@@ -225,10 +223,6 @@ end
225
223
 
226
224
  Datadog::LibdatadogExtconfHelpers.add_libdatadog_version_define
227
225
 
228
- unless have_type("atomic_int", ["stdatomic.h"])
229
- skip_building_extension!(Datadog::Profiling::NativeExtensionHelpers::Supported::COMPILER_ATOMIC_MISSING)
230
- end
231
-
232
226
  # Tag the native extension library with the Ruby version and Ruby platform.
233
227
  # This makes it easier for development (avoids "oops I forgot to rebuild when I switched my Ruby") and ensures that
234
228
  # the wrong library is never loaded.
@@ -94,9 +94,9 @@ module Datadog
94
94
  )
95
95
 
96
96
  # Validation for this check is done in extconf.rb because it relies on mkmf
97
- COMPILER_ATOMIC_MISSING = explain_issue(
98
- "your C compiler is missing support for the <stdatomic.h> header.",
99
- "This issue can usually be fixed by upgrading to a later version of your",
97
+ COMPILER_C11_MISSING = explain_issue(
98
+ "your C compiler does not support C11 (-std=gnu11).",
99
+ "This issue can be fixed by upgrading to a later version of your",
100
100
  "operating system image or compiler.",
101
101
  suggested: CONTACT_SUPPORT,
102
102
  )