datadog 2.20.0 → 2.26.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 (310) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +212 -1
  3. data/README.md +0 -1
  4. data/ext/LIBDATADOG_DEVELOPMENT.md +3 -0
  5. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +93 -23
  6. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
  7. data/ext/datadog_profiling_native_extension/collectors_stack.c +21 -5
  8. data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +239 -0
  9. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +1 -1
  10. data/ext/datadog_profiling_native_extension/extconf.rb +9 -4
  11. data/ext/datadog_profiling_native_extension/heap_recorder.c +1 -1
  12. data/ext/datadog_profiling_native_extension/http_transport.c +1 -0
  13. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +12 -0
  14. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +4 -0
  15. data/ext/datadog_profiling_native_extension/profiling.c +2 -0
  16. data/ext/libdatadog_api/datadog_ruby_common.h +1 -1
  17. data/ext/libdatadog_api/ddsketch.c +106 -0
  18. data/ext/libdatadog_api/feature_flags.c +554 -0
  19. data/ext/libdatadog_api/feature_flags.h +5 -0
  20. data/ext/libdatadog_api/init.c +5 -0
  21. data/ext/libdatadog_api/library_config.c +34 -25
  22. data/ext/libdatadog_api/process_discovery.c +24 -18
  23. data/ext/libdatadog_extconf_helpers.rb +1 -1
  24. data/lib/datadog/ai_guard/api_client.rb +82 -0
  25. data/lib/datadog/ai_guard/component.rb +42 -0
  26. data/lib/datadog/ai_guard/configuration/ext.rb +17 -0
  27. data/lib/datadog/ai_guard/configuration/settings.rb +98 -0
  28. data/lib/datadog/ai_guard/configuration.rb +11 -0
  29. data/lib/datadog/ai_guard/evaluation/message.rb +25 -0
  30. data/lib/datadog/ai_guard/evaluation/no_op_result.rb +34 -0
  31. data/lib/datadog/ai_guard/evaluation/request.rb +81 -0
  32. data/lib/datadog/ai_guard/evaluation/result.rb +43 -0
  33. data/lib/datadog/ai_guard/evaluation/tool_call.rb +18 -0
  34. data/lib/datadog/ai_guard/evaluation.rb +72 -0
  35. data/lib/datadog/ai_guard/ext.rb +16 -0
  36. data/lib/datadog/ai_guard.rb +153 -0
  37. data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +26 -0
  38. data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +59 -0
  39. data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +29 -0
  40. data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +26 -0
  41. data/lib/datadog/appsec/api_security/endpoint_collection.rb +10 -0
  42. data/lib/datadog/appsec/api_security/route_extractor.rb +26 -5
  43. data/lib/datadog/appsec/api_security/sampler.rb +7 -4
  44. data/lib/datadog/appsec/assets/blocked.html +8 -0
  45. data/lib/datadog/appsec/assets/blocked.json +1 -1
  46. data/lib/datadog/appsec/assets/blocked.text +3 -1
  47. data/lib/datadog/appsec/assets/waf_rules/README.md +30 -36
  48. data/lib/datadog/appsec/assets/waf_rules/recommended.json +359 -4
  49. data/lib/datadog/appsec/assets/waf_rules/strict.json +43 -2
  50. data/lib/datadog/appsec/assets.rb +1 -1
  51. data/lib/datadog/appsec/autoload.rb +1 -1
  52. data/lib/datadog/appsec/compressed_json.rb +1 -1
  53. data/lib/datadog/appsec/configuration/settings.rb +9 -0
  54. data/lib/datadog/appsec/context.rb +2 -1
  55. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +3 -1
  56. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +3 -2
  57. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +3 -1
  58. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +3 -1
  59. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +9 -4
  60. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +5 -1
  61. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +7 -2
  62. data/lib/datadog/appsec/contrib/rails/patcher.rb +30 -0
  63. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +3 -1
  64. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +10 -4
  65. data/lib/datadog/appsec/event.rb +12 -14
  66. data/lib/datadog/appsec/metrics/collector.rb +19 -3
  67. data/lib/datadog/appsec/metrics/telemetry_exporter.rb +2 -1
  68. data/lib/datadog/appsec/monitor/gateway/watcher.rb +4 -4
  69. data/lib/datadog/appsec/remote.rb +34 -25
  70. data/lib/datadog/appsec/response.rb +18 -4
  71. data/lib/datadog/appsec/security_engine/engine.rb +3 -3
  72. data/lib/datadog/appsec/security_engine/result.rb +29 -9
  73. data/lib/datadog/appsec/security_engine/runner.rb +19 -9
  74. data/lib/datadog/appsec/security_event.rb +5 -7
  75. data/lib/datadog/core/configuration/agent_settings_resolver.rb +4 -4
  76. data/lib/datadog/core/configuration/components.rb +59 -11
  77. data/lib/datadog/core/configuration/config_helper.rb +100 -0
  78. data/lib/datadog/core/configuration/deprecations.rb +36 -0
  79. data/lib/datadog/core/configuration/ext.rb +0 -1
  80. data/lib/datadog/core/configuration/option.rb +38 -43
  81. data/lib/datadog/core/configuration/option_definition.rb +4 -11
  82. data/lib/datadog/core/configuration/options.rb +9 -10
  83. data/lib/datadog/core/configuration/settings.rb +38 -9
  84. data/lib/datadog/core/configuration/stable_config.rb +10 -0
  85. data/lib/datadog/core/configuration/supported_configurations.rb +373 -0
  86. data/lib/datadog/core/configuration.rb +2 -2
  87. data/lib/datadog/core/ddsketch.rb +19 -0
  88. data/lib/datadog/core/deprecations.rb +2 -2
  89. data/lib/datadog/core/environment/cgroup.rb +52 -25
  90. data/lib/datadog/core/environment/container.rb +140 -46
  91. data/lib/datadog/core/environment/ext.rb +7 -2
  92. data/lib/datadog/core/environment/git.rb +2 -2
  93. data/lib/datadog/core/environment/process.rb +87 -0
  94. data/lib/datadog/core/environment/variable_helpers.rb +3 -3
  95. data/lib/datadog/core/environment/yjit.rb +2 -1
  96. data/lib/datadog/core/error.rb +6 -6
  97. data/lib/datadog/core/feature_flags.rb +61 -0
  98. data/lib/datadog/core/metrics/client.rb +2 -2
  99. data/lib/datadog/core/pin.rb +8 -8
  100. data/lib/datadog/core/process_discovery/tracer_memfd.rb +2 -4
  101. data/lib/datadog/core/process_discovery.rb +48 -23
  102. data/lib/datadog/core/rate_limiter.rb +9 -1
  103. data/lib/datadog/core/remote/client/capabilities.rb +7 -0
  104. data/lib/datadog/core/remote/client.rb +14 -6
  105. data/lib/datadog/core/remote/component.rb +10 -10
  106. data/lib/datadog/core/remote/configuration/content.rb +15 -2
  107. data/lib/datadog/core/remote/configuration/digest.rb +14 -7
  108. data/lib/datadog/core/remote/configuration/repository.rb +1 -1
  109. data/lib/datadog/core/remote/configuration/target.rb +13 -6
  110. data/lib/datadog/core/remote/transport/config.rb +4 -25
  111. data/lib/datadog/core/remote/transport/http/config.rb +10 -50
  112. data/lib/datadog/core/remote/transport/http/negotiation.rb +14 -44
  113. data/lib/datadog/core/remote/transport/http.rb +15 -24
  114. data/lib/datadog/core/remote/transport/negotiation.rb +8 -33
  115. data/lib/datadog/core/remote/worker.rb +25 -37
  116. data/lib/datadog/core/runtime/ext.rb +0 -1
  117. data/lib/datadog/core/runtime/metrics.rb +11 -1
  118. data/lib/datadog/core/semaphore.rb +1 -4
  119. data/lib/datadog/core/tag_builder.rb +0 -4
  120. data/lib/datadog/core/tag_normalizer.rb +84 -0
  121. data/lib/datadog/core/telemetry/component.rb +69 -15
  122. data/lib/datadog/core/telemetry/emitter.rb +6 -6
  123. data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +30 -0
  124. data/lib/datadog/core/telemetry/event/app_started.rb +89 -51
  125. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +27 -4
  126. data/lib/datadog/core/telemetry/event.rb +1 -0
  127. data/lib/datadog/core/telemetry/logger.rb +2 -2
  128. data/lib/datadog/core/telemetry/logging.rb +2 -8
  129. data/lib/datadog/core/telemetry/metrics_manager.rb +9 -0
  130. data/lib/datadog/core/telemetry/request.rb +17 -3
  131. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +3 -34
  132. data/lib/datadog/core/telemetry/transport/http.rb +21 -16
  133. data/lib/datadog/core/telemetry/transport/telemetry.rb +3 -11
  134. data/lib/datadog/core/telemetry/worker.rb +88 -32
  135. data/lib/datadog/core/transport/ext.rb +2 -0
  136. data/lib/datadog/core/transport/http/api/endpoint.rb +9 -4
  137. data/lib/datadog/core/transport/http/api/instance.rb +4 -21
  138. data/lib/datadog/core/transport/http/builder.rb +9 -5
  139. data/lib/datadog/core/transport/http/client.rb +80 -0
  140. data/lib/datadog/core/transport/http.rb +22 -19
  141. data/lib/datadog/core/transport/response.rb +15 -1
  142. data/lib/datadog/core/transport/transport.rb +90 -0
  143. data/lib/datadog/core/utils/array.rb +29 -0
  144. data/lib/datadog/{appsec/api_security → core/utils}/lru_cache.rb +10 -21
  145. data/lib/datadog/core/utils/network.rb +22 -1
  146. data/lib/datadog/core/utils/only_once_successful.rb +8 -2
  147. data/lib/datadog/core/utils/safe_dup.rb +2 -2
  148. data/lib/datadog/core/utils/sequence.rb +2 -0
  149. data/lib/datadog/core/utils/time.rb +1 -1
  150. data/lib/datadog/core/utils.rb +2 -0
  151. data/lib/datadog/core/workers/async.rb +10 -1
  152. data/lib/datadog/core/workers/interval_loop.rb +44 -3
  153. data/lib/datadog/core/workers/polling.rb +2 -0
  154. data/lib/datadog/core/workers/queue.rb +100 -1
  155. data/lib/datadog/core.rb +2 -0
  156. data/lib/datadog/data_streams/configuration/settings.rb +49 -0
  157. data/lib/datadog/data_streams/configuration.rb +11 -0
  158. data/lib/datadog/data_streams/ext.rb +11 -0
  159. data/lib/datadog/data_streams/extensions.rb +16 -0
  160. data/lib/datadog/data_streams/pathway_context.rb +169 -0
  161. data/lib/datadog/data_streams/processor.rb +509 -0
  162. data/lib/datadog/data_streams/transport/http/stats.rb +52 -0
  163. data/lib/datadog/data_streams/transport/http.rb +40 -0
  164. data/lib/datadog/data_streams/transport/stats.rb +46 -0
  165. data/lib/datadog/data_streams.rb +100 -0
  166. data/lib/datadog/di/boot.rb +7 -3
  167. data/lib/datadog/di/component.rb +14 -16
  168. data/lib/datadog/di/context.rb +70 -0
  169. data/lib/datadog/di/contrib/active_record.rb +30 -5
  170. data/lib/datadog/di/el/compiler.rb +168 -0
  171. data/lib/datadog/di/el/evaluator.rb +159 -0
  172. data/lib/datadog/di/el/expression.rb +42 -0
  173. data/lib/datadog/di/el.rb +5 -0
  174. data/lib/datadog/di/error.rb +34 -0
  175. data/lib/datadog/di/instrumenter.rb +189 -55
  176. data/lib/datadog/di/logger.rb +2 -2
  177. data/lib/datadog/di/probe.rb +55 -15
  178. data/lib/datadog/di/probe_builder.rb +41 -2
  179. data/lib/datadog/di/probe_file_loader/railtie.rb +1 -1
  180. data/lib/datadog/di/probe_file_loader.rb +1 -1
  181. data/lib/datadog/di/probe_manager.rb +50 -35
  182. data/lib/datadog/di/probe_notification_builder.rb +121 -70
  183. data/lib/datadog/di/probe_notifier_worker.rb +5 -5
  184. data/lib/datadog/di/proc_responder.rb +32 -0
  185. data/lib/datadog/di/remote.rb +89 -84
  186. data/lib/datadog/di/serializer.rb +151 -7
  187. data/lib/datadog/di/transport/diagnostics.rb +8 -36
  188. data/lib/datadog/di/transport/http/diagnostics.rb +1 -33
  189. data/lib/datadog/di/transport/http/input.rb +1 -33
  190. data/lib/datadog/di/transport/http.rb +32 -17
  191. data/lib/datadog/di/transport/input.rb +67 -34
  192. data/lib/datadog/di.rb +61 -5
  193. data/lib/datadog/error_tracking/filters.rb +2 -2
  194. data/lib/datadog/kit/appsec/events/v2.rb +2 -3
  195. data/lib/datadog/open_feature/component.rb +60 -0
  196. data/lib/datadog/open_feature/configuration.rb +27 -0
  197. data/lib/datadog/open_feature/evaluation_engine.rb +70 -0
  198. data/lib/datadog/open_feature/exposures/batch_builder.rb +32 -0
  199. data/lib/datadog/open_feature/exposures/buffer.rb +43 -0
  200. data/lib/datadog/open_feature/exposures/deduplicator.rb +30 -0
  201. data/lib/datadog/open_feature/exposures/event.rb +60 -0
  202. data/lib/datadog/open_feature/exposures/reporter.rb +40 -0
  203. data/lib/datadog/open_feature/exposures/worker.rb +116 -0
  204. data/lib/datadog/open_feature/ext.rb +14 -0
  205. data/lib/datadog/open_feature/native_evaluator.rb +38 -0
  206. data/lib/datadog/open_feature/noop_evaluator.rb +26 -0
  207. data/lib/datadog/open_feature/provider.rb +141 -0
  208. data/lib/datadog/open_feature/remote.rb +67 -0
  209. data/lib/datadog/open_feature/resolution_details.rb +35 -0
  210. data/lib/datadog/open_feature/transport.rb +70 -0
  211. data/lib/datadog/open_feature.rb +19 -0
  212. data/lib/datadog/opentelemetry/api/baggage.rb +1 -1
  213. data/lib/datadog/opentelemetry/configuration/settings.rb +159 -0
  214. data/lib/datadog/opentelemetry/metrics.rb +117 -0
  215. data/lib/datadog/opentelemetry/sdk/configurator.rb +26 -2
  216. data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +35 -0
  217. data/lib/datadog/opentelemetry.rb +3 -0
  218. data/lib/datadog/profiling/collectors/code_provenance.rb +41 -7
  219. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +3 -2
  220. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -1
  221. data/lib/datadog/profiling/collectors/info.rb +6 -5
  222. data/lib/datadog/profiling/component.rb +12 -11
  223. data/lib/datadog/profiling/ext/dir_monkey_patches.rb +18 -0
  224. data/lib/datadog/profiling/ext.rb +2 -1
  225. data/lib/datadog/profiling/http_transport.rb +5 -2
  226. data/lib/datadog/profiling/profiler.rb +4 -0
  227. data/lib/datadog/profiling/tag_builder.rb +36 -3
  228. data/lib/datadog/profiling/tasks/exec.rb +2 -2
  229. data/lib/datadog/profiling.rb +1 -2
  230. data/lib/datadog/single_step_instrument.rb +1 -1
  231. data/lib/datadog/tracing/component.rb +6 -17
  232. data/lib/datadog/tracing/configuration/dynamic.rb +2 -2
  233. data/lib/datadog/tracing/configuration/ext.rb +9 -3
  234. data/lib/datadog/tracing/configuration/settings.rb +89 -10
  235. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +4 -4
  236. data/lib/datadog/tracing/contrib/action_pack/utils.rb +1 -2
  237. data/lib/datadog/tracing/contrib/active_job/log_injection.rb +21 -7
  238. data/lib/datadog/tracing/contrib/active_job/patcher.rb +5 -1
  239. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +4 -2
  240. data/lib/datadog/tracing/contrib/component.rb +2 -2
  241. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -1
  242. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +11 -3
  243. data/lib/datadog/tracing/contrib/extensions.rb +10 -2
  244. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +11 -7
  245. data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +7 -3
  246. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +7 -0
  247. data/lib/datadog/tracing/contrib/graphql/ext.rb +1 -0
  248. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +84 -43
  249. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +11 -3
  250. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +11 -3
  251. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +11 -3
  252. data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +66 -0
  253. data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +66 -0
  254. data/lib/datadog/tracing/contrib/kafka/patcher.rb +14 -0
  255. data/lib/datadog/tracing/contrib/karafka/framework.rb +30 -0
  256. data/lib/datadog/tracing/contrib/karafka/monitor.rb +11 -0
  257. data/lib/datadog/tracing/contrib/karafka/patcher.rb +35 -4
  258. data/lib/datadog/tracing/contrib/rack/middlewares.rb +59 -27
  259. data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -0
  260. data/lib/datadog/tracing/contrib/rack/route_inference.rb +53 -0
  261. data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +7 -1
  262. data/lib/datadog/tracing/contrib/rails/ext.rb +2 -1
  263. data/lib/datadog/tracing/contrib/rails/integration.rb +1 -1
  264. data/lib/datadog/tracing/contrib/rails/middlewares.rb +2 -2
  265. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +4 -1
  266. data/lib/datadog/tracing/contrib/roda/instrumentation.rb +3 -1
  267. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +3 -1
  268. data/lib/datadog/tracing/contrib/span_attribute_schema.rb +1 -1
  269. data/lib/datadog/tracing/contrib/status_range_matcher.rb +9 -1
  270. data/lib/datadog/tracing/contrib/utils/quantization/hash.rb +3 -1
  271. data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +27 -0
  272. data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +48 -0
  273. data/lib/datadog/tracing/contrib/waterdrop/ext.rb +17 -0
  274. data/lib/datadog/tracing/contrib/waterdrop/integration.rb +43 -0
  275. data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +46 -0
  276. data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +49 -0
  277. data/lib/datadog/tracing/contrib/waterdrop/producer.rb +50 -0
  278. data/lib/datadog/tracing/contrib/waterdrop.rb +41 -0
  279. data/lib/datadog/tracing/contrib.rb +1 -0
  280. data/lib/datadog/tracing/diagnostics/environment_logger.rb +1 -1
  281. data/lib/datadog/tracing/distributed/baggage.rb +3 -2
  282. data/lib/datadog/tracing/metadata/ext.rb +9 -1
  283. data/lib/datadog/tracing/remote.rb +1 -9
  284. data/lib/datadog/tracing/sampling/priority_sampler.rb +3 -1
  285. data/lib/datadog/tracing/span.rb +1 -1
  286. data/lib/datadog/tracing/span_event.rb +2 -2
  287. data/lib/datadog/tracing/span_operation.rb +20 -9
  288. data/lib/datadog/tracing/trace_operation.rb +44 -6
  289. data/lib/datadog/tracing/tracer.rb +42 -16
  290. data/lib/datadog/tracing/transport/http/client.rb +12 -26
  291. data/lib/datadog/tracing/transport/http/traces.rb +2 -50
  292. data/lib/datadog/tracing/transport/http.rb +15 -9
  293. data/lib/datadog/tracing/transport/io/client.rb +1 -1
  294. data/lib/datadog/tracing/transport/trace_formatter.rb +11 -0
  295. data/lib/datadog/tracing/transport/traces.rb +9 -71
  296. data/lib/datadog/tracing/workers/trace_writer.rb +5 -0
  297. data/lib/datadog/tracing/writer.rb +1 -0
  298. data/lib/datadog/version.rb +2 -2
  299. data/lib/datadog.rb +3 -0
  300. metadata +110 -24
  301. data/ext/libdatadog_api/macos_development.md +0 -26
  302. data/lib/datadog/core/remote/transport/http/api.rb +0 -53
  303. data/lib/datadog/core/remote/transport/http/client.rb +0 -49
  304. data/lib/datadog/core/telemetry/transport/http/api.rb +0 -43
  305. data/lib/datadog/core/telemetry/transport/http/client.rb +0 -49
  306. data/lib/datadog/core/transport/http/api/spec.rb +0 -36
  307. data/lib/datadog/di/transport/http/api.rb +0 -42
  308. data/lib/datadog/di/transport/http/client.rb +0 -47
  309. data/lib/datadog/opentelemetry/api/baggage.rbs +0 -26
  310. data/lib/datadog/tracing/transport/http/api.rb +0 -44
@@ -10,6 +10,10 @@ module Datadog
10
10
  #
11
11
  # @api private
12
12
  class Error < StandardError
13
+ # Internal Dynamic Instrumentation error ("should never happen").
14
+ class InternalError < Error
15
+ end
16
+
13
17
  # Probe does not contain a line number (i.e., is not a line probe).
14
18
  class MissingLineNumber < Error
15
19
  end
@@ -38,6 +42,11 @@ module Datadog
38
42
  class ProbePreviouslyFailed < Error
39
43
  end
40
44
 
45
+ # Raised when trying to instrument a probe when there is existing
46
+ # instrumentation for the same probe id.
47
+ class AlreadyInstrumented < Error
48
+ end
49
+
41
50
  # Raised when installing a line probe and multiple files match the
42
51
  # specified path suffix.
43
52
  # A probe must be installed into one file only, since UI only
@@ -48,6 +57,31 @@ module Datadog
48
57
  # and the user will need to make their suffix more precise.
49
58
  class MultiplePathsMatch < Error
50
59
  end
60
+
61
+ # Base class for exceptions arising during expression language AST
62
+ # compilation into Ruby code.
63
+ #
64
+ # Expression language does not specify behavior in all cases,
65
+ # leaving some choices to the language implementation in the tracers.
66
+ # It is therefore possible that some technically valid expressions are
67
+ # prohibited by our implementation.
68
+ #
69
+ # It is also possible that the sanitizers/validators prohibit some
70
+ # esoteric constructs that are technically valid in Ruby,
71
+ # for example if instance variable name rules are relaxed to allow
72
+ # arbitrary characters in them as permitted in method names.
73
+ class InvalidExpression < Error
74
+ end
75
+
76
+ # Variable name with invalid characters in an expression language
77
+ # expression.
78
+ class BadVariableName < InvalidExpression
79
+ end
80
+
81
+ # Base class for exceptions arising when evaluating expression language
82
+ # expressions.
83
+ class ExpressionEvaluationError < Error
84
+ end
51
85
  end
52
86
  end
53
87
  end
@@ -3,6 +3,7 @@
3
3
  require_relative '../core/utils/time'
4
4
 
5
5
  # rubocop:disable Lint/AssignmentInCondition
6
+ # rubocop:disable Style/AndOr
6
7
 
7
8
  module Datadog
8
9
  module DI
@@ -88,11 +89,7 @@ module Datadog
88
89
  # from the method but from outside of the method).
89
90
  Location = Struct.new(:path, :lineno, :label)
90
91
 
91
- def hook_method(probe, &block)
92
- unless block
93
- raise ArgumentError, 'block is required'
94
- end
95
-
92
+ def hook_method(probe, responder)
96
93
  lock.synchronize do
97
94
  if probe.instrumentation_module
98
95
  # Already instrumented, warn?
@@ -117,8 +114,53 @@ module Datadog
117
114
  settings = self.settings
118
115
 
119
116
  mod = Module.new do
120
- define_method(method_name) do |*args, **kwargs, &target_block| # steep:ignore
121
- if rate_limiter.nil? || rate_limiter.allow?
117
+ define_method(method_name) do |*args, **kwargs, &target_block| # steep:ignore NoMethod
118
+ # Steep: Unsure why it cannot detect kwargs in this block. Workaround:
119
+ # @type var kwargs: ::Hash[::Symbol, untyped]
120
+ continue = true
121
+ if condition = probe.condition
122
+ begin
123
+ # This context will be recreated later, unlike for line probes.
124
+ context = Context.new(
125
+ locals: serializer.combine_args(args, kwargs, self),
126
+ target_self: self,
127
+ probe: probe, settings: settings, serializer: serializer,
128
+ caller_locations: caller_locations,
129
+ )
130
+ continue = condition.satisfied?(context)
131
+ rescue => exc
132
+ # Evaluation error exception can be raised for "expected"
133
+ # errors, we probably need another setting to control whether
134
+ # these exceptions are propagated.
135
+ raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions &&
136
+ !exc.is_a?(DI::Error::ExpressionEvaluationError)
137
+
138
+ if context
139
+ # We want to report evaluation errors for conditions
140
+ # as probe snapshots. However, if we failed to create
141
+ # the context, we won't be able to report anything as
142
+ # the probe notifier builder requires a context.
143
+ begin
144
+ responder.probe_condition_evaluation_failed_callback(context, exc)
145
+ rescue
146
+ raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
147
+
148
+ # TODO log / report via telemetry?
149
+ end
150
+ else
151
+ _ = 42 # stop standard from wrecking this code
152
+
153
+ raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
154
+
155
+ # TODO log / report via telemetry?
156
+ # If execution gets here, there is probably a bug in the tracer.
157
+ end
158
+
159
+ continue = false
160
+ end
161
+ end
162
+
163
+ if continue and rate_limiter.nil? || rate_limiter.allow?
122
164
  # Arguments may be mutated by the method, therefore
123
165
  # they need to be serialized prior to method invocation.
124
166
  serialized_entry_args = if probe.capture_snapshot?
@@ -126,21 +168,34 @@ module Datadog
126
168
  depth: probe.max_capture_depth || settings.dynamic_instrumentation.max_capture_depth,
127
169
  attribute_count: probe.max_capture_attribute_count || settings.dynamic_instrumentation.max_capture_attribute_count)
128
170
  end
129
- start_time = Core::Utils::Time.get_time
130
- # Under Ruby 2.6 we cannot just call super(*args, **kwargs)
131
- # for methods defined via method_missing.
132
- rv = if args.any?
133
- if kwargs.any?
134
- super(*args, **kwargs, &target_block)
171
+ # We intentionally do not use Core::Utils::Time.get_time
172
+ # here because the time provider may be overridden by the
173
+ # customer, and DI is not allowed to invoke customer code.
174
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
175
+
176
+ rv = nil
177
+ begin
178
+ # Under Ruby 2.6 we cannot just call super(*args, **kwargs)
179
+ # for methods defined via method_missing.
180
+ rv = if args.any?
181
+ if kwargs.any?
182
+ super(*args, **kwargs, &target_block)
183
+ else
184
+ super(*args, &target_block)
185
+ end
186
+ elsif kwargs.any?
187
+ super(**kwargs, &target_block)
135
188
  else
136
- super(*args, &target_block)
189
+ super(&target_block)
137
190
  end
138
- elsif kwargs.any?
139
- super(**kwargs, &target_block)
140
- else
141
- super(&target_block)
191
+ rescue NoMemoryError, Interrupt, SystemExit
192
+ raise
193
+ rescue Exception => exc # standard:disable Lint/RescueException
194
+ # We will raise the exception captured here later, after
195
+ # the instrumentation callback runs.
142
196
  end
143
- duration = Core::Utils::Time.get_time - start_time
197
+
198
+ duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time
144
199
  # The method itself is not part of the stack trace because
145
200
  # we are getting the stack trace from outside of the method.
146
201
  # Add the method in manually as the top frame.
@@ -156,14 +211,22 @@ module Datadog
156
211
  # that location here.
157
212
  []
158
213
  end
159
- caller_locs = method_frame + caller_locations # steep:ignore
214
+ # Steep: https://github.com/ruby/rbs/pull/2745
215
+ caller_locs = method_frame + caller_locations # steep:ignore ArgumentTypeMismatch
160
216
  # TODO capture arguments at exit
161
- # & is to stop steep complaints, block is always present here.
162
- block&.call(probe: probe, rv: rv,
163
- duration: duration, caller_locations: caller_locs,
164
- target_self: self,
165
- serialized_entry_args: serialized_entry_args)
166
- rv
217
+
218
+ context = Context.new(locals: nil, target_self: self,
219
+ probe: probe, settings: settings, serializer: serializer,
220
+ serialized_entry_args: serialized_entry_args,
221
+ caller_locations: caller_locs,
222
+ return_value: rv, duration: duration, exception: exc,)
223
+
224
+ responder.probe_executed_callback(context)
225
+ if exc
226
+ raise exc
227
+ else
228
+ rv
229
+ end
167
230
  else
168
231
  # stop standard from trying to mess up my code
169
232
  _ = 42
@@ -199,6 +262,8 @@ module Datadog
199
262
 
200
263
  probe.instrumentation_module = mod
201
264
  cls.send(:prepend, mod)
265
+
266
+ DI.instrumented_count_inc(:method)
202
267
  end
203
268
  end
204
269
 
@@ -211,6 +276,8 @@ module Datadog
211
276
  if mod = probe.instrumentation_module
212
277
  mod.send(:remove_method, probe.method_name)
213
278
  probe.instrumentation_module = nil
279
+
280
+ DI.instrumented_count_dec(:method)
214
281
  end
215
282
  end
216
283
  end
@@ -220,11 +287,7 @@ module Datadog
220
287
  # not for eval'd code, unless the eval'd code is associated with
221
288
  # a file name and client invokes this method with the correct
222
289
  # file name for the eval'd code.
223
- def hook_line(probe, &block)
224
- unless block
225
- raise ArgumentError, 'No block given to hook_line'
226
- end
227
-
290
+ def hook_line(probe, responder)
228
291
  lock.synchronize do
229
292
  if probe.instrumentation_trace_point
230
293
  # Already instrumented, warn?
@@ -245,7 +308,10 @@ module Datadog
245
308
 
246
309
  iseq = nil
247
310
  if code_tracker
248
- ret = code_tracker.iseqs_for_path_suffix(probe.file) # steep:ignore
311
+ # Steep: Complex type narrowing (before calling hook_line,
312
+ # we check that probe.line? is true which itself checks that probe.file is not nil)
313
+ # Annotation do not work here as `file` is a method on probe, not a local variable.
314
+ ret = code_tracker.iseqs_for_path_suffix(probe.file) # steep:ignore ArgumentTypeMismatch
249
315
  unless ret
250
316
  if permit_untargeted_trace_points
251
317
  # Continue withoout targeting the trace point.
@@ -307,27 +373,86 @@ module Datadog
307
373
  # are invoked for *each* line of Ruby executed.
308
374
  # TODO find out exactly when the path in trace point is relative.
309
375
  # Looks like this is the case when line trace point is not targeted?
310
- if iseq || tp.lineno == probe.line_no && (
376
+ continue = iseq || tp.lineno == probe.line_no && (
311
377
  probe.file == tp.path || probe.file_matches?(tp.path)
312
378
  )
313
- if rate_limiter.nil? || rate_limiter.allow?
314
- serialized_locals = if probe.capture_snapshot?
315
- serializer.serialize_vars(Instrumenter.get_local_variables(tp),
316
- depth: probe.max_capture_depth || settings.dynamic_instrumentation.max_capture_depth,
317
- attribute_count: probe.max_capture_attribute_count || settings.dynamic_instrumentation.max_capture_attribute_count,)
318
- end
319
- if probe.capture_snapshot?
320
- serializer.serialize_value(tp.self,
321
- depth: probe.max_capture_depth || settings.dynamic_instrumentation.max_capture_depth,
322
- attribute_count: probe.max_capture_attribute_count || settings.dynamic_instrumentation.max_capture_attribute_count,)
379
+
380
+ # We set the trace point on :return to be able to instrument
381
+ # 'end' lines. This also causes the trace point to be invoked on
382
+ # non-'end' lines when a line raises an exception, since the
383
+ # exception causes the method to stop executing and stack unwends.
384
+ # We do not want two invocations of the trace point.
385
+ # Therefore, if a trace point is invoked with a :line event,
386
+ # mark it as such and ignore subsequent :return events.
387
+ continue &&= if probe.executed_on_line?
388
+ tp.event == :line
389
+ else
390
+ if tp.event == :line
391
+ probe.executed_on_line!
392
+ end
393
+ true
394
+ end
395
+
396
+ if continue
397
+ if condition = probe.condition
398
+ begin
399
+ context = Context.new(
400
+ locals: Instrumenter.get_local_variables(tp),
401
+ target_self: tp.self,
402
+ probe: probe, settings: settings, serializer: serializer,
403
+ path: tp.path,
404
+ caller_locations: caller_locations,
405
+ )
406
+ continue = condition.satisfied?(context)
407
+ rescue => exc
408
+ # Evaluation error exception can be raised for "expected"
409
+ # errors, we probably need another setting to control whether
410
+ # these exceptions are propagated.
411
+ raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions &&
412
+ !exc.is_a?(DI::Error::ExpressionEvaluationError)
413
+
414
+ continue = false
415
+ if context
416
+ # We want to report evaluation errors for conditions
417
+ # as probe snapshots. However, if we failed to create
418
+ # the context, we won't be able to report anything as
419
+ # the probe notifier builder requires a context.
420
+ begin
421
+ responder.probe_condition_evaluation_failed_callback(context, condition, exc)
422
+ rescue
423
+ raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
424
+
425
+ # TODO log / report via telemetry?
426
+ end
427
+ else
428
+ _ = 42 # stop standard from wrecking this code
429
+
430
+ raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
431
+
432
+ # TODO log / report via telemetry?
433
+ # If execution gets here, there is probably a bug in the tracer.
434
+ end
323
435
  end
324
- # & is to stop steep complaints, block is always present here.
325
- block&.call(probe: probe,
326
- serialized_locals: serialized_locals,
327
- target_self: tp.self,
328
- path: tp.path, caller_locations: caller_locations)
329
436
  end
330
437
  end
438
+
439
+ continue &&= rate_limiter.nil? || rate_limiter.allow? # standard:disable Style/AndOr
440
+
441
+ if continue
442
+ # The context creation is relatively expensive and we don't
443
+ # want to run it if the callback won't be executed due to the
444
+ # rate limit.
445
+ # Thus the copy-paste of the creation call here.
446
+ context ||= Context.new(
447
+ locals: Instrumenter.get_local_variables(tp),
448
+ target_self: tp.self,
449
+ probe: probe, settings: settings, serializer: serializer,
450
+ path: tp.path,
451
+ caller_locations: caller_locations,
452
+ )
453
+
454
+ responder.probe_executed_callback(context)
455
+ end
331
456
  rescue => exc
332
457
  raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
333
458
  logger.debug { "di: unhandled exception in line trace point: #{exc.class}: #{exc}" }
@@ -341,9 +466,11 @@ module Datadog
341
466
  # TODO test this path
342
467
  end
343
468
 
344
- # TODO internal check - remove or use a proper exception
469
+ # Internal sanity check - untargeted trace points create a huge
470
+ # performance impact, and we absolutely do not want to set them
471
+ # accidentally.
345
472
  if !iseq && !permit_untargeted_trace_points
346
- raise "Trying to use an untargeted trace point when user did not permit it"
473
+ raise Error::InternalError, "Trying to use an untargeted trace point when user did not permit it"
347
474
  end
348
475
 
349
476
  lock.synchronize do
@@ -356,12 +483,16 @@ module Datadog
356
483
  # actual_path could be nil if we don't use targeted trace points.
357
484
  probe.instrumented_path = actual_path
358
485
 
359
- if iseq
486
+ # TracePoint#enable returns false when it succeeds.
487
+ rv = if iseq
360
488
  tp.enable(target: iseq, target_line: line_no)
361
489
  else
362
490
  tp.enable
363
491
  end
364
- # TracePoint#enable returns false when it succeeds.
492
+
493
+ DI.instrumented_count_inc(:line)
494
+
495
+ rv
365
496
  end
366
497
  true
367
498
  end
@@ -371,15 +502,17 @@ module Datadog
371
502
  if tp = probe.instrumentation_trace_point
372
503
  tp.disable
373
504
  probe.instrumentation_trace_point = nil
505
+
506
+ DI.instrumented_count_dec(:line)
374
507
  end
375
508
  end
376
509
  end
377
510
 
378
- def hook(probe, &block)
511
+ def hook(probe, responder)
379
512
  if probe.method?
380
- hook_method(probe, &block)
513
+ hook_method(probe, responder)
381
514
  elsif probe.line?
382
- hook_line(probe, &block)
515
+ hook_line(probe, responder)
383
516
  else
384
517
  # TODO add test coverage for this path
385
518
  logger.debug { "di: unknown probe type to hook: #{probe}" }
@@ -449,3 +582,4 @@ module Datadog
449
582
  end
450
583
 
451
584
  # rubocop:enable Lint/AssignmentInCondition
585
+ # rubocop:enable Style/AndOr
@@ -8,7 +8,7 @@ module Datadog
8
8
  #
9
9
  # @api private
10
10
  class Logger
11
- extend Forwardable # steep:ignore
11
+ extend Forwardable
12
12
 
13
13
  def initialize(settings, target)
14
14
  @settings = settings
@@ -18,7 +18,7 @@ module Datadog
18
18
  attr_reader :settings
19
19
  attr_reader :target
20
20
 
21
- def_delegators :target, :debug # steep:ignore
21
+ def_delegators :target, :debug
22
22
 
23
23
  def trace(&block)
24
24
  if settings.dynamic_instrumentation.internal.trace_logging
@@ -17,7 +17,7 @@ module Datadog
17
17
  # and remote config code must be prepared to deal with exceptions
18
18
  # raised by Probe constructor in particular. Therefore, Probe constructor
19
19
  # will raise an exception if it determines that there is not enough
20
- # information (or confilcting information) in the arguments to create a
20
+ # information (or conflicting information) in the arguments to create a
21
21
  # functional probe, and upstream code is tasked with not spamming logs
22
22
  # with notifications of such errors (and potentially limiting the
23
23
  # attempts to construct probe from a given payload).
@@ -36,8 +36,9 @@ module Datadog
36
36
 
37
37
  def initialize(id:, type:,
38
38
  file: nil, line_no: nil, type_name: nil, method_name: nil,
39
- template: nil, capture_snapshot: false, max_capture_depth: nil,
40
- max_capture_attribute_count: nil,
39
+ template: nil, template_segments: nil,
40
+ capture_snapshot: false, max_capture_depth: nil,
41
+ max_capture_attribute_count: nil, condition: nil,
41
42
  rate_limit: nil)
42
43
  # Perform some sanity checks here to detect unexpected attribute
43
44
  # combinations, in order to not do them in subsequent code.
@@ -45,9 +46,17 @@ module Datadog
45
46
  raise ArgumentError, "Unknown probe type: #{type}"
46
47
  end
47
48
 
48
- if line_no && method_name
49
- raise ArgumentError, "Probe contains both line number and method name: #{id}"
50
- end
49
+ # Probe should be inferred to be a line probe if the specification
50
+ # contains a line number. This how Java tracer works and Go tracer
51
+ # is implementing the same behavior, and Go will have all 3 fields
52
+ # (file path, line number and method name) for line probes.
53
+ # Do not raise if line number and method name both exist - instead
54
+ # treat the probe as a line probe.
55
+ #
56
+ # In the future we want to provide type name and method name to line
57
+ # probes, so that the library can verify that the instrumented line
58
+ # is in the method that the frontend showed to the user when the
59
+ # user created the probe.
51
60
 
52
61
  if line_no && !file
53
62
  raise ArgumentError, "Probe contains line number but not file: #{id}"
@@ -57,6 +66,10 @@ module Datadog
57
66
  raise ArgumentError, "Partial method probe definition: #{id}"
58
67
  end
59
68
 
69
+ if line_no.nil? && method_name.nil?
70
+ raise ArgumentError, "Unhandled probe type: neither method nor line probe: #{id}"
71
+ end
72
+
60
73
  @id = id
61
74
  @type = type
62
75
  @file = file
@@ -64,21 +77,25 @@ module Datadog
64
77
  @type_name = type_name
65
78
  @method_name = method_name
66
79
  @template = template
80
+ @template_segments = template_segments
67
81
  @capture_snapshot = !!capture_snapshot
68
82
  @max_capture_depth = max_capture_depth
69
83
  @max_capture_attribute_count = max_capture_attribute_count
70
-
71
- # These checks use instance methods that have more complex logic
72
- # than checking a single argument value. To avoid duplicating
73
- # the logic here, use the methods and perform these checks after
74
- # instance variable assignment.
75
- unless method? || line?
76
- raise ArgumentError, "Unhandled probe type: neither method nor line probe: #{id}"
77
- end
84
+ @condition = condition
78
85
 
79
86
  @rate_limit = rate_limit || (@capture_snapshot ? 1 : 5000)
80
87
  @rate_limiter = Datadog::Core::TokenBucket.new(@rate_limit)
81
88
 
89
+ # At most one report per second.
90
+ # We create the rate limiter here even though it may never be used,
91
+ # to avoid having to synchronize the creation since method probes
92
+ # can be executed on multiple threads concurrently (even if line
93
+ # probes are never executed concurrently since those are done in a
94
+ # trace point).
95
+ if condition
96
+ @condition_evaluation_failed_rate_limiter = Datadog::Core::TokenBucket.new(1)
97
+ end
98
+
82
99
  @emitting_notified = false
83
100
  end
84
101
 
@@ -89,6 +106,10 @@ module Datadog
89
106
  attr_reader :type_name
90
107
  attr_reader :method_name
91
108
  attr_reader :template
109
+ attr_reader :template_segments
110
+
111
+ # The compiled condition for the probe, as a String.
112
+ attr_reader :condition
92
113
 
93
114
  # Configured maximum capture depth. Can be nil in which case
94
115
  # the global default will be used.
@@ -104,6 +125,16 @@ module Datadog
104
125
  # Rate limiter object. For internal DI use only.
105
126
  attr_reader :rate_limiter
106
127
 
128
+ # Rate limiter object for sending snapshots with evaluation errors
129
+ # for when probe condition evaluation fails.
130
+ # This rate limit is separate from the "base" rate limit for the probe
131
+ # because when the condition evaluation succeeds we want the "base"
132
+ # rate limit applied, not tainted by any evaluation errors
133
+ # (for example, the condition can be highly selective, and when it
134
+ # does not hold the evaluation may fail - we don't want to use up the
135
+ # probe rate limit for the errors).
136
+ attr_reader :condition_evaluation_failed_rate_limiter
137
+
107
138
  def capture_snapshot?
108
139
  @capture_snapshot
109
140
  end
@@ -122,7 +153,7 @@ module Datadog
122
153
 
123
154
  # Returns whether the probe is a method probe.
124
155
  def method?
125
- !!(type_name && method_name)
156
+ line_no.nil?
126
157
  end
127
158
 
128
159
  # Returns the line number associated with the probe, raising
@@ -186,6 +217,15 @@ module Datadog
186
217
  def emitting_notified?
187
218
  !!@emitting_notified
188
219
  end
220
+
221
+ def executed_on_line?
222
+ !!@executed_on_line
223
+ end
224
+
225
+ def executed_on_line!
226
+ # TODO lock?
227
+ @executed_on_line = true
228
+ end
189
229
  end
190
230
  end
191
231
  end
@@ -1,6 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # rubocop:disable Lint/AssignmentInCondition
4
+
3
5
  require_relative "probe"
6
+ require_relative 'el'
4
7
 
5
8
  module Datadog
6
9
  module DI
@@ -17,14 +20,24 @@ module Datadog
17
20
  #
18
21
  # @api private
19
22
  module ProbeBuilder
20
- PROBE_TYPES = {
23
+ # Steep: https://github.com/soutaro/steep/issues/363
24
+ PROBE_TYPES = { # steep:ignore IncompatibleAssignment
21
25
  'LOG_PROBE' => :log,
22
26
  }.freeze
23
27
 
24
- module_function def build_from_remote_config(config)
28
+ module_function
29
+
30
+ def build_from_remote_config(config)
25
31
  # The validations here are not yet comprehensive.
26
32
  type = config.fetch('type')
27
33
  type_symbol = PROBE_TYPES[type] or raise ArgumentError, "Unrecognized probe type: #{type}"
34
+ cond = if cond_spec = config['when']
35
+ unless cond_spec['dsl'] && cond_spec['json']
36
+ raise ArgumentError, "Malformed condition specification for probe: #{config}"
37
+ end
38
+ compiled = EL::Compiler.new.compile(cond_spec['json'])
39
+ EL::Expression.new(cond_spec['dsl'], compiled)
40
+ end
28
41
  Probe.new(
29
42
  id: config.fetch("id"),
30
43
  type: type_symbol,
@@ -34,15 +47,41 @@ module Datadog
34
47
  line_no: config["where"]&.[]("lines")&.compact&.map(&:to_i)&.first,
35
48
  type_name: config["where"]&.[]("typeName"),
36
49
  method_name: config["where"]&.[]("methodName"),
50
+ # We should not be using the template for anything - we instead
51
+ # use +segments+ - but keep the template for debugging.
37
52
  template: config["template"],
53
+ template_segments: build_template_segments(config['segments']),
38
54
  capture_snapshot: !!config["captureSnapshot"],
39
55
  max_capture_depth: config["capture"]&.[]("maxReferenceDepth"),
40
56
  max_capture_attribute_count: config["capture"]&.[]("maxFieldCount"),
41
57
  rate_limit: config["sampling"]&.[]("snapshotsPerSecond"),
58
+ condition: cond,
42
59
  )
43
60
  rescue KeyError => exc
44
61
  raise ArgumentError, "Malformed remote configuration entry for probe: #{exc.class}: #{exc}: #{config}"
45
62
  end
63
+
64
+ def build_template_segments(segments)
65
+ segments&.map do |segment|
66
+ if Hash === segment
67
+ if str = segment['str']
68
+ str
69
+ elsif ast = segment['json']
70
+ unless dsl = segment['dsl']
71
+ raise ArgumentError, "Missing dsl for json in segment: #{segment}"
72
+ end
73
+ compiled = EL::Compiler.new.compile(ast)
74
+ EL::Expression.new(dsl, compiled)
75
+ else
76
+ # TODO report to telemetry?
77
+ end
78
+ else
79
+ # TODO report to telemetry?
80
+ end
81
+ end&.compact
82
+ end
46
83
  end
47
84
  end
48
85
  end
86
+
87
+ # rubocop:enable Lint/AssignmentInCondition
@@ -6,7 +6,7 @@ module Datadog
6
6
  # Railtie class initializes dynamic instrumentation contrib code
7
7
  # in Rails environments.
8
8
  class Railtie < Rails::Railtie
9
- initializer 'datadog.dynamic_instrumentation.load_probe_file' do |app| # steep:ignore
9
+ initializer 'datadog.dynamic_instrumentation.load_probe_file' do |app|
10
10
  ProbeFileLoader.load_now
11
11
  end
12
12
  end
@@ -20,7 +20,7 @@ module Datadog
20
20
  module_function def load_now
21
21
  should_propagate = false
22
22
 
23
- probe_file_path = ENV['DD_DYNAMIC_INSTRUMENTATION_PROBE_FILE']
23
+ probe_file_path = DATADOG_ENV['DD_DYNAMIC_INSTRUMENTATION_PROBE_FILE']
24
24
  if probe_file_path.nil? || probe_file_path.empty?
25
25
  return
26
26
  end