ddtrace 1.14.0 → 1.16.2

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 (282) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +165 -2
  3. data/ext/ddtrace_profiling_native_extension/NativeExtensionDesign.md +3 -5
  4. data/ext/ddtrace_profiling_native_extension/clock_id.h +0 -3
  5. data/ext/ddtrace_profiling_native_extension/clock_id_from_pthread.c +0 -22
  6. data/ext/ddtrace_profiling_native_extension/clock_id_noop.c +0 -1
  7. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +41 -6
  8. data/ext/ddtrace_profiling_native_extension/collectors_idle_sampling_helper.c +3 -0
  9. data/ext/ddtrace_profiling_native_extension/collectors_stack.c +76 -24
  10. data/ext/ddtrace_profiling_native_extension/collectors_stack.h +1 -1
  11. data/ext/ddtrace_profiling_native_extension/collectors_thread_context.c +207 -32
  12. data/ext/ddtrace_profiling_native_extension/collectors_thread_context.h +1 -1
  13. data/ext/ddtrace_profiling_native_extension/extconf.rb +8 -2
  14. data/ext/ddtrace_profiling_native_extension/http_transport.c +26 -10
  15. data/ext/ddtrace_profiling_native_extension/libdatadog_helpers.c +42 -0
  16. data/ext/ddtrace_profiling_native_extension/libdatadog_helpers.h +6 -0
  17. data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +1 -16
  18. data/ext/ddtrace_profiling_native_extension/pid_controller.c +57 -0
  19. data/ext/ddtrace_profiling_native_extension/pid_controller.h +45 -0
  20. data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +17 -12
  21. data/ext/ddtrace_profiling_native_extension/profiling.c +0 -2
  22. data/ext/ddtrace_profiling_native_extension/stack_recorder.c +74 -37
  23. data/ext/ddtrace_profiling_native_extension/stack_recorder.h +13 -3
  24. data/lib/datadog/appsec/assets/waf_rules/processors.json +92 -0
  25. data/lib/datadog/appsec/assets/waf_rules/recommended.json +698 -75
  26. data/lib/datadog/appsec/assets/waf_rules/scanners.json +114 -0
  27. data/lib/datadog/appsec/assets/waf_rules/strict.json +98 -8
  28. data/lib/datadog/appsec/assets.rb +8 -0
  29. data/lib/datadog/appsec/component.rb +9 -2
  30. data/lib/datadog/appsec/configuration/settings.rb +61 -2
  31. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +6 -2
  32. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +8 -6
  33. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +2 -7
  34. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +2 -5
  35. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +2 -5
  36. data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +3 -2
  37. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +24 -10
  38. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +3 -2
  39. data/lib/datadog/appsec/contrib/rails/patcher.rb +9 -3
  40. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +2 -5
  41. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +6 -4
  42. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +13 -7
  43. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +2 -5
  44. data/lib/datadog/appsec/event.rb +106 -50
  45. data/lib/datadog/appsec/monitor/gateway/watcher.rb +3 -3
  46. data/lib/datadog/appsec/monitor/reactive/set_user.rb +2 -5
  47. data/lib/datadog/appsec/processor/actions.rb +49 -0
  48. data/lib/datadog/appsec/processor/rule_merger.rb +22 -2
  49. data/lib/datadog/appsec/processor.rb +34 -6
  50. data/lib/datadog/appsec/remote.rb +4 -1
  51. data/lib/datadog/appsec/response.rb +82 -4
  52. data/lib/datadog/appsec/sample_rate.rb +21 -0
  53. data/lib/datadog/appsec.rb +2 -2
  54. data/lib/datadog/core/configuration/agent_settings_resolver.rb +29 -24
  55. data/lib/datadog/core/configuration/base.rb +1 -11
  56. data/lib/datadog/core/configuration/components.rb +7 -2
  57. data/lib/datadog/core/configuration/ext.rb +21 -0
  58. data/lib/datadog/core/configuration/option.rb +2 -4
  59. data/lib/datadog/core/configuration/option_definition.rb +17 -41
  60. data/lib/datadog/core/configuration/options.rb +5 -5
  61. data/lib/datadog/core/configuration/settings.rb +47 -45
  62. data/lib/datadog/core/environment/execution.rb +47 -9
  63. data/lib/datadog/core/environment/variable_helpers.rb +0 -69
  64. data/lib/datadog/core/error.rb +1 -0
  65. data/lib/datadog/core/git/ext.rb +2 -0
  66. data/lib/datadog/core/remote/client/capabilities.rb +1 -1
  67. data/lib/datadog/core/remote/component.rb +2 -2
  68. data/lib/datadog/core/remote/negotiation.rb +2 -2
  69. data/lib/datadog/core/remote/transport/config.rb +60 -0
  70. data/lib/datadog/core/remote/transport/http/api/instance.rb +39 -0
  71. data/lib/datadog/core/remote/transport/http/api/spec.rb +21 -0
  72. data/lib/datadog/core/remote/transport/http/api.rb +58 -0
  73. data/lib/datadog/core/remote/transport/http/builder.rb +219 -0
  74. data/lib/datadog/core/remote/transport/http/client.rb +48 -0
  75. data/lib/datadog/core/remote/transport/http/config.rb +280 -0
  76. data/lib/datadog/core/remote/transport/http/negotiation.rb +146 -0
  77. data/lib/datadog/core/remote/transport/http.rb +179 -0
  78. data/lib/datadog/core/{transport → remote/transport}/negotiation.rb +25 -23
  79. data/lib/datadog/core/remote/worker.rb +3 -1
  80. data/lib/datadog/core/telemetry/collector.rb +3 -2
  81. data/lib/datadog/core/telemetry/http/transport.rb +2 -1
  82. data/lib/datadog/core/transport/ext.rb +47 -0
  83. data/lib/datadog/core/transport/http/adapters/net.rb +168 -0
  84. data/lib/datadog/core/transport/http/adapters/registry.rb +29 -0
  85. data/lib/datadog/core/transport/http/adapters/test.rb +89 -0
  86. data/lib/datadog/core/transport/http/adapters/unix_socket.rb +83 -0
  87. data/lib/datadog/core/transport/http/api/endpoint.rb +31 -0
  88. data/lib/datadog/core/transport/http/api/fallbacks.rb +26 -0
  89. data/lib/datadog/core/transport/http/api/map.rb +18 -0
  90. data/lib/datadog/core/transport/http/env.rb +62 -0
  91. data/lib/datadog/core/transport/http/response.rb +60 -0
  92. data/lib/datadog/core/transport/parcel.rb +22 -0
  93. data/lib/datadog/core/transport/request.rb +17 -0
  94. data/lib/datadog/core/transport/response.rb +64 -0
  95. data/lib/datadog/core/workers/polling.rb +2 -2
  96. data/lib/datadog/opentelemetry/api/context.rb +10 -3
  97. data/lib/datadog/opentelemetry/sdk/propagator.rb +2 -1
  98. data/lib/datadog/opentelemetry/sdk/span_processor.rb +14 -2
  99. data/lib/datadog/opentelemetry/sdk/trace/span.rb +68 -0
  100. data/lib/datadog/opentelemetry/trace.rb +58 -0
  101. data/lib/datadog/opentelemetry.rb +1 -0
  102. data/lib/datadog/opentracer.rb +9 -0
  103. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +14 -19
  104. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -1
  105. data/lib/datadog/profiling/collectors/thread_context.rb +9 -1
  106. data/lib/datadog/profiling/component.rb +24 -99
  107. data/lib/datadog/profiling/ext.rb +0 -12
  108. data/lib/datadog/profiling/flush.rb +0 -3
  109. data/lib/datadog/profiling/http_transport.rb +6 -3
  110. data/lib/datadog/profiling/native_extension.rb +0 -21
  111. data/lib/datadog/profiling/profiler.rb +36 -13
  112. data/lib/datadog/profiling/scheduler.rb +16 -9
  113. data/lib/datadog/profiling.rb +8 -81
  114. data/lib/datadog/tracing/component.rb +10 -4
  115. data/lib/datadog/tracing/configuration/agent_settings_resolver.rb +13 -0
  116. data/lib/datadog/tracing/configuration/ext.rb +4 -2
  117. data/lib/datadog/tracing/configuration/settings.rb +14 -7
  118. data/lib/datadog/tracing/contrib/action_pack/configuration/settings.rb +1 -1
  119. data/lib/datadog/tracing/contrib/active_job/configuration/settings.rb +1 -1
  120. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +4 -0
  121. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +106 -197
  122. data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +3 -0
  123. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +7 -0
  124. data/lib/datadog/tracing/contrib/concurrent_ruby/context_composite_executor_service.rb +14 -14
  125. data/lib/datadog/tracing/contrib/concurrent_ruby/future_patch.rb +3 -10
  126. data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +2 -1
  127. data/lib/datadog/tracing/contrib/concurrent_ruby/patcher.rb +8 -1
  128. data/lib/datadog/tracing/contrib/concurrent_ruby/promises_future_patch.rb +22 -0
  129. data/lib/datadog/tracing/contrib/configuration/settings.rb +1 -1
  130. data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +6 -0
  131. data/lib/datadog/tracing/contrib/dalli/ext.rb +7 -0
  132. data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +9 -2
  133. data/lib/datadog/tracing/contrib/delayed_job/configuration/settings.rb +1 -1
  134. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +5 -0
  135. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +5 -0
  136. data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +8 -0
  137. data/lib/datadog/tracing/contrib/excon/middleware.rb +5 -0
  138. data/lib/datadog/tracing/contrib/ext.rb +3 -0
  139. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +1 -1
  140. data/lib/datadog/tracing/contrib/faraday/middleware.rb +5 -0
  141. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +21 -1
  142. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +11 -1
  143. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +18 -0
  144. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor.rb +0 -4
  145. data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +3 -3
  146. data/lib/datadog/tracing/contrib/http/instrumentation.rb +5 -0
  147. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +5 -0
  148. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +5 -0
  149. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +7 -0
  150. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +13 -3
  151. data/lib/datadog/tracing/contrib/opensearch/integration.rb +2 -2
  152. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +7 -0
  153. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +5 -0
  154. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +5 -0
  155. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +1 -1
  156. data/lib/datadog/tracing/contrib/que/configuration/settings.rb +1 -1
  157. data/lib/datadog/tracing/contrib/racecar/event.rb +5 -0
  158. data/lib/datadog/tracing/contrib/rack/header_tagging.rb +14 -4
  159. data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +4 -4
  160. data/lib/datadog/tracing/contrib/rake/configuration/settings.rb +1 -1
  161. data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +1 -1
  162. data/lib/datadog/tracing/contrib/redis/instrumentation.rb +3 -38
  163. data/lib/datadog/tracing/contrib/redis/tags.rb +7 -2
  164. data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +46 -33
  165. data/lib/datadog/tracing/contrib/resque/configuration/settings.rb +1 -1
  166. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +5 -0
  167. data/lib/datadog/tracing/contrib/sequel/utils.rb +5 -0
  168. data/lib/datadog/tracing/contrib/shoryuken/configuration/settings.rb +1 -1
  169. data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +1 -1
  170. data/lib/datadog/tracing/contrib/sneakers/configuration/settings.rb +1 -1
  171. data/lib/datadog/tracing/contrib/utils/quantization/http.rb +2 -2
  172. data/lib/datadog/tracing/diagnostics/environment_logger.rb +6 -0
  173. data/lib/datadog/tracing/distributed/propagation.rb +13 -33
  174. data/lib/datadog/tracing/metadata/tagging.rb +3 -3
  175. data/lib/datadog/tracing/sync_writer.rb +3 -3
  176. data/lib/datadog/tracing/tracer.rb +2 -0
  177. data/lib/datadog/{core → tracing}/transport/http/api/instance.rb +1 -1
  178. data/lib/datadog/{core → tracing}/transport/http/api/spec.rb +1 -1
  179. data/lib/datadog/tracing/transport/http/api.rb +43 -0
  180. data/lib/datadog/{core → tracing}/transport/http/builder.rb +13 -68
  181. data/lib/datadog/tracing/transport/http/client.rb +57 -0
  182. data/lib/datadog/tracing/transport/http/statistics.rb +47 -0
  183. data/lib/datadog/tracing/transport/http/traces.rb +152 -0
  184. data/lib/datadog/tracing/transport/http.rb +124 -0
  185. data/lib/datadog/tracing/transport/io/client.rb +89 -0
  186. data/lib/datadog/tracing/transport/io/response.rb +27 -0
  187. data/lib/datadog/tracing/transport/io/traces.rb +101 -0
  188. data/lib/datadog/tracing/transport/io.rb +30 -0
  189. data/lib/datadog/tracing/transport/serializable_trace.rb +126 -0
  190. data/lib/datadog/tracing/transport/statistics.rb +77 -0
  191. data/lib/datadog/tracing/transport/trace_formatter.rb +209 -0
  192. data/lib/datadog/tracing/transport/traces.rb +224 -0
  193. data/lib/datadog/tracing/workers/trace_writer.rb +5 -3
  194. data/lib/datadog/tracing/workers.rb +3 -2
  195. data/lib/datadog/tracing/writer.rb +5 -2
  196. data/lib/ddtrace/transport/ext.rb +17 -15
  197. data/lib/ddtrace/version.rb +2 -2
  198. data/lib/ddtrace.rb +1 -1
  199. metadata +73 -96
  200. data/lib/datadog/ci/configuration/components.rb +0 -32
  201. data/lib/datadog/ci/configuration/settings.rb +0 -51
  202. data/lib/datadog/ci/contrib/cucumber/configuration/settings.rb +0 -35
  203. data/lib/datadog/ci/contrib/cucumber/ext.rb +0 -22
  204. data/lib/datadog/ci/contrib/cucumber/formatter.rb +0 -94
  205. data/lib/datadog/ci/contrib/cucumber/instrumentation.rb +0 -28
  206. data/lib/datadog/ci/contrib/cucumber/integration.rb +0 -47
  207. data/lib/datadog/ci/contrib/cucumber/patcher.rb +0 -27
  208. data/lib/datadog/ci/contrib/minitest/configuration/settings.rb +0 -35
  209. data/lib/datadog/ci/contrib/minitest/ext.rb +0 -21
  210. data/lib/datadog/ci/contrib/minitest/integration.rb +0 -49
  211. data/lib/datadog/ci/contrib/minitest/patcher.rb +0 -27
  212. data/lib/datadog/ci/contrib/minitest/test_helper.rb +0 -68
  213. data/lib/datadog/ci/contrib/rspec/configuration/settings.rb +0 -35
  214. data/lib/datadog/ci/contrib/rspec/example.rb +0 -68
  215. data/lib/datadog/ci/contrib/rspec/ext.rb +0 -21
  216. data/lib/datadog/ci/contrib/rspec/integration.rb +0 -48
  217. data/lib/datadog/ci/contrib/rspec/patcher.rb +0 -27
  218. data/lib/datadog/ci/ext/app_types.rb +0 -9
  219. data/lib/datadog/ci/ext/environment.rb +0 -575
  220. data/lib/datadog/ci/ext/settings.rb +0 -10
  221. data/lib/datadog/ci/ext/test.rb +0 -35
  222. data/lib/datadog/ci/extensions.rb +0 -19
  223. data/lib/datadog/ci/flush.rb +0 -38
  224. data/lib/datadog/ci/test.rb +0 -81
  225. data/lib/datadog/ci.rb +0 -21
  226. data/lib/datadog/core/configuration/dependency_resolver.rb +0 -28
  227. data/lib/datadog/core/configuration/option_definition_set.rb +0 -22
  228. data/lib/datadog/core/configuration/option_set.rb +0 -10
  229. data/lib/datadog/core/transport/config.rb +0 -58
  230. data/lib/datadog/core/transport/http/api.rb +0 -57
  231. data/lib/datadog/core/transport/http/client.rb +0 -45
  232. data/lib/datadog/core/transport/http/config.rb +0 -278
  233. data/lib/datadog/core/transport/http/negotiation.rb +0 -144
  234. data/lib/datadog/core/transport/http.rb +0 -169
  235. data/lib/datadog/core/utils/object_set.rb +0 -43
  236. data/lib/datadog/core/utils/string_table.rb +0 -47
  237. data/lib/datadog/profiling/backtrace_location.rb +0 -34
  238. data/lib/datadog/profiling/buffer.rb +0 -43
  239. data/lib/datadog/profiling/collectors/old_stack.rb +0 -301
  240. data/lib/datadog/profiling/encoding/profile.rb +0 -41
  241. data/lib/datadog/profiling/event.rb +0 -15
  242. data/lib/datadog/profiling/events/stack.rb +0 -82
  243. data/lib/datadog/profiling/old_recorder.rb +0 -107
  244. data/lib/datadog/profiling/pprof/builder.rb +0 -125
  245. data/lib/datadog/profiling/pprof/converter.rb +0 -102
  246. data/lib/datadog/profiling/pprof/message_set.rb +0 -16
  247. data/lib/datadog/profiling/pprof/payload.rb +0 -20
  248. data/lib/datadog/profiling/pprof/pprof.proto +0 -212
  249. data/lib/datadog/profiling/pprof/pprof_pb.rb +0 -81
  250. data/lib/datadog/profiling/pprof/stack_sample.rb +0 -139
  251. data/lib/datadog/profiling/pprof/string_table.rb +0 -12
  252. data/lib/datadog/profiling/pprof/template.rb +0 -118
  253. data/lib/datadog/profiling/trace_identifiers/ddtrace.rb +0 -43
  254. data/lib/datadog/profiling/trace_identifiers/helper.rb +0 -45
  255. data/lib/ddtrace/transport/http/adapters/net.rb +0 -168
  256. data/lib/ddtrace/transport/http/adapters/registry.rb +0 -27
  257. data/lib/ddtrace/transport/http/adapters/test.rb +0 -85
  258. data/lib/ddtrace/transport/http/adapters/unix_socket.rb +0 -77
  259. data/lib/ddtrace/transport/http/api/endpoint.rb +0 -29
  260. data/lib/ddtrace/transport/http/api/fallbacks.rb +0 -24
  261. data/lib/ddtrace/transport/http/api/instance.rb +0 -35
  262. data/lib/ddtrace/transport/http/api/map.rb +0 -16
  263. data/lib/ddtrace/transport/http/api/spec.rb +0 -17
  264. data/lib/ddtrace/transport/http/api.rb +0 -39
  265. data/lib/ddtrace/transport/http/builder.rb +0 -176
  266. data/lib/ddtrace/transport/http/client.rb +0 -52
  267. data/lib/ddtrace/transport/http/env.rb +0 -58
  268. data/lib/ddtrace/transport/http/response.rb +0 -58
  269. data/lib/ddtrace/transport/http/statistics.rb +0 -43
  270. data/lib/ddtrace/transport/http/traces.rb +0 -144
  271. data/lib/ddtrace/transport/http.rb +0 -117
  272. data/lib/ddtrace/transport/io/client.rb +0 -85
  273. data/lib/ddtrace/transport/io/response.rb +0 -25
  274. data/lib/ddtrace/transport/io/traces.rb +0 -99
  275. data/lib/ddtrace/transport/io.rb +0 -28
  276. data/lib/ddtrace/transport/parcel.rb +0 -20
  277. data/lib/ddtrace/transport/request.rb +0 -15
  278. data/lib/ddtrace/transport/response.rb +0 -60
  279. data/lib/ddtrace/transport/serializable_trace.rb +0 -122
  280. data/lib/ddtrace/transport/statistics.rb +0 -75
  281. data/lib/ddtrace/transport/trace_formatter.rb +0 -207
  282. data/lib/ddtrace/transport/traces.rb +0 -216
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Core
5
+ module Remote
6
+ module Transport
7
+ module HTTP
8
+ module API
9
+ # Specification for an HTTP API
10
+ # Defines behaviors without specific configuration details.
11
+ class Spec
12
+ def initialize
13
+ yield(self) if block_given?
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../encoding'
4
+ require_relative '../../../transport/http/api/map'
5
+
6
+ # TODO: Decouple standard transport/http/api/instance
7
+ #
8
+ # Separate classes are needed because transport/http/traces includes
9
+ # Trace::API::Instance which closes over and uses a single spec, which is
10
+ # negotiated as either /v3 or /v4 for the whole API at the spec level, but we
11
+ # need an independent toplevel path at the endpoint level.
12
+ #
13
+ # Separate classes are needed because of `include Trace::API::Instance`.
14
+ #
15
+ # Below should be:
16
+ # require_relative '../../../../ddtrace/transport/http/api/spec'
17
+ require_relative 'api/spec'
18
+
19
+ # TODO: only needed for Negotiation::API::Endpoint
20
+ require_relative 'negotiation'
21
+
22
+ # TODO: only needed for Config::API::Endpoint
23
+ require_relative 'config'
24
+
25
+ module Datadog
26
+ module Core
27
+ module Remote
28
+ module Transport
29
+ module HTTP
30
+ # Namespace for API components
31
+ module API
32
+ # Default API versions
33
+ ROOT = 'root'
34
+ V7 = 'v0.7'
35
+
36
+ module_function
37
+
38
+ def defaults
39
+ Datadog::Core::Transport::HTTP::API::Map[
40
+ ROOT => Spec.new do |s|
41
+ s.info = Negotiation::API::Endpoint.new(
42
+ '/info',
43
+ )
44
+ end,
45
+ V7 => Spec.new do |s|
46
+ s.config = Config::API::Endpoint.new(
47
+ '/v0.7/config',
48
+ Core::Encoding::JSONEncoder,
49
+ )
50
+ end,
51
+ ]
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,219 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../configuration/agent_settings_resolver'
4
+ require_relative '../../../transport/http/adapters/registry'
5
+ require_relative '../../../transport/http/api/map'
6
+
7
+ # TODO: Decouple standard transport/http/api/instance
8
+ #
9
+ # Separate classes are needed because transport/http/trace includes
10
+ # Trace::API::Instance which closes over and uses a single spec, which is
11
+ # negotiated as either /v3 or /v4 for the whole API at the spec level, but we
12
+ # need an independent toplevel path at the endpoint level.
13
+ #
14
+ # Separate classes are needed because of `include Trace::API::Instance`.
15
+ #
16
+ # Below should be:
17
+ # require_relative '../../../../ddtrace/transport/http/api/instance'
18
+ require_relative 'api/instance'
19
+
20
+ # TODO: Decouple transport/http/client
21
+ #
22
+ # The standard one does `include Transport::HTTP::Statistics` and performs
23
+ # stats updates, which may or may not be desirable in general.
24
+ #
25
+ # Below should be:
26
+ # require_relative '../../../../ddtrace/transport/http/client'
27
+ require_relative 'client'
28
+
29
+ # TODO: Decouple transport/http/builder
30
+ #
31
+ # This class is duplicated even though it is tantalisingly close to the
32
+ # one in ddtrace/transport mostly because it refers to a different
33
+ # `API::Instance` in `#api_instance_class` but also because it operates on a
34
+ # different `HTTP::Client`, as well as de-hardcoding the transport class
35
+ # `Transport::Traces::Transport` in `#to_transport`
36
+ #
37
+ # Additionally, its design makes it so there can be only one (API, Client,
38
+ # Transport) triplet, requiring a new transport instance for any varying
39
+ # element of the triplet.
40
+
41
+ module Datadog
42
+ module Core
43
+ module Remote
44
+ module Transport
45
+ module HTTP
46
+ # Builds new instances of Transport::HTTP::Client
47
+ class Builder
48
+ REGISTRY = Datadog::Core::Transport::HTTP::Adapters::Registry.new
49
+
50
+ attr_reader \
51
+ :apis,
52
+ :api_options,
53
+ :default_adapter,
54
+ :default_api,
55
+ :default_headers
56
+
57
+ def initialize
58
+ # Global settings
59
+ @default_adapter = nil
60
+ @default_headers = {}
61
+
62
+ # Client settings
63
+ @apis = Datadog::Core::Transport::HTTP::API::Map.new
64
+ @default_api = nil
65
+
66
+ # API settings
67
+ @api_options = {}
68
+
69
+ yield(self) if block_given?
70
+ end
71
+
72
+ def adapter(config, *args, **kwargs)
73
+ @default_adapter = case config
74
+ when Core::Configuration::AgentSettingsResolver::AgentSettings
75
+ registry_klass = REGISTRY.get(config.adapter)
76
+ raise UnknownAdapterError, config.adapter if registry_klass.nil?
77
+
78
+ registry_klass.build(config)
79
+ when Symbol
80
+ registry_klass = REGISTRY.get(config)
81
+ raise UnknownAdapterError, config if registry_klass.nil?
82
+
83
+ registry_klass.new(*args, **kwargs)
84
+ else
85
+ config
86
+ end
87
+ end
88
+
89
+ def headers(values = {})
90
+ @default_headers.merge!(values)
91
+ end
92
+
93
+ # Adds a new API to the client
94
+ # Valid options:
95
+ # - :adapter
96
+ # - :default
97
+ # - :fallback
98
+ # - :headers
99
+ def api(key, spec, options = {})
100
+ options = options.dup
101
+
102
+ # Copy spec into API map
103
+ @apis[key] = spec
104
+
105
+ # Apply as default API, if specified to do so.
106
+ @default_api = key if options.delete(:default) || @default_api.nil?
107
+
108
+ # Save all other settings for initialization
109
+ (@api_options[key] ||= {}).merge!(options)
110
+ end
111
+
112
+ def default_api=(key)
113
+ raise UnknownApiError, key unless @apis.key?(key)
114
+
115
+ @default_api = key
116
+ end
117
+
118
+ def to_transport(klass)
119
+ raise NoDefaultApiError if @default_api.nil?
120
+
121
+ klass.new(to_api_instances, @default_api)
122
+ end
123
+
124
+ def to_api_instances
125
+ raise NoApisError if @apis.empty?
126
+
127
+ @apis.inject(Datadog::Core::Transport::HTTP::API::Map.new) do |instances, (key, spec)|
128
+ instances.tap do
129
+ api_options = @api_options[key].dup
130
+
131
+ # Resolve the adapter to use for this API
132
+ adapter = api_options.delete(:adapter) || @default_adapter
133
+ raise NoAdapterForApiError, key if adapter.nil?
134
+
135
+ # Resolve fallback and merge headers
136
+ fallback = api_options.delete(:fallback)
137
+ api_options[:headers] = @default_headers.merge((api_options[:headers] || {}))
138
+
139
+ # Add API::Instance with all settings
140
+ instances[key] = api_instance_class.new(
141
+ spec,
142
+ adapter,
143
+ api_options
144
+ )
145
+
146
+ # Configure fallback, if provided.
147
+ instances.with_fallbacks(key => fallback) unless fallback.nil?
148
+ end
149
+ end
150
+ end
151
+
152
+ def api_instance_class
153
+ API::Instance
154
+ end
155
+
156
+ # Raised when the API key does not match known APIs.
157
+ class UnknownApiError < StandardError
158
+ attr_reader :key
159
+
160
+ def initialize(key)
161
+ super()
162
+
163
+ @key = key
164
+ end
165
+
166
+ def message
167
+ "Unknown transport API '#{key}'!"
168
+ end
169
+ end
170
+
171
+ # Raised when the identifier cannot be matched to an adapter.
172
+ class UnknownAdapterError < StandardError
173
+ attr_reader :type
174
+
175
+ def initialize(type)
176
+ super()
177
+
178
+ @type = type
179
+ end
180
+
181
+ def message
182
+ "Unknown transport adapter '#{type}'!"
183
+ end
184
+ end
185
+
186
+ # Raised when an adapter cannot be resolved for an API instance.
187
+ class NoAdapterForApiError < StandardError
188
+ attr_reader :key
189
+
190
+ def initialize(key)
191
+ super()
192
+
193
+ @key = key
194
+ end
195
+
196
+ def message
197
+ "No adapter resolved for transport API '#{key}'!"
198
+ end
199
+ end
200
+
201
+ # Raised when built without defining APIs.
202
+ class NoApisError < StandardError
203
+ def message
204
+ 'No APIs configured for transport!'
205
+ end
206
+ end
207
+
208
+ # Raised when client built without defining a default API.
209
+ class NoDefaultApiError < StandardError
210
+ def message
211
+ 'No default API configured for transport!'
212
+ end
213
+ end
214
+ end
215
+ end
216
+ end
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../../core/transport/http/env'
4
+ require_relative '../../../../core/transport/http/response'
5
+
6
+ # TODO: Decouple transport/http/client
7
+ #
8
+ # The standard one does `include Transport::HTTP::Statistics` and performs
9
+ # stats updates, which may or may not be desirable in general.
10
+
11
+ module Datadog
12
+ module Core
13
+ module Remote
14
+ module Transport
15
+ module HTTP
16
+ # Routes, encodes, and sends tracer data to the trace agent via HTTP.
17
+ class Client
18
+ attr_reader :api
19
+
20
+ def initialize(api)
21
+ @api = api
22
+ end
23
+
24
+ def send_request(request, &block)
25
+ # Build request into env
26
+ env = build_env(request)
27
+
28
+ # Get responses from API
29
+ yield(api, env)
30
+ rescue StandardError => e
31
+ message =
32
+ "Internal error during #{self.class.name} request. Cause: #{e.class.name} #{e.message} " \
33
+ "Location: #{Array(e.backtrace).first}"
34
+
35
+ Datadog.logger.debug(message)
36
+
37
+ Datadog::Core::Transport::InternalErrorResponse.new(e)
38
+ end
39
+
40
+ def build_env(request)
41
+ Datadog::Core::Transport::HTTP::Env.new(request)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,280 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'base64'
5
+
6
+ require_relative '../config'
7
+ require_relative 'client'
8
+ require_relative '../../../transport/http/response'
9
+ require_relative '../../../transport/http/api/endpoint'
10
+
11
+ # TODO: Decouple standard transport/http/api/instance
12
+ #
13
+ # Separate classes are needed because transport/http/trace includes
14
+ # Trace::API::Instance which closes over and uses a single spec, which is
15
+ # negotiated as either /v3 or /v4 for the whole API at the spec level, but we
16
+ # need an independent toplevel path at the endpoint level.
17
+ #
18
+ # Separate classes are needed because of `include Trace::API::Instance`.
19
+ #
20
+ # Below should be:
21
+ # require_relative '../../../core/transport/http/api/instance'
22
+ require_relative 'api/instance'
23
+ # Below should be:
24
+ # require_relative '../../../core/transport/http/api/spec'
25
+ require_relative 'api/spec'
26
+
27
+ module Datadog
28
+ module Core
29
+ module Remote
30
+ module Transport
31
+ module HTTP
32
+ # HTTP transport behavior for remote configuration
33
+ module Config
34
+ # Response from HTTP transport for remote configuration
35
+ class Response
36
+ include Datadog::Core::Transport::HTTP::Response
37
+ include Core::Remote::Transport::Config::Response
38
+
39
+ def initialize(http_response, options = {}) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
40
+ super(http_response)
41
+
42
+ begin
43
+ payload = JSON.parse(http_response.payload, symbolize_names: true)
44
+ rescue JSON::ParserError => e
45
+ raise ParseError.new(:roots, e)
46
+ end
47
+
48
+ raise TypeError.new(Hash, payload) unless payload.is_a?(Hash)
49
+
50
+ @empty = true if payload.empty?
51
+
52
+ # TODO: these fallbacks should be improved
53
+ roots = payload[:roots] || []
54
+ targets = payload[:targets] || Base64.encode64('{}').chomp
55
+ target_files = payload[:target_files] || []
56
+ client_configs = payload[:client_configs] || []
57
+
58
+ raise TypeError.new(Array, roots) unless roots.is_a?(Array)
59
+
60
+ @roots = roots.map do |root|
61
+ raise TypeError.new(String, root) unless root.is_a?(String)
62
+
63
+ decoded = begin
64
+ Base64.strict_decode64(root) # TODO: unprocessed, don't symbolize_names
65
+ rescue ArgumentError
66
+ raise DecodeError.new(:roots, root)
67
+ end
68
+
69
+ parsed = begin
70
+ JSON.parse(decoded)
71
+ rescue JSON::ParserError
72
+ raise ParseError.new(:roots, decoded)
73
+ end
74
+
75
+ # TODO: perform more processing to validate content. til then, no freeze
76
+
77
+ parsed
78
+ end
79
+
80
+ raise TypeError.new(String, targets) unless targets.is_a?(String)
81
+
82
+ @targets = begin
83
+ decoded = begin
84
+ Base64.strict_decode64(targets)
85
+ rescue ArgumentError
86
+ raise DecodeError.new(:targets, targets)
87
+ end
88
+
89
+ parsed = begin
90
+ JSON.parse(decoded) # TODO: unprocessed, don't symbolize_names
91
+ rescue JSON::ParserError
92
+ raise ParseError.new(:targets, decoded)
93
+ end
94
+
95
+ # TODO: perform more processing to validate content. til then, no freeze
96
+
97
+ parsed
98
+ end
99
+
100
+ raise TypeError.new(Array, target_files) unless target_files.is_a?(Array)
101
+
102
+ @target_files = target_files.map do |h|
103
+ raise TypeError.new(Hash, h) unless h.is_a?(Hash)
104
+ raise KeyError.new(:raw) unless h.key?(:raw) # rubocop:disable Style/RaiseArgs
105
+ raise KeyError.new(:path) unless h.key?(:path) # rubocop:disable Style/RaiseArgs
106
+
107
+ raw = h[:raw]
108
+
109
+ raise TypeError.new(String, raw) unless raw.is_a?(String)
110
+
111
+ content = begin
112
+ Base64.strict_decode64(raw)
113
+ rescue ArgumentError
114
+ raise DecodeError.new(:target_files, raw)
115
+ end
116
+
117
+ {
118
+ path: h[:path].freeze,
119
+ content: StringIO.new(content.freeze),
120
+ }
121
+ end.freeze
122
+
123
+ @client_configs = client_configs.map do |s|
124
+ raise TypeError.new(String, s) unless s.is_a?(String)
125
+
126
+ s.freeze
127
+ end.freeze
128
+ end
129
+
130
+ def inspect
131
+ "#{super}, #{
132
+ {
133
+ roots: @roots,
134
+ targets: @targets,
135
+ target_files: @target_files,
136
+ client_configs: @client_configs,
137
+ }}"
138
+ end
139
+
140
+ # When an expected key is missing
141
+ class KeyError < StandardError
142
+ def initialize(key)
143
+ message = "key not found: #{key.inspect}"
144
+
145
+ super(message)
146
+ end
147
+ end
148
+
149
+ # When an expected value type is incorrect
150
+ class TypeError < StandardError
151
+ def initialize(type, value)
152
+ message = "not a #{type}: #{value.inspect}"
153
+
154
+ super(message)
155
+ end
156
+ end
157
+
158
+ # When value decoding fails
159
+ class DecodeError < StandardError
160
+ def initialize(key, value)
161
+ message = "could not decode key #{key.inspect}: #{value.inspect}"
162
+
163
+ super(message)
164
+ end
165
+ end
166
+
167
+ # When value parsing fails
168
+ class ParseError < StandardError
169
+ def initialize(key, value)
170
+ message = "could not parse key #{key.inspect}: #{value.inspect}"
171
+
172
+ super(message)
173
+ end
174
+ end
175
+ end
176
+
177
+ # Extensions for HTTP client
178
+ module Client
179
+ def send_config_payload(request)
180
+ send_request(request) do |api, env|
181
+ api.send_config(env)
182
+ end
183
+ end
184
+ end
185
+
186
+ module API
187
+ # Extensions for HTTP API Spec
188
+ module Spec
189
+ attr_reader :config
190
+
191
+ def config=(endpoint)
192
+ @config = endpoint
193
+ end
194
+
195
+ def send_config(env, &block)
196
+ raise NoConfigEndpointDefinedError, self if config.nil?
197
+
198
+ config.call(env, &block)
199
+ end
200
+
201
+ # Raised when traces sent but no traces endpoint is defined
202
+ class NoConfigEndpointDefinedError < StandardError
203
+ attr_reader :spec
204
+
205
+ def initialize(spec)
206
+ super()
207
+
208
+ @spec = spec
209
+ end
210
+
211
+ def message
212
+ 'No config endpoint is defined for API specification!'
213
+ end
214
+ end
215
+ end
216
+
217
+ # Extensions for HTTP API Instance
218
+ module Instance
219
+ def send_config(env)
220
+ raise ConfigNotSupportedError, spec unless spec.is_a?(Config::API::Spec)
221
+
222
+ spec.send_config(env) do |request_env|
223
+ call(request_env)
224
+ end
225
+ end
226
+
227
+ # Raised when traces sent to API that does not support traces
228
+ class ConfigNotSupportedError < StandardError
229
+ attr_reader :spec
230
+
231
+ def initialize(spec)
232
+ super()
233
+
234
+ @spec = spec
235
+ end
236
+
237
+ def message
238
+ 'Config not supported for this API!'
239
+ end
240
+ end
241
+ end
242
+
243
+ # Endpoint for remote configuration
244
+ class Endpoint < Datadog::Core::Transport::HTTP::API::Endpoint
245
+ HEADER_CONTENT_TYPE = 'Content-Type'
246
+
247
+ attr_reader :encoder
248
+
249
+ def initialize(path, encoder)
250
+ super(:post, path)
251
+ @encoder = encoder
252
+ end
253
+
254
+ def call(env, &block)
255
+ # Encode body & type
256
+ env.headers[HEADER_CONTENT_TYPE] = encoder.content_type
257
+ env.body = env.request.parcel.data
258
+
259
+ # Query for response
260
+ http_response = super(env, &block)
261
+
262
+ response_options = {}
263
+
264
+ # Build and return a response
265
+ Config::Response.new(http_response, response_options)
266
+ end
267
+ end
268
+ end
269
+
270
+ # Add remote configuration behavior to transport components
271
+ ###### overrides send_payload! which calls send_<endpoint>! kills any other possible endpoint!
272
+ HTTP::Client.include(Config::Client)
273
+ HTTP::API::Spec.include(Config::API::Spec)
274
+ HTTP::API::Instance.include(Config::API::Instance)
275
+ end
276
+ end
277
+ end
278
+ end
279
+ end
280
+ end