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
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'cgroup'
4
+ require_relative 'ext'
4
5
 
5
6
  module Datadog
6
7
  module Core
@@ -15,73 +16,166 @@ module Datadog
15
16
  CONTAINER_REGEX = /(?<container>#{UUID_PATTERN}|#{CONTAINER_PATTERN})(?:.scope)?$/.freeze
16
17
  FARGATE_14_CONTAINER_REGEX = /(?<container>[0-9a-f]{32}-[0-9]{1,10})/.freeze
17
18
 
18
- Descriptor = Struct.new(
19
+ # From https://github.com/torvalds/linux/blob/5859a2b1991101d6b978f3feb5325dad39421f29/include/linux/proc_ns.h#L41-L49
20
+ # Currently, the host namespace inode number is hardcoded.
21
+ # We use it to determine if we're running in the host namespace.
22
+ # This detection approach does not work when running in
23
+ # ["Docker-in-Docker"](https://www.docker.com/resources/docker-in-docker-containerized-ci-workflows-dockercon-2023/).
24
+ HOST_CGROUP_NAMESPACE_INODE = 0xEFFFFFFB
25
+
26
+ Entry = Struct.new(
19
27
  :platform,
28
+ :task_uid,
20
29
  :container_id,
21
- :task_uid
30
+ :inode
22
31
  )
23
32
 
24
33
  module_function
25
34
 
35
+ # Returns HTTP headers representing container information.
36
+ # These can used in any Datadog request that requires origin detection.
37
+ # This is the recommended method to call to get container information.
38
+ def to_headers
39
+ headers = {}
40
+ headers["Datadog-Container-ID"] = container_id if container_id
41
+ headers["Datadog-Entity-ID"] = entity_id if entity_id
42
+ headers["Datadog-External-Env"] = external_env if external_env
43
+ headers
44
+ end
45
+
46
+ # Container ID, prefixed with "ci-" or Inode, prefixed with "in-".
47
+ def entity_id
48
+ if container_id
49
+ "ci-#{container_id}"
50
+ elsif inode
51
+ "in-#{inode}"
52
+ end
53
+ end
54
+
55
+ # External data supplied by the Datadog Cluster Agent Admission Controller.
56
+ # @see {Ext::ENV_EXTERNAL_ENV} for more details.
57
+ def external_env
58
+ Datadog.configuration.container.external_env
59
+ end
60
+
61
+ # The container orchestration platform or runtime environment.
62
+ #
63
+ # Examples: Docker, Kubernetes, AWS Fargate, LXC, etc.
64
+ #
65
+ # @return [String, nil] The platform name (e.g., "docker", "kubepods", "fargate"), or nil if not containerized
26
66
  def platform
27
- descriptor.platform
67
+ entry.platform
28
68
  end
29
69
 
70
+ # The unique identifier of the current container in the container environment.
71
+ #
72
+ # @return [String, nil] The container ID, or nil if not running in a containerized environment
30
73
  def container_id
31
- descriptor.container_id
74
+ entry.container_id
32
75
  end
33
76
 
77
+ # The unique identifier of the task or pod containing this container.
78
+ #
79
+ # In Kubernetes, this is the Pod UID; in AWS ECS/Fargate, the task ID.
80
+ # Used to identify higher-level workloads beyond this container,
81
+ # enabling correlation across container restarts and multi-container applications.
82
+ #
83
+ # @return [String, nil] The task/pod UID, or nil if not available in the current environment
34
84
  def task_uid
35
- descriptor.task_uid
85
+ entry.task_uid
36
86
  end
37
87
 
38
- def descriptor
39
- @descriptor ||= Descriptor.new.tap do |descriptor|
40
- Cgroup.descriptors.each do |cgroup_descriptor|
41
- # Parse container data from cgroup descriptor
42
- path = cgroup_descriptor.path
43
- next if path.nil?
44
-
45
- # Split path into parts
46
- parts = path.split('/')
47
- parts.shift # Remove leading empty part
48
-
49
- # Read info from path
50
- next if parts.empty?
51
-
52
- platform = parts[0][PLATFORM_REGEX, :platform]
53
- container_id, task_uid = nil
54
-
55
- case parts.length
56
- when 0..1
57
- next
58
- when 2
59
- container_id = parts[-1][CONTAINER_REGEX, :container] \
60
- || parts[-1][FARGATE_14_CONTAINER_REGEX, :container]
61
- else
62
- if (container_id = parts[-1][CONTAINER_REGEX, :container])
88
+ # A unique identifier for the execution context (container or host namespace).
89
+ #
90
+ # Used as a fallback identifier when {#container_id} is unavailable.
91
+ #
92
+ # @return [Integer, nil] The namespace inode, or nil if unavailable
93
+ def inode
94
+ entry.inode
95
+ end
96
+
97
+ # Checks if the current process is running on the host cgroup namespace.
98
+ # This indicates that the process is not running inside a container.
99
+ # When unsure, we return `false` (not running on host).
100
+ def running_on_host?
101
+ return @running_on_host if defined?(@running_on_host)
102
+
103
+ @running_on_host = begin
104
+ if File.exist?('/proc/self/ns/cgroup')
105
+ File.stat('/proc/self/ns/cgroup').ino == HOST_CGROUP_NAMESPACE_INODE
106
+ else
107
+ false
108
+ end
109
+ rescue => e
110
+ Datadog.logger.debug(
111
+ "Error while checking cgroup namespace. Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
112
+ )
113
+ false
114
+ end
115
+ end
116
+
117
+ # All cgroup entries have the same container identity.
118
+ # The first valid one is sufficient.
119
+ # v2 entries are preferred over v1.
120
+ def entry
121
+ return @entry if defined?(@entry)
122
+
123
+ # Scan all v2 entries first, only then falling back to v1 entries.
124
+ #
125
+ # To do this, we {Enumerable#partition} the list between v1 and v2,
126
+ # with a `true` predicate for v2 entries, making v2 first
127
+ # partition returned.
128
+ #
129
+ # All v2 entries have the `hierarchy` set to zero.
130
+ # v1 entries have a non-zero `hierarchy`.
131
+ entries = Cgroup.entries.partition { |d| d.hierarchy == '0' }.flatten(1)
132
+ entries.each do |entry_obj|
133
+ path = entry_obj.path
134
+ next unless path
135
+
136
+ # To ease handling, remove the emtpy leading "",
137
+ # as `path` starts with a "/".
138
+ path.delete_prefix!('/')
139
+ parts = path.split('/')
140
+
141
+ # With not path information, we can still use the inode
142
+ if parts.empty? && entry_obj.inode && !running_on_host?
143
+ return @entry = Entry.new(nil, nil, nil, entry_obj.inode)
144
+ end
145
+
146
+ platform = parts[0][PLATFORM_REGEX, :platform]
147
+
148
+ # Extract container_id and task_uid based on path structure
149
+ container_id = task_uid = nil
150
+ if parts.length >= 2
151
+ # Try standard container regex first
152
+ if (container_id = parts[-1][CONTAINER_REGEX, :container])
153
+ # For 3+ parts, also extract task_uid
154
+ if parts.length > 2
63
155
  task_uid = parts[-2][POD_REGEX, :pod] || parts[1][POD_REGEX, :pod]
64
- else
65
- container_id = parts[-1][FARGATE_14_CONTAINER_REGEX, :container]
66
156
  end
157
+ else
158
+ # Fall back to Fargate regex
159
+ container_id = parts[-1][FARGATE_14_CONTAINER_REGEX, :container]
67
160
  end
161
+ end
68
162
 
69
- # If container ID wasn't found, ignore.
70
- # Path might describe a non-container environment.
71
- next if container_id.nil?
72
-
73
- descriptor.platform = platform
74
- descriptor.container_id = container_id
75
- descriptor.task_uid = task_uid
76
-
77
- break
163
+ # container_id is a better container identifier than inode.
164
+ # We MUST only populate one of them, to avoid container identification ambiguity.
165
+ if container_id
166
+ return @entry = Entry.new(platform, task_uid, container_id)
167
+ elsif entry_obj.inode && !running_on_host?
168
+ return @entry = Entry.new(platform, task_uid, nil, entry_obj.inode)
78
169
  end
79
- rescue => e
80
- Datadog.logger.error(
81
- "Error while parsing container info. Cause: #{e.class.name} #{e.message} " \
82
- "Location: #{Array(e.backtrace).first}"
83
- )
84
170
  end
171
+
172
+ @entry = Entry.new # Empty entry if no valid cgroup entry is found
173
+ rescue => e
174
+ Datadog.logger.debug(
175
+ "Error while reading container entry. Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
176
+ )
177
+ @entry = Entry.new unless defined?(@entry)
178
+ @entry
85
179
  end
86
180
  end
87
181
  end
@@ -17,11 +17,10 @@ module Datadog
17
17
 
18
18
  ENV_API_KEY = 'DD_API_KEY'
19
19
  ENV_ENVIRONMENT = 'DD_ENV'
20
+ ENV_EXTERNAL_ENV = 'DD_EXTERNAL_ENV'
20
21
  ENV_SERVICE = 'DD_SERVICE'
21
- ENV_OTEL_SERVICE = 'OTEL_SERVICE_NAME'
22
22
  ENV_SITE = 'DD_SITE'
23
23
  ENV_TAGS = 'DD_TAGS'
24
- ENV_OTEL_RESOURCE_ATTRIBUTES = 'OTEL_RESOURCE_ATTRIBUTES'
25
24
  ENV_VERSION = 'DD_VERSION'
26
25
  FALLBACK_SERVICE_NAME =
27
26
  begin
@@ -35,8 +34,14 @@ module Datadog
35
34
  LANG_INTERPRETER = "#{RUBY_ENGINE}-#{RUBY_PLATFORM}"
36
35
  LANG_PLATFORM = RUBY_PLATFORM
37
36
  LANG_VERSION = RUBY_VERSION
37
+ PROCESS_TYPE = 'script' # Out of the options [jar, script, class, executable], we consider Ruby to always be a script
38
38
  RUBY_ENGINE = ::RUBY_ENGINE # e.g. 'ruby', 'jruby', 'truffleruby'
39
39
  TAG_ENV = 'env'
40
+ TAG_ENTRYPOINT_BASEDIR = "entrypoint.basedir"
41
+ TAG_ENTRYPOINT_NAME = "entrypoint.name"
42
+ TAG_ENTRYPOINT_WORKDIR = "entrypoint.workdir"
43
+ TAG_ENTRYPOINT_TYPE = "entrypoint.type"
44
+ TAG_PROCESS_TAGS = "_dd.tags.process"
40
45
  TAG_SERVICE = 'service'
41
46
  TAG_VERSION = 'version'
42
47
 
@@ -12,13 +12,13 @@ module Datadog
12
12
  def self.git_repository_url
13
13
  return @git_repository_url if defined?(@git_repository_url)
14
14
 
15
- @git_repository_url = Utils::Url.filter_basic_auth(ENV[Datadog::Core::Git::Ext::ENV_REPOSITORY_URL])
15
+ @git_repository_url = Utils::Url.filter_basic_auth(DATADOG_ENV[Datadog::Core::Git::Ext::ENV_REPOSITORY_URL])
16
16
  end
17
17
 
18
18
  def self.git_commit_sha
19
19
  return @git_commit_sha if defined?(@git_commit_sha)
20
20
 
21
- @git_commit_sha = ENV[Datadog::Core::Git::Ext::ENV_COMMIT_SHA]
21
+ @git_commit_sha = DATADOG_ENV[Datadog::Core::Git::Ext::ENV_COMMIT_SHA]
22
22
  end
23
23
  end
24
24
  end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'ext'
4
+ require_relative '../tag_normalizer'
5
+
6
+ module Datadog
7
+ module Core
8
+ module Environment
9
+ # Retrieves process level information such that it can be attached to various payloads
10
+ #
11
+ # @api private
12
+ module Process
13
+ # This method returns a key/value part of serialized tags in the format of k1:v1,k2:v2,k3:v3
14
+ # @return [String] comma-separated normalized key:value pairs
15
+ def self.serialized
16
+ return @serialized if defined?(@serialized)
17
+
18
+ @serialized = tags.join(',').freeze
19
+ end
20
+
21
+ # This method returns an array in the format ["k1:v1","k2:v2","k3:v3"]
22
+ # @return [Array<String>] array of normalized key:value pairs
23
+ def self.tags
24
+ return @tags if defined?(@tags)
25
+ tags = []
26
+
27
+ workdir = TagNormalizer.normalize_process_value(entrypoint_workdir.to_s)
28
+ tags << "#{Environment::Ext::TAG_ENTRYPOINT_WORKDIR}:#{workdir}" unless workdir.empty?
29
+
30
+ entry_name = TagNormalizer.normalize_process_value(entrypoint_name.to_s)
31
+ tags << "#{Environment::Ext::TAG_ENTRYPOINT_NAME}:#{entry_name}" unless entry_name.empty?
32
+
33
+ basedir = TagNormalizer.normalize_process_value(entrypoint_basedir.to_s)
34
+ tags << "#{Environment::Ext::TAG_ENTRYPOINT_BASEDIR}:#{basedir}" unless basedir.empty?
35
+
36
+ tags << "#{Environment::Ext::TAG_ENTRYPOINT_TYPE}:#{TagNormalizer.normalize(entrypoint_type, remove_digit_start_char: false)}"
37
+
38
+ @tags = tags.freeze
39
+ end
40
+
41
+ # Returns the last segment of the working directory of the process
42
+ # Example: /app/myapp -> myapp
43
+ # @return [String] the last segment of the working directory
44
+ def self.entrypoint_workdir
45
+ File.basename(Dir.pwd)
46
+ end
47
+
48
+ # Returns the entrypoint type of the process
49
+ # In Ruby, the entrypoint type is always 'script'
50
+ # @return [String] the type of the process, which is fixed in Ruby
51
+ def self.entrypoint_type
52
+ Environment::Ext::PROCESS_TYPE
53
+ end
54
+
55
+ # Returns the last segment of the base directory of the process
56
+ # Example 1: /bin/mybin -> mybin
57
+ # Example 2: ruby /test/myapp.rb -> myapp
58
+ # @return [String] the last segment of base directory of the script
59
+ #
60
+ # @note Determining true entrypoint name is rather complicated. This method
61
+ # is the initial implementation but it does not produce optimal output in all cases.
62
+ # For example, all Rails applications launched via `rails server` get `rails`
63
+ # as their entrypoint name.
64
+ # We might improve the behavior in the future if there is customer demand for it.
65
+ def self.entrypoint_name
66
+ File.basename($0)
67
+ end
68
+
69
+ # Returns the last segment of the base directory of the process
70
+ # Example 1: /bin/mybin -> bin
71
+ # Example 2: ruby /test/myapp.js -> test
72
+ # @return [String] the last segment of the base directory of the script
73
+ #
74
+ # @note As with entrypoint name, determining true entrypoint directory is complicated.
75
+ # This method has an initial implementation that does not necessarily return good
76
+ # results in all cases. For example, for Rails applications launched via `rails server`
77
+ # the entrypoint basedir is `bin` which is not very helpful.
78
+ # We might improve this in the future if there is customer demand.
79
+ def self.entrypoint_basedir
80
+ File.basename(File.expand_path(File.dirname($0)))
81
+ end
82
+
83
+ private_class_method :entrypoint_workdir, :entrypoint_type, :entrypoint_name, :entrypoint_basedir
84
+ end
85
+ end
86
+ end
87
+ end
@@ -20,8 +20,8 @@ module Datadog
20
20
  # @return [default] if the environment value is not found
21
21
  def env_to_bool(var, default = nil, deprecation_warning: true)
22
22
  var = decode_array(var, deprecation_warning)
23
- if var && ENV.key?(var)
24
- value = ENV[var].to_s.strip
23
+ if var && DATADOG_ENV.key?(var)
24
+ value = DATADOG_ENV[var].to_s.strip
25
25
  value.downcase!
26
26
  value == 'true' || value == '1'
27
27
  else
@@ -34,7 +34,7 @@ module Datadog
34
34
  def decode_array(var, deprecation_warning)
35
35
  if var.is_a?(Array)
36
36
  var.find.with_index do |env_var, i|
37
- found = ENV.key?(env_var)
37
+ found = DATADOG_ENV.key?(env_var)
38
38
 
39
39
  # Check if we are using a non-preferred environment variable
40
40
  if deprecation_warning && found && i != 0
@@ -54,7 +54,8 @@ module Datadog
54
54
 
55
55
  # Ratio of YJIT-executed instructions
56
56
  def ratio_in_yjit
57
- ::RubyVM::YJIT.runtime_stats[:ratio_in_yjit]
57
+ stats = ::RubyVM::YJIT.runtime_stats
58
+ stats[:ratio_in_yjit] if stats.key?(:ratio_in_yjit)
58
59
  end
59
60
 
60
61
  def available?
@@ -13,12 +13,12 @@ module Datadog
13
13
  case value
14
14
  # A Ruby {Exception} is the most common parameter type.
15
15
  when Exception then new(value.class, value.message, full_backtrace(value))
16
- # steep:ignore:start
17
- # Steep doesn't like an array with up to 3 elements to be passed here: it thinks the array is unbounded.
18
- when Array then new(*value)
19
- # Steep can not follow the logic inside the lambda, thus it doesn't know `value` responds to `:message`.
20
- when ->(v) { v.respond_to?(:message) } then new(value.class, value.message)
21
- # steep:ignore:end
16
+ # Steep: Steep doesn't like an array with up to 3 elements to be passed here: it thinks the array is unbounded.
17
+ when Array then new(*value) # steep:ignore UnexpectedPositionalArgument
18
+ when ->(v) { v.respond_to?(:message) }
19
+ # Steep: Steep can not follow the logic inside the lambda, thus it doesn't know `value` responds to `:message`.
20
+ # @type var value: _ContainsMessage
21
+ new(value.class, value.message)
22
22
  when String then new(nil, value)
23
23
  when Error then value
24
24
  else Error.new # Blank error
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Datadog
6
+ module Core
7
+ # Feature flags evaluation using libdatadog
8
+ # The classes in this module are defined as C extensions in ext/libdatadog_api/feature_flags.c
9
+ #
10
+ # @api private
11
+ module FeatureFlags
12
+ # A top-level error raised by the extension
13
+ class Error < StandardError # rubocop:disable Lint/EmptyClass
14
+ end
15
+
16
+ # Configuration for feature flags evaluation
17
+ # This class is defined in the C extension
18
+ class Configuration # rubocop:disable Lint/EmptyClass
19
+ end
20
+
21
+ # Resolution details for a feature flag evaluation
22
+ # Base class is defined in the C extension, with Ruby methods added here
23
+ class ResolutionDetails
24
+ attr_writer :value
25
+
26
+ # Get the resolved value, with JSON parsing for object types
27
+ #
28
+ # @return [Object] The resolved value (parsed from JSON if object type)
29
+ # @raise [Datadog::Core::FeatureFlags::Error] If JSON parsing fails
30
+ def value
31
+ return @value if defined?(@value)
32
+
33
+ # NOTE: Raw value method call doesn't support memoization right now
34
+ value = raw_value
35
+
36
+ # NOTE: Lazy parsing of the JSON is a temporary solution and will be
37
+ # moved into C extension
38
+ @value = json?(value) ? JSON.parse(value) : value
39
+ rescue JSON::ParserError => e
40
+ raise Error, "Failed to parse JSON value: #{e.class}: #{e}"
41
+ end
42
+
43
+ # Check if the resolution resulted in an error
44
+ #
45
+ # @return [Boolean] True if there was an error
46
+ def error?
47
+ reason == 'ERROR'
48
+ end
49
+
50
+ private
51
+
52
+ # NOTE: A JSON raw string will be returned by the `libdatadog` as
53
+ # a Ruby String class with a flag type `:object`, otherwise it's
54
+ # just a string.
55
+ def json?(value)
56
+ flag_type == :object && value.is_a?(String)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -54,11 +54,11 @@ module Datadog
54
54
  end
55
55
 
56
56
  def default_hostname
57
- ENV.fetch(Configuration::Ext::Agent::ENV_DEFAULT_HOST, Ext::DEFAULT_HOST)
57
+ DATADOG_ENV.fetch(Configuration::Ext::Agent::ENV_DEFAULT_HOST, Ext::DEFAULT_HOST)
58
58
  end
59
59
 
60
60
  def default_port
61
- ENV.fetch(Configuration::Ext::Metrics::ENV_DEFAULT_PORT, Ext::DEFAULT_PORT).to_i
61
+ DATADOG_ENV.fetch(Configuration::Ext::Metrics::ENV_DEFAULT_PORT, Ext::DEFAULT_PORT).to_i
62
62
  end
63
63
 
64
64
  def default_statsd_client
@@ -43,18 +43,18 @@ module Datadog
43
43
  # rubocop:disable Style/TrivialAccessors
44
44
  def onto(obj)
45
45
  unless obj.respond_to? :datadog_pin=
46
- obj.instance_exec do
47
- def datadog_pin=(pin)
48
- @datadog_pin = pin
49
- end
46
+ obj.define_singleton_method(:datadog_pin=) do |pin|
47
+ # Steep: https://github.com/soutaro/steep/issues/380
48
+ # @type self: PinnedObject
49
+ @datadog_pin = pin
50
50
  end
51
51
  end
52
52
 
53
53
  unless obj.respond_to? :datadog_pin
54
- obj.instance_exec do
55
- def datadog_pin
56
- @datadog_pin
57
- end
54
+ obj.define_singleton_method(:datadog_pin) do
55
+ # Steep: https://github.com/soutaro/steep/issues/380
56
+ # @type self: PinnedObject
57
+ @datadog_pin
58
58
  end
59
59
  end
60
60
 
@@ -2,11 +2,9 @@
2
2
 
3
3
  module Datadog
4
4
  module Core
5
- class ProcessDiscovery
5
+ module ProcessDiscovery
6
6
  class TracerMemfd
7
- attr_accessor :logger
8
-
9
- def shutdown!
7
+ def shutdown!(logger)
10
8
  ProcessDiscovery._native_close_tracer_memfd(self, logger)
11
9
  end
12
10
  end
@@ -2,34 +2,59 @@
2
2
 
3
3
  require 'datadog/core/process_discovery/tracer_memfd'
4
4
 
5
+ require_relative 'utils/at_fork_monkey_patch'
6
+ require_relative 'utils/only_once'
7
+
5
8
  module Datadog
6
9
  module Core
7
10
  # Class used to store tracer metadata in a native file descriptor.
8
- class ProcessDiscovery
9
- def self.get_and_store_metadata(settings, logger)
10
- if (libdatadog_api_failure = Datadog::Core::LIBDATADOG_API_FAILURE)
11
- logger.debug("Cannot enable process discovery: #{libdatadog_api_failure}")
12
- return
11
+ module ProcessDiscovery
12
+ ONLY_ONCE = Core::Utils::OnlyOnce.new
13
+
14
+ class << self
15
+ def publish(settings)
16
+ if (libdatadog_api_failure = Datadog::Core::LIBDATADOG_API_FAILURE)
17
+ Datadog.logger.debug { "Cannot enable process discovery: #{libdatadog_api_failure}" }
18
+ return
19
+ end
20
+
21
+ ONLY_ONCE.run { apply_at_fork_patch }
22
+
23
+ metadata = get_metadata(settings)
24
+
25
+ shutdown!
26
+ @file_descriptor = _native_store_tracer_metadata(Datadog.logger, **metadata)
13
27
  end
14
- metadata = get_metadata(settings)
15
- memfd = _native_store_tracer_metadata(logger, **metadata)
16
- memfd.logger = logger if memfd
17
- memfd
18
- end
19
28
 
20
- # According to the RFC, runtime_id, service_name, service_env, service_version are optional.
21
- # In the C method exposed by ddcommon, memfd_create replaces empty strings by None for these fields.
22
- private_class_method def self.get_metadata(settings)
23
- {
24
- schema_version: 1,
25
- runtime_id: Core::Environment::Identity.id,
26
- tracer_language: Core::Environment::Identity.lang,
27
- tracer_version: Core::Environment::Identity.gem_datadog_version_semver2,
28
- hostname: Core::Environment::Socket.hostname,
29
- service_name: settings.service || '',
30
- service_env: settings.env || '',
31
- service_version: settings.version || ''
32
- }
29
+ def shutdown!
30
+ @file_descriptor&.shutdown!(Datadog.logger)
31
+ @file_descriptor = nil
32
+ end
33
+
34
+ private
35
+
36
+ # According to the RFC, runtime_id, service_name, service_env, service_version are optional.
37
+ # In the C method exposed by ddcommon, memfd_create replaces empty strings by None for these fields.
38
+ def get_metadata(settings)
39
+ {
40
+ runtime_id: Core::Environment::Identity.id,
41
+ tracer_language: Core::Environment::Identity.lang,
42
+ tracer_version: Core::Environment::Identity.gem_datadog_version_semver2,
43
+ hostname: Core::Environment::Socket.hostname,
44
+ service_name: settings.service || '',
45
+ service_env: settings.env || '',
46
+ service_version: settings.version || '',
47
+ # TODO: Implement process tags and container id
48
+ process_tags: '',
49
+ container_id: ''
50
+ }
51
+ end
52
+
53
+ def apply_at_fork_patch
54
+ # The runtime-id changes after a fork. We apply this patch to at_fork to ensure that the runtime-id is updated.
55
+ Utils::AtForkMonkeyPatch.apply!
56
+ Utils::AtForkMonkeyPatch.at_fork(:child) { publish(Datadog.configuration) }
57
+ end
33
58
  end
34
59
  end
35
60
  end
@@ -81,6 +81,10 @@ module Datadog
81
81
 
82
82
  return current_window_rate if @prev_conforming_messages.nil? || @prev_total_messages.nil?
83
83
 
84
+ # Steep: Due to https://github.com/soutaro/steep/issues/477,
85
+ # the previous nil check does not narrow type to Integer
86
+ # The annotation fixes the typing error, but it takes effect in the method
87
+ # @type ivar @prev_total_messages: Integer
84
88
  (@conforming_messages.to_f + @prev_conforming_messages.to_f) / (@total_messages + @prev_total_messages)
85
89
  end
86
90
 
@@ -154,7 +158,11 @@ module Datadog
154
158
  if @current_window.nil?
155
159
  @current_window = now
156
160
  # If more than 1 second has past since last window, reset
157
- elsif now - @current_window >= 1
161
+ #
162
+ # Steep: @current_window is a Float, but for some reason annotations does not work here
163
+ # Once a fix will be out for nil checks on instance variables, we can remove the ignore comment
164
+ # https://github.com/soutaro/steep/issues/477
165
+ elsif now - @current_window >= 1 # steep:ignore UnresolvedOverloading
158
166
  @prev_conforming_messages = @conforming_messages
159
167
  @prev_total_messages = @total_messages
160
168
  @conforming_messages = 0
@@ -3,6 +3,7 @@
3
3
  require_relative '../../utils/base64'
4
4
  require_relative '../../../appsec/remote'
5
5
  require_relative '../../../tracing/remote'
6
+ require_relative '../../../open_feature/remote'
6
7
 
7
8
  module Datadog
8
9
  module Core
@@ -38,6 +39,12 @@ module Datadog
38
39
  register_receivers(Datadog::DI::Remote.receivers(@telemetry))
39
40
  end
40
41
 
42
+ if settings.respond_to?(:open_feature) && settings.open_feature.enabled
43
+ register_capabilities(Datadog::OpenFeature::Remote.capabilities)
44
+ register_products(Datadog::OpenFeature::Remote.products)
45
+ register_receivers(Datadog::OpenFeature::Remote.receivers(@telemetry))
46
+ end
47
+
41
48
  register_capabilities(Datadog::Tracing::Remote.capabilities)
42
49
  register_products(Datadog::Tracing::Remote.products)
43
50
  register_receivers(Datadog::Tracing::Remote.receivers(@telemetry))