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
@@ -23,51 +23,47 @@ module Datadog
23
23
  attr_reader :logger
24
24
 
25
25
  def start
26
- logger.debug { 'remote worker starting' }
26
+ logger.debug { "remote worker starting (pid: #{Process.pid})" }
27
27
 
28
- acquire_lock
28
+ @mutex.synchronize do
29
+ if @stopped
30
+ logger.debug('remote worker: refusing to restart after previous stop')
31
+ return
32
+ end
29
33
 
30
- if @stopped
31
- logger.debug('remote worker: refusing to restart after previous stop')
32
- return
33
- end
34
-
35
- return if @starting || @started
34
+ return if @starting || @started
36
35
 
37
- @starting = true
36
+ @starting = true
38
37
 
39
- thread = Thread.new { poll(@interval) }
40
- thread.name = self.class.name
41
- thread.thread_variable_set(:fork_safe, true)
42
- @thr = thread
38
+ thread = Thread.new { poll(@interval) }
39
+ thread.name = self.class.name
40
+ thread.thread_variable_set(:fork_safe, true)
41
+ @thr = thread
43
42
 
44
- @started = true
45
- @starting = false
43
+ @started = true
44
+ @starting = false
45
+ end
46
46
 
47
47
  logger.debug { 'remote worker started' }
48
- ensure
49
- release_lock
50
48
  end
51
49
 
52
50
  def stop
53
- logger.debug { 'remote worker stopping' }
51
+ logger.debug { "remote worker stopping (pid: #{Process.pid})" }
54
52
 
55
- acquire_lock
53
+ @mutex.synchronize do
54
+ thread = @thr
56
55
 
57
- thread = @thr
56
+ if thread
57
+ thread.kill
58
+ thread.join
59
+ end
58
60
 
59
- if thread
60
- thread.kill
61
- thread.join
61
+ @started = false
62
+ @thr = nil
63
+ @stopped = true
62
64
  end
63
65
 
64
- @started = false
65
- @thr = nil
66
- @stopped = true
67
-
68
66
  logger.debug { 'remote worker stopped' }
69
- ensure
70
- release_lock
71
67
  end
72
68
 
73
69
  def started?
@@ -76,14 +72,6 @@ module Datadog
76
72
 
77
73
  private
78
74
 
79
- def acquire_lock
80
- @mutex.lock
81
- end
82
-
83
- def release_lock
84
- @mutex.unlock
85
- end
86
-
87
75
  def poll(interval)
88
76
  loop do
89
77
  break unless @mutex.synchronize { @starting || @started }
@@ -13,7 +13,6 @@ module Datadog
13
13
  # @public_api
14
14
  module Metrics
15
15
  ENV_ENABLED = 'DD_RUNTIME_METRICS_ENABLED'
16
- ENV_OTEL_METRICS_EXPORTER = 'OTEL_METRICS_EXPORTER'
17
16
 
18
17
  METRIC_CLASS_COUNT = 'runtime.ruby.class_count'
19
18
  METRIC_GC_PREFIX = 'runtime.ruby.gc'
@@ -8,6 +8,7 @@ require_relative '../environment/gc'
8
8
  require_relative '../environment/thread_count'
9
9
  require_relative '../environment/vm_cache'
10
10
  require_relative '../environment/yjit'
11
+ require_relative '../environment/process'
11
12
 
12
13
  module Datadog
13
14
  module Core
@@ -24,6 +25,9 @@ module Datadog
24
25
 
25
26
  # Initialize the collection of runtime-id
26
27
  @runtime_id_enabled = options.fetch(:experimental_runtime_id_enabled, false)
28
+
29
+ # Initialized process tags support
30
+ @process_tags_enabled = options.fetch(:experimental_propagate_process_tags_enabled, false)
27
31
  end
28
32
 
29
33
  # Associate service with runtime metrics
@@ -111,6 +115,11 @@ module Datadog
111
115
 
112
116
  # Add runtime-id dynamically because it might change during runtime.
113
117
  options[:tags].concat(["runtime-id:#{Core::Environment::Identity.id}"]) if @runtime_id_enabled
118
+
119
+ # Add process tags when enabled
120
+ if @process_tags_enabled
121
+ options[:tags].concat(Core::Environment::Process.tags)
122
+ end
114
123
  end
115
124
  end
116
125
 
@@ -119,7 +128,8 @@ module Datadog
119
128
  attr_reader \
120
129
  :service_tags,
121
130
  :services,
122
- :runtime_id_enabled
131
+ :runtime_id_enabled,
132
+ :process_tags_enabled
123
133
 
124
134
  def compile_service_tags!
125
135
  @service_tags = services.to_a.collect do |service|
@@ -20,10 +20,7 @@ module Datadog
20
20
 
21
21
  def wait(timeout = nil)
22
22
  wake_lock.synchronize do
23
- # steep specifies that the second argument to wait is of type
24
- # ::Time::_Timeout which for some reason is not Numeric and is not
25
- # castable from Numeric.
26
- wake.wait(wake_lock, timeout) # steep:ignore
23
+ wake.wait(wake_lock, timeout)
27
24
  end
28
25
  end
29
26
 
@@ -8,10 +8,6 @@ module Datadog
8
8
  module Core
9
9
  # This module builds a hash of tags.
10
10
  #
11
- # When changing or adding the tags, make sure they are kept in sync with
12
- # https://docs.google.com/spreadsheets/d/1LOGMf4c4Avbtn36uZ2SWvhIGKRPLM1BoWkUP4JYj7hA/
13
- # (Datadog internal link).
14
- #
15
11
  # @api private
16
12
  module TagBuilder
17
13
  def self.fixed_environment_tags
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'utils'
4
+
5
+ module Datadog
6
+ module Core
7
+ # @api private
8
+ module TagNormalizer
9
+ # Normalization logic used for tag keys and values that the Trace Agent has for traces
10
+ # Useful for ensuring that tag keys and values are normalized consistently
11
+ # An use case for now is Process Tags which need to be sent across various intakes (profiling, tracing, etc.) consistently
12
+
13
+ module_function
14
+
15
+ INVALID_TAG_CHARACTERS = %r{[^\p{L}0-9_\-:./]}
16
+ LEADING_INVALID_CHARS_NO_DIGITS = %r{\A[^\p{L}:]++}
17
+ LEADING_INVALID_CHARS_WITH_DIGITS = %r{\A[^\p{L}0-9:./]++}
18
+ MAX_BYTE_SIZE = 200 # Represents the general max tag length
19
+ MAX_PROCESS_VALUE_BYTE_SIZE = 100 # Represents the max tag length for process tags
20
+ VALID_ASCII_TAG = %r{\A[a-z:][a-z0-9:./-]*\z}
21
+
22
+ # Based on https://github.com/DataDog/datadog-agent/blob/45799c842bbd216bcda208737f9f11cade6fdd95/pkg/trace/traceutil/normalize.go#L131
23
+ # Specifically for general normalization:
24
+ # - Must be valid UTF-8
25
+ # - Invalid characters are replaced with an underscore
26
+ # - Leading non-letter characters are removed but colons are kept
27
+ # - Trailing non-letter characters are removed
28
+ # - Trailing underscores are removed
29
+ # - Consecutive underscores are merged into a single underscore
30
+ # - Maximum length is 200 characters
31
+ # If it's a tag value, allow it to start with a digit
32
+ # @param original_value [String] The original string
33
+ # @param remove_digit_start_char [Boolean] - whether to remove the leading digit (currently only used for tag values)
34
+ # @return [String] The normalized string
35
+ def self.normalize(original_value, remove_digit_start_char: false)
36
+ # DEV-3.0: Ideally this encode call should be replaced with Datadog::Core::Utils.utf8_encode once it
37
+ # is safe to modify the default behavior.
38
+ value = original_value.to_s.encode('UTF-8', invalid: :replace, undef: :replace)
39
+ value.strip!
40
+ return "" if value.empty?
41
+
42
+ return value if value.bytesize <= MAX_BYTE_SIZE &&
43
+ value.match?(VALID_ASCII_TAG)
44
+
45
+ if value.bytesize > MAX_BYTE_SIZE
46
+ value = value.byteslice(0, MAX_BYTE_SIZE)
47
+ value.scrub!("")
48
+ end
49
+
50
+ value.downcase!
51
+ value.gsub!(INVALID_TAG_CHARACTERS, '_')
52
+
53
+ # The Trace Agent allows tag values to start with a number so this logic is here too
54
+ leading_invalid_regex = remove_digit_start_char ? LEADING_INVALID_CHARS_NO_DIGITS : LEADING_INVALID_CHARS_WITH_DIGITS
55
+ value.sub!(leading_invalid_regex, "")
56
+
57
+ value.squeeze!('_') if value.include?('__')
58
+ value.delete_suffix!('_')
59
+
60
+ value
61
+ end
62
+
63
+ # Process tags values follow an additional piece of normalization:
64
+ # - must not be more than 100 bytes
65
+ # - and must not contain colons
66
+ # @param value [String] The original string
67
+ # @return [String] The normalized string
68
+ def self.normalize_process_value(value)
69
+ value = normalize(value)
70
+ return value if value.empty?
71
+
72
+ value.tr!(':', '_')
73
+ value.squeeze!('_') if value.include?('__')
74
+
75
+ if value.bytesize > MAX_PROCESS_VALUE_BYTE_SIZE
76
+ value = value.byteslice(0, MAX_PROCESS_VALUE_BYTE_SIZE) || value
77
+ value.scrub!("")
78
+ end
79
+
80
+ value
81
+ end
82
+ end
83
+ end
84
+ end
@@ -14,12 +14,26 @@ require_relative '../utils/forking'
14
14
  module Datadog
15
15
  module Core
16
16
  module Telemetry
17
- # Telemetry entrypoint, coordinates sending telemetry events at various points in app lifecycle.
18
- # Note: Telemetry does not spawn its worker thread in fork processes, thus no telemetry is sent in forked processes.
17
+ # Telemetry entry point, coordinates sending telemetry events at
18
+ # various points in application lifecycle.
19
19
  #
20
20
  # @api private
21
21
  class Component
22
- attr_reader :enabled, :logger, :transport, :worker
22
+ ENDPOINT_COLLECTION_MESSAGE_LIMIT = 300
23
+
24
+ ONLY_ONCE = Utils::OnlyOnce.new
25
+
26
+ attr_reader :enabled
27
+ attr_reader :logger
28
+ attr_reader :transport
29
+ attr_reader :worker
30
+ attr_reader :settings
31
+ attr_reader :agent_settings
32
+ attr_reader :metrics_manager
33
+
34
+ # Alias for consistency with other components.
35
+ # TODO Remove +enabled+ method
36
+ alias_method :enabled?, :enabled
23
37
 
24
38
  include Core::Utils::Forking
25
39
  include Telemetry::Logging
@@ -48,6 +62,17 @@ module Datadog
48
62
  logger:,
49
63
  enabled:
50
64
  )
65
+ ONLY_ONCE.run do
66
+ Utils::AtForkMonkeyPatch.apply!
67
+
68
+ # All of the other at fork monkey patch callbacks reference
69
+ # globals, follow that pattern here to avoid having the component
70
+ # referenced via the at fork callbacks.
71
+ Datadog::Core::Utils::AtForkMonkeyPatch.at_fork(:child) do
72
+ Datadog.send(:components, allow_initialization: false)&.telemetry&.after_fork
73
+ end
74
+ end
75
+
51
76
  @enabled = enabled
52
77
  @log_collection_enabled = settings.telemetry.log_collection_enabled
53
78
  @logger = logger
@@ -107,13 +132,17 @@ module Datadog
107
132
  @worker&.enabled = false
108
133
  end
109
134
 
110
- def start(initial_event_is_change = false)
111
- return if !@enabled
135
+ def start(initial_event_is_change = false, components:)
136
+ return unless enabled?
112
137
 
113
138
  initial_event = if initial_event_is_change
114
- Event::SynthAppClientConfigurationChange.new(agent_settings: @agent_settings)
139
+ Event::SynthAppClientConfigurationChange.new(
140
+ components: components,
141
+ )
115
142
  else
116
- Event::AppStarted.new(agent_settings: @agent_settings)
143
+ Event::AppStarted.new(
144
+ components: components,
145
+ )
117
146
  end
118
147
 
119
148
  @worker.start(initial_event)
@@ -130,41 +159,50 @@ module Datadog
130
159
  end
131
160
 
132
161
  def emit_closing!
133
- return if !@enabled || forked?
162
+ return unless enabled?
134
163
 
135
164
  @worker.enqueue(Event::AppClosing.new)
136
165
  end
137
166
 
138
167
  def integrations_change!
139
- return if !@enabled || forked?
168
+ return unless enabled?
140
169
 
141
170
  @worker.enqueue(Event::AppIntegrationsChange.new)
142
171
  end
143
172
 
144
173
  def log!(event)
145
- return if !@enabled || forked? || !@log_collection_enabled
174
+ return unless enabled? && @log_collection_enabled
146
175
 
147
176
  @worker.enqueue(event)
148
177
  end
149
178
 
150
179
  # Wait for the worker to send out all events that have already
151
180
  # been queued, up to 15 seconds. Returns whether all events have
152
- # been flushed.
181
+ # been flushed, or nil if telemetry is disabled.
153
182
  #
154
183
  # @api private
155
- def flush
156
- return if !@enabled || forked?
184
+ def flush(timeout: nil)
185
+ return unless enabled?
157
186
 
158
- @worker.flush
187
+ @worker.flush(timeout: timeout)
159
188
  end
160
189
 
161
190
  # Report configuration changes caused by Remote Configuration.
162
191
  def client_configuration_change!(changes)
163
- return if !@enabled || forked?
192
+ return unless enabled?
164
193
 
165
194
  @worker.enqueue(Event::AppClientConfigurationChange.new(changes, 'remote_config'))
166
195
  end
167
196
 
197
+ # Report application endpoints
198
+ def app_endpoints_loaded(endpoints, page_size: ENDPOINT_COLLECTION_MESSAGE_LIMIT)
199
+ return unless enabled?
200
+
201
+ endpoints.each_slice(page_size).with_index do |endpoints_slice, i|
202
+ @worker.enqueue(Event::AppEndpointsLoaded.new(endpoints_slice, is_first: i.zero?))
203
+ end
204
+ end
205
+
168
206
  # Increments a count metric.
169
207
  def inc(namespace, metric_name, value, tags: {}, common: true)
170
208
  @metrics_manager.inc(namespace, metric_name, value, tags: tags, common: common)
@@ -189,6 +227,22 @@ module Datadog
189
227
  def distribution(namespace, metric_name, value, tags: {}, common: true)
190
228
  @metrics_manager.distribution(namespace, metric_name, value, tags: tags, common: common)
191
229
  end
230
+
231
+ # When a fork happens, we generally need to do two things inside the
232
+ # child proess:
233
+ # 1. Restart the worker.
234
+ # 2. Discard any events and metrics that were submitted in the
235
+ # parent process (because they will be sent out in the parent
236
+ # process, sending them in the child would cause duplicate
237
+ # submission).
238
+ def after_fork
239
+ # We cannot simply create a new instance of metrics manager because
240
+ # it is referenced from other objects (e.g. the worker).
241
+ # We must reset the existing instance.
242
+ @metrics_manager.clear
243
+
244
+ worker&.send(:after_fork_monkey_patched)
245
+ end
192
246
  end
193
247
  end
194
248
  end
@@ -31,15 +31,15 @@ module Datadog
31
31
  seq_id = self.class.sequence.next
32
32
  payload = Request.build_payload(event, seq_id, debug: debug?)
33
33
  res = @transport.send_telemetry(request_type: event.type, payload: payload)
34
- logger.debug { "Telemetry sent for event `#{event.type}` (response code: #{res.code})" }
34
+ if res.ok?
35
+ logger.debug { "Telemetry sent for event `#{event.type}`" }
36
+ else
37
+ logger.debug { "Failed to send telemetry for event `#{event.type}`: #{res.inspect}" }
38
+ end
35
39
  res
36
40
  rescue => e
37
41
  logger.debug {
38
- "Unable to send telemetry request for event `#{begin
39
- event.type
40
- rescue
41
- "unknown"
42
- end}`: #{e}"
42
+ "Unable to send telemetry request for event `#{event.respond_to?(:type) ? event.type : event.to_s}`: #{e.class}: #{e}"
43
43
  }
44
44
  Core::Transport::InternalErrorResponse.new(e)
45
45
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Datadog
6
+ module Core
7
+ module Telemetry
8
+ module Event
9
+ # Telemetry event class for sending 'app-endpoints' payload
10
+ class AppEndpointsLoaded < Base
11
+ def initialize(endpoints, is_first:)
12
+ @endpoints = endpoints
13
+ @is_first = !!is_first
14
+ end
15
+
16
+ def type
17
+ 'app-endpoints'
18
+ end
19
+
20
+ def payload
21
+ {
22
+ is_first: @is_first,
23
+ endpoints: @endpoints
24
+ }
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end