datadog 2.47.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 (273) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -1
  3. data/LICENSE-3rdparty.csv +1 -0
  4. data/ext/datadog_profiling_native_extension/collectors_stack.c +141 -101
  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 +66 -13
  10. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +5 -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 +1 -1
  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 +2 -2
  48. data/lib/datadog/appsec/contrib/rails/patcher.rb +2 -2
  49. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +1 -1
  50. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +3 -3
  51. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +1 -1
  52. data/lib/datadog/appsec/metrics/collector.rb +5 -5
  53. data/lib/datadog/appsec/metrics/telemetry_exporter.rb +3 -3
  54. data/lib/datadog/appsec/monitor/gateway/watcher.rb +2 -2
  55. data/lib/datadog/appsec/processor/rule_loader.rb +1 -1
  56. data/lib/datadog/appsec/response.rb +1 -1
  57. data/lib/datadog/appsec/security_engine/engine.rb +6 -6
  58. data/lib/datadog/appsec/security_engine/runner.rb +2 -2
  59. data/lib/datadog/appsec/trace_keeper.rb +1 -1
  60. data/lib/datadog/appsec.rb +1 -1
  61. data/lib/datadog/core/configuration/agent_settings_resolver.rb +14 -13
  62. data/lib/datadog/core/configuration/agentless_settings_resolver.rb +2 -2
  63. data/lib/datadog/core/configuration/components.rb +1 -1
  64. data/lib/datadog/core/configuration/settings.rb +5 -2
  65. data/lib/datadog/core/configuration/supported_configurations.rb +1 -0
  66. data/lib/datadog/core/configuration.rb +2 -2
  67. data/lib/datadog/core/crashtracking/component.rb +1 -1
  68. data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
  69. data/lib/datadog/core/environment/cgroup.rb +2 -2
  70. data/lib/datadog/core/environment/container.rb +3 -3
  71. data/lib/datadog/core/metrics/client.rb +6 -6
  72. data/lib/datadog/core/process_discovery.rb +1 -1
  73. data/lib/datadog/core/remote/tie/tracing.rb +4 -3
  74. data/lib/datadog/core/remote/transport/http.rb +2 -2
  75. data/lib/datadog/core/runtime/metrics.rb +14 -14
  76. data/lib/datadog/core/semaphore.rb +3 -1
  77. data/lib/datadog/core/telemetry/event/app_started.rb +9 -9
  78. data/lib/datadog/core/telemetry/logger.rb +1 -1
  79. data/lib/datadog/core/telemetry/logging.rb +1 -1
  80. data/lib/datadog/core/telemetry/request.rb +9 -3
  81. data/lib/datadog/core/telemetry/transport/http.rb +2 -2
  82. data/lib/datadog/core/telemetry/worker.rb +1 -1
  83. data/lib/datadog/core/transport/http/adapters/net.rb +1 -1
  84. data/lib/datadog/core/transport/http/adapters/unix_socket.rb +1 -1
  85. data/lib/datadog/core/transport/http/builder.rb +1 -1
  86. data/lib/datadog/core/transport/http.rb +3 -3
  87. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +2 -2
  88. data/lib/datadog/core/workers/async.rb +1 -1
  89. data/lib/datadog/core/workers/runtime_metrics.rb +1 -1
  90. data/lib/datadog/data_streams/pathway_context.rb +1 -1
  91. data/lib/datadog/data_streams/processor.rb +48 -27
  92. data/lib/datadog/data_streams/transport/http.rb +1 -1
  93. data/lib/datadog/data_streams.rb +16 -0
  94. data/lib/datadog/di/capture_expression_evaluator.rb +48 -11
  95. data/lib/datadog/di/component.rb +3 -2
  96. data/lib/datadog/di/configuration.rb +19 -0
  97. data/lib/datadog/di/contrib/active_record.rb +1 -1
  98. data/lib/datadog/di/el/compiler.rb +4 -4
  99. data/lib/datadog/di/el/evaluator.rb +247 -43
  100. data/lib/datadog/di/el/expression.rb +36 -6
  101. data/lib/datadog/di/error.rb +16 -0
  102. data/lib/datadog/di/guardrails_telemetry/reason.rb +3 -2
  103. data/lib/datadog/di/instrumenter.rb +39 -10
  104. data/lib/datadog/di/probe_notification_builder.rb +58 -10
  105. data/lib/datadog/di/probe_notifier_worker.rb +1 -1
  106. data/lib/datadog/di/serializer.rb +20 -2
  107. data/lib/datadog/di.rb +27 -0
  108. data/lib/datadog/error_tracking/component.rb +1 -1
  109. data/lib/datadog/error_tracking/configuration.rb +1 -1
  110. data/lib/datadog/kit/appsec/events/v2.rb +6 -6
  111. data/lib/datadog/kit/appsec/events.rb +1 -1
  112. data/lib/datadog/kit/enable_core_dumps.rb +1 -1
  113. data/lib/datadog/kit/identity.rb +1 -1
  114. data/lib/datadog/open_feature/activation.rb +26 -1
  115. data/lib/datadog/open_feature/agentless/configuration_source.rb +94 -15
  116. data/lib/datadog/open_feature/component.rb +22 -2
  117. data/lib/datadog/open_feature/configuration/agentless_endpoint.rb +6 -0
  118. data/lib/datadog/open_feature/configuration.rb +4 -4
  119. data/lib/datadog/open_feature/evaluation_engine.rb +62 -4
  120. data/lib/datadog/open_feature/exposures/buffer.rb +4 -0
  121. data/lib/datadog/open_feature/exposures/reporter.rb +17 -4
  122. data/lib/datadog/open_feature/exposures/worker.rb +37 -6
  123. data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +5 -5
  124. data/lib/datadog/open_feature/flag_evaluation/writer.rb +1 -1
  125. data/lib/datadog/open_feature/hooks/debug_logging_hook.rb +56 -0
  126. data/lib/datadog/open_feature/hooks/span_enrichment_hook.rb +2 -2
  127. data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +1 -1
  128. data/lib/datadog/open_feature/native_evaluator.rb +1 -1
  129. data/lib/datadog/open_feature/noop_evaluator.rb +1 -1
  130. data/lib/datadog/open_feature/provider.rb +50 -12
  131. data/lib/datadog/open_feature/remote.rb +8 -1
  132. data/lib/datadog/open_feature/resolution_details.rb +2 -2
  133. data/lib/datadog/open_feature/transport.rb +6 -6
  134. data/lib/datadog/opentelemetry/api/context.rb +3 -3
  135. data/lib/datadog/opentelemetry/logs.rb +5 -5
  136. data/lib/datadog/opentelemetry/metrics.rb +3 -3
  137. data/lib/datadog/opentelemetry/sdk/propagator.rb +3 -3
  138. data/lib/datadog/opentelemetry/sdk/span_processor.rb +2 -2
  139. data/lib/datadog/opentelemetry/sdk/trace/span.rb +1 -1
  140. data/lib/datadog/profiling/collectors/code_provenance.rb +3 -3
  141. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +4 -4
  142. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -1
  143. data/lib/datadog/profiling/collectors/thread_context.rb +1 -1
  144. data/lib/datadog/profiling/component.rb +19 -19
  145. data/lib/datadog/profiling/exporter.rb +1 -1
  146. data/lib/datadog/profiling/http_transport.rb +3 -3
  147. data/lib/datadog/profiling/profiler.rb +2 -2
  148. data/lib/datadog/profiling/scheduler.rb +2 -2
  149. data/lib/datadog/profiling/tag_builder.rb +1 -1
  150. data/lib/datadog/symbol_database/extractor.rb +8 -8
  151. data/lib/datadog/symbol_database/uploader.rb +1 -1
  152. data/lib/datadog/tracing/buffer.rb +3 -3
  153. data/lib/datadog/tracing/client_ip.rb +1 -1
  154. data/lib/datadog/tracing/component.rb +8 -8
  155. data/lib/datadog/tracing/configuration/dynamic/option.rb +2 -2
  156. data/lib/datadog/tracing/configuration/settings.rb +3 -3
  157. data/lib/datadog/tracing/context.rb +1 -1
  158. data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +2 -2
  159. data/lib/datadog/tracing/contrib/active_job/data_streams.rb +27 -2
  160. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +2 -2
  161. data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +1 -1
  162. data/lib/datadog/tracing/contrib/active_record/utils.rb +1 -1
  163. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +1 -1
  164. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +1 -1
  165. data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +2 -2
  166. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +2 -2
  167. data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +1 -1
  168. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +1 -1
  169. data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +1 -1
  170. data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +1 -1
  171. data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +2 -2
  172. data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +1 -1
  173. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +3 -3
  174. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +1 -1
  175. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +8 -8
  176. data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +1 -1
  177. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +1 -1
  178. data/lib/datadog/tracing/contrib/excon/middleware.rb +7 -7
  179. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +1 -1
  180. data/lib/datadog/tracing/contrib/faraday/middleware.rb +5 -5
  181. data/lib/datadog/tracing/contrib/grape/endpoint.rb +4 -4
  182. data/lib/datadog/tracing/contrib/graphql/patcher.rb +1 -1
  183. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +3 -3
  184. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +1 -1
  185. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +2 -2
  186. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +1 -1
  187. data/lib/datadog/tracing/contrib/grpc.rb +1 -1
  188. data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +1 -1
  189. data/lib/datadog/tracing/contrib/hanami/plugin.rb +1 -1
  190. data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +1 -1
  191. data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +1 -1
  192. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +1 -1
  193. data/lib/datadog/tracing/contrib/http/instrumentation.rb +6 -6
  194. data/lib/datadog/tracing/contrib/http.rb +1 -1
  195. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +1 -1
  196. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +7 -7
  197. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +1 -1
  198. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +5 -5
  199. data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +2 -2
  200. data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +2 -2
  201. data/lib/datadog/tracing/contrib/karafka/monitor.rb +1 -1
  202. data/lib/datadog/tracing/contrib/karafka/patcher.rb +1 -1
  203. data/lib/datadog/tracing/contrib/karafka.rb +1 -1
  204. data/lib/datadog/tracing/contrib/lograge/patcher.rb +1 -1
  205. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +1 -1
  206. data/lib/datadog/tracing/contrib/mongodb/parsers.rb +1 -1
  207. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +1 -1
  208. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +1 -1
  209. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +3 -3
  210. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +2 -2
  211. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +3 -3
  212. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +1 -1
  213. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +4 -4
  214. data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +1 -1
  215. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +4 -4
  216. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +1 -1
  217. data/lib/datadog/tracing/contrib/que/tracer.rb +1 -1
  218. data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +1 -1
  219. data/lib/datadog/tracing/contrib/racecar/events/batch.rb +1 -1
  220. data/lib/datadog/tracing/contrib/racecar/events/message.rb +1 -1
  221. data/lib/datadog/tracing/contrib/rack/middlewares.rb +3 -3
  222. data/lib/datadog/tracing/contrib/rack/patcher.rb +1 -1
  223. data/lib/datadog/tracing/contrib/rails/framework.rb +7 -7
  224. data/lib/datadog/tracing/contrib/rails/log_injection.rb +1 -1
  225. data/lib/datadog/tracing/contrib/rails/runner.rb +4 -4
  226. data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +1 -1
  227. data/lib/datadog/tracing/contrib/redis/quantize.rb +1 -1
  228. data/lib/datadog/tracing/contrib/redis/tags.rb +1 -1
  229. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +1 -1
  230. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +8 -8
  231. data/lib/datadog/tracing/contrib/sequel/database.rb +1 -1
  232. data/lib/datadog/tracing/contrib/sequel/dataset.rb +1 -1
  233. data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +1 -1
  234. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +2 -2
  235. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +2 -2
  236. data/lib/datadog/tracing/contrib/sidekiq.rb +1 -1
  237. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +1 -1
  238. data/lib/datadog/tracing/contrib/status_range_env_parser.rb +1 -1
  239. data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +1 -1
  240. data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +1 -1
  241. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +3 -3
  242. data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +2 -2
  243. data/lib/datadog/tracing/contrib/waterdrop.rb +1 -1
  244. data/lib/datadog/tracing/diagnostics/environment_logger.rb +1 -1
  245. data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
  246. data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
  247. data/lib/datadog/tracing/distributed/baggage.rb +3 -3
  248. data/lib/datadog/tracing/distributed/datadog.rb +3 -3
  249. data/lib/datadog/tracing/distributed/propagation.rb +7 -7
  250. data/lib/datadog/tracing/distributed/trace_context.rb +1 -1
  251. data/lib/datadog/tracing/distributed/trace_state/open_telemetry.rb +1 -1
  252. data/lib/datadog/tracing/otel_thread_context.rb +3 -3
  253. data/lib/datadog/tracing/pipeline.rb +1 -1
  254. data/lib/datadog/tracing/sampling/priority_sampler.rb +1 -1
  255. data/lib/datadog/tracing/sampling/rule.rb +1 -1
  256. data/lib/datadog/tracing/sampling/rule_sampler.rb +1 -1
  257. data/lib/datadog/tracing/sampling/span/rule_parser.rb +2 -2
  258. data/lib/datadog/tracing/span_operation.rb +1 -1
  259. data/lib/datadog/tracing/trace_digest.rb +1 -1
  260. data/lib/datadog/tracing/trace_operation.rb +6 -6
  261. data/lib/datadog/tracing/tracer.rb +6 -6
  262. data/lib/datadog/tracing/transport/http/telemetry.rb +1 -1
  263. data/lib/datadog/tracing/transport/http.rb +2 -2
  264. data/lib/datadog/tracing/transport/io.rb +1 -1
  265. data/lib/datadog/tracing/transport/native.rb +3 -3
  266. data/lib/datadog/tracing/transport/statistics.rb +2 -2
  267. data/lib/datadog/tracing/transport/telemetry.rb +3 -1
  268. data/lib/datadog/tracing/transport/trace_formatter.rb +12 -12
  269. data/lib/datadog/tracing/transport/traces.rb +1 -1
  270. data/lib/datadog/tracing/utils.rb +1 -1
  271. data/lib/datadog/tracing/workers.rb +1 -1
  272. data/lib/datadog/version.rb +1 -1
  273. metadata +4 -3
@@ -12,8 +12,29 @@ module Datadog
12
12
  # @api private
13
13
  class Evaluator
14
14
  # Maximum wall-clock time allowed for evaluating a single `matches`
15
- # operator.
16
- MATCHES_TIMEOUT_SECONDS = 0.5
15
+ # operator. Wall clock, while the evaluation budget is thread CPU
16
+ # time: the regexp engine's `timeout:` keyword and Timeout.timeout
17
+ # offer no CPU-time mode.
18
+ MATCHES_TIMEOUT_SECONDS = 0.05
19
+
20
+ MATCHES_TIMEOUT_MESSAGE = "matches operator timeout"
21
+
22
+ # Number of collection items processed between cooperative
23
+ # evaluation-deadline checks; evaluation aborts within one
24
+ # interval's worth of items past the deadline. A `matches`
25
+ # invocation can spend MATCHES_TIMEOUT_SECONDS of wall time, so
26
+ # #matches and #matches_compiled check the deadline before each
27
+ # match; a predicate that runs `matches` per item therefore
28
+ # adds at most the one match in flight when the deadline
29
+ # passes to the overshoot.
30
+ EVALUATION_DEADLINE_CHECK_INTERVAL = 64
31
+
32
+ # Built-in Array#each and Hash#each, resolved once at load and
33
+ # bound per invocation: the collection operators' iteration then
34
+ # dispatches no customer each override during probe evaluation.
35
+ ARRAY_EACH = Array.instance_method(:each)
36
+ HASH_EACH = Hash.instance_method(:each)
37
+ private_constant :ARRAY_EACH, :HASH_EACH
17
38
 
18
39
  # @param regexps [Array<Regexp>] Regexps precompiled from literal
19
40
  # `matches` patterns, looked up by index by #matches_compiled.
@@ -25,12 +46,110 @@ module Datadog
25
46
 
26
47
  attr_reader :regexps
27
48
 
28
- def ref(var)
29
- @context.fetch(var)
49
+ # Raises DI::Error::EvaluationTimeout when the evaluation deadline
50
+ # has been exceeded, aborting evaluation cooperatively.
51
+ #
52
+ # @param evaluation_deadline [Float] invocation-local evaluation
53
+ # deadline, passed from the compiled #evaluate into the operator
54
+ # calls.
55
+ # @return [void]
56
+ # @raise [DI::Error::EvaluationTimeout] the deadline has been exceeded.
57
+ def raise_if_evaluation_deadline_exceeded(evaluation_deadline)
58
+ if self.class.evaluation_deadline_exceeded?(evaluation_deadline)
59
+ raise DI::Error::EvaluationTimeout
60
+ end
61
+ end
62
+ private :raise_if_evaluation_deadline_exceeded
63
+
64
+ # Raises DI::Error::EvaluationTimeout when +item_index+ falls on
65
+ # a cooperative check boundary and the evaluation deadline has
66
+ # been exceeded. The thread CPU clock is read only at every
67
+ # EVALUATION_DEADLINE_CHECK_INTERVAL-th item, so an already-exceeded
68
+ # deadline raises at the first boundary at or after it passes.
69
+ #
70
+ # @param item_index [Integer] zero-based index of the collection
71
+ # element being processed.
72
+ # @param evaluation_deadline [Float] invocation-local evaluation
73
+ # deadline, passed from the compiled #evaluate into the operator
74
+ # calls.
75
+ # @return [void]
76
+ # @raise [DI::Error::EvaluationTimeout] a check boundary was reached
77
+ # with the deadline exceeded.
78
+ def raise_if_deadline_check_due_and_exceeded(item_index, evaluation_deadline)
79
+ if (item_index % EVALUATION_DEADLINE_CHECK_INTERVAL).zero?
80
+ raise_if_evaluation_deadline_exceeded(evaluation_deadline)
81
+ end
82
+ end
83
+ private :raise_if_deadline_check_due_and_exceeded
84
+
85
+ # Yields the evaluation values for one collection element — the
86
+ # item alone for an Array element, or the [key, value] pair as
87
+ # @it together with the @key and the @value for a Hash element —
88
+ # iterating through the built-in iteration methods bound per
89
+ # invocation and performing the interval-gated evaluation-deadline
90
+ # check and its counter advance between elements.
91
+ #
92
+ # @param collection [Array, Hash] collection whose elements the
93
+ # block receives.
94
+ # @param evaluation_deadline [Float] invocation-local evaluation deadline.
95
+ # @param operator_name [String] name of the invoking collection
96
+ # operator, reported in the bad-collection-type error.
97
+ # @yield [current_item, current_key, current_value] evaluation
98
+ # values for one element.
99
+ # @return [void]
100
+ # @raise [DI::Error::EvaluationTimeout] the evaluation deadline was
101
+ # exceeded mid-iteration.
102
+ # @raise [DI::Error::ExpressionEvaluationError] +collection+ is
103
+ # not an Array or a Hash.
104
+ def each_collection_item(collection, evaluation_deadline, operator_name)
105
+ case collection
106
+ when Array
107
+ i = 0
108
+ ARRAY_EACH.bind(collection).call do |item|
109
+ raise_if_deadline_check_due_and_exceeded(i, evaluation_deadline)
110
+ i += 1
111
+ yield item, nil, nil
112
+ end
113
+ when Hash
114
+ i = 0
115
+ HASH_EACH.bind(collection).call do |key, value|
116
+ raise_if_deadline_check_due_and_exceeded(i, evaluation_deadline)
117
+ i += 1
118
+ yield [key, value], key, value
119
+ end
120
+ else
121
+ raise DI::Error::ExpressionEvaluationError, "Bad collection type for #{operator_name}: #{collection.class}"
122
+ end
123
+ nil
124
+ end
125
+ private :each_collection_item
126
+
127
+ # Returns whether the thread CPU clock has passed +evaluation_deadline+.
128
+ #
129
+ # @param evaluation_deadline [Float] the deadline to check.
130
+ # @return [Boolean] whether the deadline has been exceeded.
131
+ def self.evaluation_deadline_exceeded?(evaluation_deadline)
132
+ Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID, :float_second) >= evaluation_deadline
133
+ end
134
+
135
+ # Resolves the value of the local variable or argument +var+ from
136
+ # the evaluation +context+.
137
+ #
138
+ # @param context [Context] context holding the evaluation locals.
139
+ # @param var [Symbol, String] name of the local variable or argument.
140
+ # @return [Object] value of the local variable or argument.
141
+ def ref(context, var)
142
+ context.fetch(var)
30
143
  end
31
144
 
32
- def iref(var)
33
- @context.fetch_ivar(var)
145
+ # Resolves the value of the instance variable +var+ from the
146
+ # receiver of the evaluation +context+.
147
+ #
148
+ # @param context [Context] context holding the evaluation receiver.
149
+ # @param var [Symbol, String] name of the instance variable.
150
+ # @return [Object] value of the instance variable.
151
+ def iref(context, var)
152
+ context.fetch_ivar(var)
34
153
  end
35
154
 
36
155
  def len(var, var_name)
@@ -92,10 +211,14 @@ module Datadog
92
211
  #
93
212
  # @param haystack [String] string to match against.
94
213
  # @param needle [String] regexp source.
214
+ # @param evaluation_deadline [Float] invocation-local evaluation
215
+ # deadline.
95
216
  # @return [Boolean] whether the haystack matches the regexp.
96
- # @raise [Regexp::TimeoutError] (Ruby 3.2+) regexp engine exceeded MATCHES_TIMEOUT_SECONDS.
97
- # @raise [Timeout::Error] (Ruby < 3.2) Timeout.timeout fired.
98
- def matches(haystack, needle)
217
+ # @raise [DI::Error::EvaluationTimeout] the evaluation deadline was
218
+ # exceeded before the match started, or the match exceeded
219
+ # MATCHES_TIMEOUT_SECONDS.
220
+ def matches(haystack, needle, evaluation_deadline)
221
+ raise_if_evaluation_deadline_exceeded(evaluation_deadline)
99
222
  bounded_match?(Evaluator.compile_regexp(needle), haystack)
100
223
  end
101
224
 
@@ -104,10 +227,14 @@ module Datadog
104
227
  #
105
228
  # @param haystack [String] string to match against.
106
229
  # @param index [Integer] position of the precompiled Regexp in +regexps+.
230
+ # @param evaluation_deadline [Float] invocation-local evaluation
231
+ # deadline.
107
232
  # @return [Boolean] whether the haystack matches the regexp.
108
- # @raise [Regexp::TimeoutError] (Ruby 3.2+) regexp engine exceeded MATCHES_TIMEOUT_SECONDS.
109
- # @raise [Timeout::Error] (Ruby < 3.2) Timeout.timeout fired.
110
- def matches_compiled(haystack, index)
233
+ # @raise [DI::Error::EvaluationTimeout] the evaluation deadline was
234
+ # exceeded before the match started, or the match exceeded
235
+ # MATCHES_TIMEOUT_SECONDS.
236
+ def matches_compiled(haystack, index, evaluation_deadline)
237
+ raise_if_evaluation_deadline_exceeded(evaluation_deadline)
111
238
  bounded_match?(regexps.fetch(index), haystack)
112
239
  end
113
240
 
@@ -117,18 +244,32 @@ module Datadog
117
244
  # @param re [Regexp] regexp to match against.
118
245
  # @param haystack [String] string to match against.
119
246
  # @return [Boolean] whether the haystack matches the regexp.
247
+ # @raise [DI::Error::EvaluationTimeout] the match exceeded
248
+ # MATCHES_TIMEOUT_SECONDS.
120
249
  if Datadog::RubyVersion.is?(">= 3.2")
121
250
  def bounded_match?(re, haystack)
122
251
  # Uses Regexp#match? rather than =~ so that the
123
252
  # thread-local match data ($~, $1, ...) is not mutated as a side
124
253
  # effect of DI expression evaluation.
125
254
  re.match?(haystack)
255
+ rescue Regexp::TimeoutError
256
+ raise DI::Error::EvaluationTimeout.new(message: MATCHES_TIMEOUT_MESSAGE)
126
257
  end
127
258
  else
259
+ # Raised by Timeout.timeout in the matching thread. A dedicated
260
+ # class because Timeout.timeout passes a positional message,
261
+ # which EvaluationTimeout does not accept, and because rescuing
262
+ # Timeout::Error would also catch an enclosing customer timeout.
263
+ class MatchTimeoutSignal < StandardError
264
+ end
265
+ private_constant :MatchTimeoutSignal
266
+
128
267
  def bounded_match?(re, haystack)
129
- Timeout.timeout(MATCHES_TIMEOUT_SECONDS) do
268
+ Timeout.timeout(MATCHES_TIMEOUT_SECONDS, MatchTimeoutSignal) do
130
269
  re.match?(haystack)
131
270
  end
271
+ rescue MatchTimeoutSignal
272
+ raise DI::Error::EvaluationTimeout.new(message: MATCHES_TIMEOUT_MESSAGE)
132
273
  end
133
274
  end
134
275
  private :bounded_match?
@@ -171,50 +312,113 @@ module Datadog
171
312
  String === haystack && haystack.end_with?(needle)
172
313
  end
173
314
 
174
- def all(collection, &block)
175
- case collection
176
- when Array
177
- collection.all? do |item|
178
- block.call(item)
179
- end
180
- when Hash
181
- # For hashes, the expression language has both @it and
182
- # @key/@value. Manufacture @it from the key and value.
183
- collection.all? do |key, value|
184
- block.call([key, value], key, value)
315
+ # Returns true when +block+ returns a truthy value for every element
316
+ # of +collection+.
317
+ #
318
+ # @param collection [Array, Hash] collection to test.
319
+ # @param evaluation_deadline [Float] invocation-local evaluation deadline.
320
+ # @return [Boolean] whether the block is satisfied by every element.
321
+ # @raise [DI::Error::EvaluationTimeout] the evaluation deadline was
322
+ # exceeded mid-iteration.
323
+ # @raise [DI::Error::ExpressionEvaluationError] +collection+ is not
324
+ # an Array or a Hash.
325
+ def all(collection, evaluation_deadline, &block)
326
+ result = true
327
+ each_collection_item(collection, evaluation_deadline, "all") do |current_item, current_key, current_value|
328
+ unless block.call(current_item, current_key, current_value)
329
+ result = false
330
+ break
185
331
  end
186
- else
187
- raise DI::Error::ExpressionEvaluationError, "Bad collection type for all: #{collection.class}"
188
332
  end
333
+ result
189
334
  end
190
335
 
191
- def any(collection, &block)
192
- case collection
193
- when Array
194
- collection.any? do |item|
195
- block.call(item)
336
+ # Returns true when +block+ returns a truthy value for any element
337
+ # of +collection+.
338
+ #
339
+ # @param collection [Array, Hash] collection to test.
340
+ # @param evaluation_deadline [Float] invocation-local evaluation deadline.
341
+ # @return [Boolean] whether the block is satisfied by any element.
342
+ # @raise [DI::Error::EvaluationTimeout] the evaluation deadline was
343
+ # exceeded mid-iteration.
344
+ # @raise [DI::Error::ExpressionEvaluationError] +collection+ is not
345
+ # an Array or a Hash.
346
+ def any(collection, evaluation_deadline, &block)
347
+ result = false
348
+ each_collection_item(collection, evaluation_deadline, "any") do |current_item, current_key, current_value|
349
+ if block.call(current_item, current_key, current_value)
350
+ result = true
351
+ break
196
352
  end
197
- when Hash
198
- collection.any? do |key, value|
199
- # For hashes, the expression language has both @it and
200
- # @key/@value. Manufacture @it from the key and value.
353
+ end
354
+ result
355
+ end
356
+
357
+ # Returns the key-value pairs of the Hash +collection+ for which
358
+ # +block+ returns a truthy value.
359
+ #
360
+ # Ruby 3.1 changed Hash#select to reuse the stored key hashes
361
+ # instead of invoking the keys' hash methods and to keep a
362
+ # compare_by_identity hash's distinct-but-eql? keys and identity
363
+ # flag, so this Ruby filters through the built-in Hash#select
364
+ # bound per invocation. Earlier Rubies invoke the keys' hash
365
+ # methods and collapse identity hashes, so they keep the manual
366
+ # iteration through #each_collection_item, preserving the source
367
+ # hash's identity mode in the result.
368
+ if Datadog::RubyVersion.is?(">= 3.1")
369
+ # Built-in Hash#select, resolved once at load and bound per
370
+ # invocation: #filter's Hash iteration then dispatches no
371
+ # customer select override during probe evaluation.
372
+ HASH_SELECT = Hash.instance_method(:select)
373
+ private_constant :HASH_SELECT
374
+
375
+ def filter_hash(collection, evaluation_deadline, &block)
376
+ i = 0
377
+ HASH_SELECT.bind(collection).call do |key, value|
378
+ raise_if_deadline_check_due_and_exceeded(i, evaluation_deadline)
379
+ i += 1
201
380
  block.call([key, value], key, value)
381
+ end.to_h
382
+ end
383
+ else
384
+ # Core identity-mode check, resolved once at load and bound per
385
+ # invocation so that #filter dispatches no customer
386
+ # compare_by_identity? override during probe evaluation.
387
+ IDENTITY_MODE_CHECK = Hash.instance_method(:compare_by_identity?)
388
+ private_constant :IDENTITY_MODE_CHECK
389
+
390
+ def filter_hash(collection, evaluation_deadline, &block)
391
+ result = {}
392
+ result.compare_by_identity if IDENTITY_MODE_CHECK.bind(collection).call
393
+ each_collection_item(collection, evaluation_deadline, "filter") do |_current_item, current_key, current_value|
394
+ result[current_key] = current_value if block.call([current_key, current_value], current_key, current_value)
202
395
  end
203
- else
204
- raise DI::Error::ExpressionEvaluationError, "Bad collection type for any: #{collection.class}"
396
+ result
205
397
  end
206
398
  end
399
+ private :filter_hash
207
400
 
208
- def filter(collection, &block)
401
+ # Returns the elements of +collection+ for which +block+ returns a
402
+ # truthy value: the selected items of an Array collection, and a
403
+ # Hash of the selected key-value pairs of a Hash collection.
404
+ #
405
+ # @param collection [Array, Hash] collection to filter.
406
+ # @param evaluation_deadline [Float] invocation-local evaluation deadline.
407
+ # @return [Array, Hash] the selected elements.
408
+ # @raise [DI::Error::EvaluationTimeout] the evaluation deadline was
409
+ # exceeded mid-iteration.
410
+ # @raise [DI::Error::ExpressionEvaluationError] +collection+ is not
411
+ # an Array or a Hash.
412
+ def filter(collection, evaluation_deadline, &block)
209
413
  case collection
210
414
  when Array
211
- collection.select do |item|
212
- block.call(item)
415
+ result = []
416
+ each_collection_item(collection, evaluation_deadline, "filter") do |current_item, current_key, current_value|
417
+ result << current_item if block.call(current_item, current_key, current_value)
213
418
  end
419
+ result
214
420
  when Hash
215
- collection.select do |key, value|
216
- block.call([key, value], key, value)
217
- end.to_h
421
+ filter_hash(collection, evaluation_deadline, &block)
218
422
  else
219
423
  raise DI::Error::ExpressionEvaluationError, "Bad collection type for filter: #{collection.class}"
220
424
  end
@@ -27,8 +27,18 @@ module Datadog
27
27
  cls = Class.new(Evaluator)
28
28
  cls.class_exec do
29
29
  eval(<<-RUBY, Object.new.send(:binding), __FILE__, __LINE__ + 1) # standard:disable Security/Eval
30
- def evaluate(context)
31
- @context = context
30
+ # Evaluates the compiled expression against +context+ within
31
+ # the cooperative evaluation +evaluation_deadline+.
32
+ #
33
+ # @param context [Context] evaluation context (locals, instance
34
+ # variables, and per-invocation special variables).
35
+ # @param evaluation_deadline [Float] invocation-local evaluation
36
+ # deadline, as CLOCK_THREAD_CPUTIME_ID float seconds.
37
+ # @return [Object] the value the expression evaluates to.
38
+ # @raise [DI::Error::ExpressionEvaluationError] the expression
39
+ # failed to evaluate, including the EvaluationTimeout
40
+ # subclass raised when the deadline is exceeded.
41
+ def evaluate(context, evaluation_deadline)
32
42
  #{compiled_expr}
33
43
  end
34
44
  RUBY
@@ -40,12 +50,32 @@ module Datadog
40
50
  attr_reader :evaluator
41
51
  attr_reader :redaction_identifier
42
52
 
43
- def evaluate(context)
44
- @evaluator.evaluate(context)
53
+ # Evaluates the expression against +context+.
54
+ #
55
+ # @param context [Context] evaluation context (locals, instance
56
+ # variables, and per-invocation special variables).
57
+ # @param evaluation_deadline [Float] cooperative evaluation deadline, as
58
+ # CLOCK_THREAD_CPUTIME_ID float seconds.
59
+ # @return [Object] the value the expression evaluates to.
60
+ # @raise [DI::Error::ExpressionEvaluationError] the expression failed
61
+ # to evaluate; DI::Error::EvaluationTimeout, raised when the
62
+ # evaluation deadline is exceeded, is a subclass.
63
+ def evaluate(context, evaluation_deadline:)
64
+ evaluator.evaluate(context, evaluation_deadline)
45
65
  end
46
66
 
47
- def satisfied?(context)
48
- !!evaluate(context)
67
+ # Returns whether the expression evaluates to a truthy value
68
+ # against +context+.
69
+ #
70
+ # @param context [Context] evaluation context.
71
+ # @param evaluation_deadline [Float] cooperative evaluation deadline, as
72
+ # CLOCK_THREAD_CPUTIME_ID float seconds.
73
+ # @return [Boolean] whether the expression is satisfied.
74
+ # @raise [DI::Error::ExpressionEvaluationError] the expression failed
75
+ # to evaluate; DI::Error::EvaluationTimeout, raised when the
76
+ # evaluation deadline is exceeded, is a subclass.
77
+ def satisfied?(context, evaluation_deadline:)
78
+ !!evaluate(context, evaluation_deadline: evaluation_deadline)
49
79
  end
50
80
  end
51
81
  end
@@ -92,6 +92,22 @@ module Datadog
92
92
  # expressions.
93
93
  class ExpressionEvaluationError < Error
94
94
  end
95
+
96
+ # Raised when expression evaluation exceeds the configured
97
+ # evaluation CPU-time budget, or a `matches` operator exceeds its
98
+ # per-match wall-clock bound.
99
+ class EvaluationTimeout < ExpressionEvaluationError
100
+ # Default message for EvaluationTimeout exceptions.
101
+ DEFAULT_MESSAGE = "expression evaluation timeout"
102
+
103
+ # Builds the exception, defaulting +message+ to DEFAULT_MESSAGE.
104
+ #
105
+ # @param message [String] exception message.
106
+ # @return [void]
107
+ def initialize(message: DEFAULT_MESSAGE)
108
+ super(message)
109
+ end
110
+ end
95
111
  end
96
112
  end
97
113
  end
@@ -16,8 +16,9 @@ module Datadog
16
16
  # process-wide rate limiter.
17
17
  RATE_LIMIT_GLOBAL = "rateLimitGlobal"
18
18
 
19
- # Skip reason emitted when a capture expression evaluation exceeds
20
- # the capture time budget.
19
+ # Skip reason emitted when an evaluation exceeds its time budget:
20
+ # a probe condition, a capture expression (including one skipped at
21
+ # the expired capture time budget), or a message template.
21
22
  EVALUATION_TIMEOUT = "evaluationTimeout"
22
23
 
23
24
  # Skip reason named in the +di: debug log when a condition-evaluation
@@ -83,7 +83,7 @@ module Datadog
83
83
  # @param settings [Datadog::Core::Configuration::Settings] tracer settings
84
84
  # @param serializer [Serializer] serializer for captured values
85
85
  # @param logger [DI::Logger] logger for instrumenter diagnostics
86
- # @param guardrails_telemetry [GuardrailsTelemetry] emitter for the canonical rate-limit skip metric
86
+ # @param guardrails_telemetry [GuardrailsTelemetry] emitter for the canonical guardrail skip metrics
87
87
  # @param capture_expression_evaluator [CaptureExpressionEvaluator] evaluator for the probe's capture expressions
88
88
  # @param code_tracker [CodeTracker, nil] code tracker for line probe installation
89
89
  # @param telemetry [Datadog::Core::Telemetry::Component, nil] component instrumenter errors are reported through
@@ -554,7 +554,8 @@ module Datadog
554
554
  target_self: target_self,
555
555
  probe: probe, settings: settings, serializer: serializer,
556
556
  )
557
- continue = condition.satisfied?(context)
557
+ continue = condition.satisfied?(context,
558
+ evaluation_deadline: serializer.evaluation_deadline)
558
559
  rescue Exception => exc # standard:disable Lint/RescueException
559
560
  Datadog::DI.reraise_if_fatal(exc)
560
561
  # Evaluation error exception can be raised for "expected"
@@ -563,6 +564,10 @@ module Datadog
563
564
  raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions &&
564
565
  !exc.is_a?(DI::Error::ExpressionEvaluationError)
565
566
 
567
+ # An evaluation timeout is an internal budget abort, so it
568
+ # stays contained even under propagate_all_exceptions.
569
+ record_condition_evaluation_timeout(probe, exc)
570
+
566
571
  if context
567
572
  # We want to report evaluation errors for conditions
568
573
  # as probe snapshots. However, if we failed to create
@@ -605,7 +610,7 @@ module Datadog
605
610
  serialized_entry_args = if probe.capture_snapshot?
606
611
  serializer.serialize_args(args, kwargs, target_self,
607
612
  deadline: serializer.serialization_deadline,
608
- **probe.snapshot_serializer_limits(settings),)
613
+ **probe.snapshot_serializer_limits(settings))
609
614
  end
610
615
 
611
616
  entry_capture_expressions = nil
@@ -698,7 +703,7 @@ module Datadog
698
703
  entry_capture_expressions: entry_capture_expressions,
699
704
  entry_capture_evaluation_errors: entry_capture_evaluation_errors,
700
705
  caller_locations: caller_locs,
701
- return_value: rv, duration: duration, exception: exc,)
706
+ return_value: rv, duration: duration, exception: exc)
702
707
 
703
708
  begin
704
709
  responder.probe_executed_callback(context)
@@ -788,12 +793,16 @@ module Datadog
788
793
  public :kwargs_from_splat
789
794
  end
790
795
 
791
- # Trace point callback for a line probe.
796
+ # Trace point callback for a line probe hit. Evaluates the probe's
797
+ # condition, applies the per-probe rate limiter and the global rate
798
+ # limiter, then invokes the responder with the built context.
792
799
  #
793
- # @param probe [Probe] the probe installed on this line
794
- # @param iseq [RubyVM::InstructionSequence, nil] instruction sequence the trace point is targeted at, or nil when untargeted
795
- # @param responder [#probe_executed_callback, #probe_condition_evaluation_failed_callback] callback target invoked with the built Context
796
- # @param tp [TracePoint] the firing trace point
800
+ # @param probe [Probe] the probe the trace point was installed for.
801
+ # @param iseq [RubyVM::InstructionSequence, nil] instruction sequence of
802
+ # the probe's target file, when the trace point is targeted.
803
+ # @param responder [#probe_executed_callback, #probe_condition_evaluation_failed_callback, #probe_disabled_callback]
804
+ # callback target for the probe hit.
805
+ # @param tp [TracePoint] the trace point event that fired.
797
806
  # @return [void]
798
807
  def line_trace_point_callback(probe, iseq, responder, tp)
799
808
  di_start_time = Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID)
@@ -832,7 +841,8 @@ module Datadog
832
841
  if condition = probe.condition
833
842
  begin
834
843
  context = build_trace_point_context(probe, tp)
835
- return unless condition.satisfied?(context)
844
+ return unless condition.satisfied?(context,
845
+ evaluation_deadline: serializer.evaluation_deadline)
836
846
  rescue Exception => exc # standard:disable Lint/RescueException
837
847
  Datadog::DI.reraise_if_fatal(exc)
838
848
  # Evaluation error exception can be raised for "expected"
@@ -841,6 +851,10 @@ module Datadog
841
851
  raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions &&
842
852
  !exc.is_a?(DI::Error::ExpressionEvaluationError)
843
853
 
854
+ # An evaluation timeout is an internal budget abort, so it
855
+ # stays contained even under propagate_all_exceptions.
856
+ record_condition_evaluation_timeout(probe, exc)
857
+
844
858
  if context
845
859
  # We want to report evaluation errors for conditions
846
860
  # as probe snapshots. However, if we failed to create
@@ -900,6 +914,21 @@ module Datadog
900
914
  nil
901
915
  end
902
916
 
917
+ # Records a condition evaluation timeout for +probe+ through the
918
+ # shared evaluation-timeout reporter. Does nothing when +exc+ is not
919
+ # an evaluation timeout.
920
+ #
921
+ # @param probe [Probe] the probe whose condition evaluation timed out.
922
+ # @param exc [Exception] the exception raised by the evaluation.
923
+ # @return [void]
924
+ def record_condition_evaluation_timeout(probe, exc)
925
+ DI.report_evaluation_timeout(
926
+ telemetry: telemetry, guardrails_telemetry: guardrails_telemetry, logger: logger,
927
+ probe: probe, kind: "condition", exc: exc,
928
+ )
929
+ nil
930
+ end
931
+
903
932
  def build_trace_point_context(probe, tp)
904
933
  stack = caller_locations
905
934
  # We have two helper methods being invoked from the trace point