httpx 0.20.0 → 1.3.1

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 (250) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +0 -48
  3. data/README.md +54 -45
  4. data/doc/release_notes/0_10_0.md +2 -2
  5. data/doc/release_notes/0_11_0.md +3 -5
  6. data/doc/release_notes/0_12_0.md +5 -5
  7. data/doc/release_notes/0_13_0.md +5 -5
  8. data/doc/release_notes/0_14_0.md +2 -2
  9. data/doc/release_notes/0_16_0.md +3 -3
  10. data/doc/release_notes/0_17_0.md +1 -1
  11. data/doc/release_notes/0_18_0.md +4 -4
  12. data/doc/release_notes/0_18_2.md +1 -1
  13. data/doc/release_notes/0_19_0.md +1 -1
  14. data/doc/release_notes/0_19_8.md +1 -1
  15. data/doc/release_notes/0_20_0.md +2 -2
  16. data/doc/release_notes/0_20_1.md +5 -0
  17. data/doc/release_notes/0_20_2.md +7 -0
  18. data/doc/release_notes/0_20_3.md +6 -0
  19. data/doc/release_notes/0_20_4.md +17 -0
  20. data/doc/release_notes/0_20_5.md +3 -0
  21. data/doc/release_notes/0_21_0.md +96 -0
  22. data/doc/release_notes/0_21_1.md +12 -0
  23. data/doc/release_notes/0_22_0.md +13 -0
  24. data/doc/release_notes/0_22_1.md +11 -0
  25. data/doc/release_notes/0_22_2.md +5 -0
  26. data/doc/release_notes/0_22_3.md +55 -0
  27. data/doc/release_notes/0_22_4.md +6 -0
  28. data/doc/release_notes/0_22_5.md +6 -0
  29. data/doc/release_notes/0_23_0.md +42 -0
  30. data/doc/release_notes/0_23_1.md +5 -0
  31. data/doc/release_notes/0_23_2.md +5 -0
  32. data/doc/release_notes/0_23_3.md +6 -0
  33. data/doc/release_notes/0_23_4.md +5 -0
  34. data/doc/release_notes/0_24_0.md +48 -0
  35. data/doc/release_notes/0_24_1.md +12 -0
  36. data/doc/release_notes/0_24_2.md +12 -0
  37. data/doc/release_notes/0_24_3.md +12 -0
  38. data/doc/release_notes/0_24_4.md +18 -0
  39. data/doc/release_notes/0_24_5.md +6 -0
  40. data/doc/release_notes/0_24_6.md +5 -0
  41. data/doc/release_notes/0_24_7.md +10 -0
  42. data/doc/release_notes/1_0_0.md +60 -0
  43. data/doc/release_notes/1_0_1.md +5 -0
  44. data/doc/release_notes/1_0_2.md +7 -0
  45. data/doc/release_notes/1_1_0.md +32 -0
  46. data/doc/release_notes/1_1_1.md +17 -0
  47. data/doc/release_notes/1_1_2.md +12 -0
  48. data/doc/release_notes/1_1_3.md +18 -0
  49. data/doc/release_notes/1_1_4.md +6 -0
  50. data/doc/release_notes/1_1_5.md +12 -0
  51. data/doc/release_notes/1_2_0.md +49 -0
  52. data/doc/release_notes/1_2_1.md +6 -0
  53. data/doc/release_notes/1_2_2.md +10 -0
  54. data/doc/release_notes/1_2_3.md +16 -0
  55. data/doc/release_notes/1_2_4.md +8 -0
  56. data/doc/release_notes/1_2_5.md +7 -0
  57. data/doc/release_notes/1_2_6.md +13 -0
  58. data/doc/release_notes/1_3_0.md +18 -0
  59. data/doc/release_notes/1_3_1.md +17 -0
  60. data/lib/httpx/adapters/datadog.rb +215 -122
  61. data/lib/httpx/adapters/faraday.rb +145 -107
  62. data/lib/httpx/adapters/sentry.rb +26 -7
  63. data/lib/httpx/adapters/webmock.rb +34 -18
  64. data/lib/httpx/altsvc.rb +63 -26
  65. data/lib/httpx/base64.rb +27 -0
  66. data/lib/httpx/buffer.rb +12 -0
  67. data/lib/httpx/callbacks.rb +5 -3
  68. data/lib/httpx/chainable.rb +54 -39
  69. data/lib/httpx/connection/http1.rb +75 -44
  70. data/lib/httpx/connection/http2.rb +31 -38
  71. data/lib/httpx/connection.rb +287 -117
  72. data/lib/httpx/domain_name.rb +10 -13
  73. data/lib/httpx/errors.rb +52 -2
  74. data/lib/httpx/extensions.rb +24 -131
  75. data/lib/httpx/io/ssl.rb +83 -77
  76. data/lib/httpx/io/tcp.rb +48 -71
  77. data/lib/httpx/io/udp.rb +18 -52
  78. data/lib/httpx/io/unix.rb +10 -15
  79. data/lib/httpx/io.rb +3 -9
  80. data/lib/httpx/loggable.rb +4 -19
  81. data/lib/httpx/options.rb +176 -118
  82. data/lib/httpx/parser/http1.rb +4 -0
  83. data/lib/httpx/plugins/{authentication → auth}/basic.rb +1 -5
  84. data/lib/httpx/plugins/{authentication → auth}/digest.rb +14 -14
  85. data/lib/httpx/plugins/{authentication → auth}/ntlm.rb +1 -3
  86. data/lib/httpx/plugins/{authentication → auth}/socks5.rb +0 -2
  87. data/lib/httpx/plugins/auth.rb +25 -0
  88. data/lib/httpx/plugins/aws_sdk_authentication.rb +4 -3
  89. data/lib/httpx/plugins/aws_sigv4.rb +12 -9
  90. data/lib/httpx/plugins/basic_auth.rb +29 -0
  91. data/lib/httpx/plugins/brotli.rb +50 -0
  92. data/lib/httpx/plugins/callbacks.rb +91 -0
  93. data/lib/httpx/plugins/circuit_breaker/circuit.rb +100 -0
  94. data/lib/httpx/plugins/circuit_breaker/circuit_store.rb +53 -0
  95. data/lib/httpx/plugins/circuit_breaker.rb +148 -0
  96. data/lib/httpx/plugins/cookies/set_cookie_parser.rb +0 -2
  97. data/lib/httpx/plugins/cookies.rb +30 -17
  98. data/lib/httpx/plugins/{digest_authentication.rb → digest_auth.rb} +14 -12
  99. data/lib/httpx/plugins/expect.rb +21 -14
  100. data/lib/httpx/plugins/follow_redirects.rb +140 -41
  101. data/lib/httpx/plugins/grpc/call.rb +2 -3
  102. data/lib/httpx/plugins/grpc/grpc_encoding.rb +88 -0
  103. data/lib/httpx/plugins/grpc/message.rb +7 -37
  104. data/lib/httpx/plugins/grpc.rb +36 -29
  105. data/lib/httpx/plugins/h2c.rb +26 -19
  106. data/lib/httpx/plugins/internal_telemetry.rb +16 -0
  107. data/lib/httpx/plugins/{ntlm_authentication.rb → ntlm_auth.rb} +7 -5
  108. data/lib/httpx/plugins/oauth.rb +175 -0
  109. data/lib/httpx/plugins/persistent.rb +1 -1
  110. data/lib/httpx/plugins/proxy/http.rb +23 -13
  111. data/lib/httpx/plugins/proxy/socks4.rb +9 -7
  112. data/lib/httpx/plugins/proxy/socks5.rb +11 -9
  113. data/lib/httpx/plugins/proxy.rb +80 -61
  114. data/lib/httpx/plugins/push_promise.rb +1 -1
  115. data/lib/httpx/plugins/rate_limiter.rb +5 -1
  116. data/lib/httpx/plugins/response_cache/file_store.rb +40 -0
  117. data/lib/httpx/plugins/response_cache/store.rb +62 -25
  118. data/lib/httpx/plugins/response_cache.rb +105 -12
  119. data/lib/httpx/plugins/retries.rb +87 -17
  120. data/lib/httpx/plugins/ssrf_filter.rb +145 -0
  121. data/lib/httpx/plugins/stream.rb +27 -23
  122. data/lib/httpx/plugins/upgrade/h2.rb +4 -4
  123. data/lib/httpx/plugins/upgrade.rb +8 -10
  124. data/lib/httpx/plugins/webdav.rb +80 -0
  125. data/lib/httpx/pool/synch_pool.rb +93 -0
  126. data/lib/httpx/pool.rb +102 -27
  127. data/lib/httpx/punycode.rb +9 -291
  128. data/lib/httpx/request/body.rb +154 -0
  129. data/lib/httpx/request.rb +130 -146
  130. data/lib/httpx/resolver/https.rb +62 -27
  131. data/lib/httpx/resolver/multi.rb +9 -13
  132. data/lib/httpx/resolver/native.rb +192 -76
  133. data/lib/httpx/resolver/resolver.rb +34 -9
  134. data/lib/httpx/resolver/system.rb +16 -11
  135. data/lib/httpx/resolver.rb +38 -16
  136. data/lib/httpx/response/body.rb +242 -0
  137. data/lib/httpx/response/buffer.rb +96 -0
  138. data/lib/httpx/response.rb +159 -217
  139. data/lib/httpx/selector.rb +9 -4
  140. data/lib/httpx/session.rb +137 -89
  141. data/lib/httpx/session_extensions.rb +4 -1
  142. data/lib/httpx/timers.rb +34 -8
  143. data/lib/httpx/transcoder/body.rb +0 -2
  144. data/lib/httpx/transcoder/chunker.rb +0 -1
  145. data/lib/httpx/transcoder/deflate.rb +37 -0
  146. data/lib/httpx/transcoder/form.rb +52 -33
  147. data/lib/httpx/transcoder/gzip.rb +74 -0
  148. data/lib/httpx/transcoder/json.rb +21 -8
  149. data/lib/httpx/transcoder/multipart/decoder.rb +139 -0
  150. data/lib/httpx/{plugins → transcoder}/multipart/encoder.rb +4 -4
  151. data/lib/httpx/{plugins → transcoder}/multipart/mime_type_detector.rb +1 -1
  152. data/lib/httpx/{plugins → transcoder}/multipart/part.rb +3 -2
  153. data/lib/httpx/transcoder/multipart.rb +17 -0
  154. data/lib/httpx/transcoder/utils/body_reader.rb +46 -0
  155. data/lib/httpx/transcoder/utils/deflater.rb +72 -0
  156. data/lib/httpx/transcoder/utils/inflater.rb +19 -0
  157. data/lib/httpx/transcoder/xml.rb +52 -0
  158. data/lib/httpx/transcoder.rb +5 -6
  159. data/lib/httpx/utils.rb +36 -16
  160. data/lib/httpx/version.rb +1 -1
  161. data/lib/httpx.rb +12 -14
  162. data/sig/altsvc.rbs +33 -0
  163. data/sig/buffer.rbs +2 -1
  164. data/sig/callbacks.rbs +3 -3
  165. data/sig/chainable.rbs +11 -9
  166. data/sig/connection/http1.rbs +8 -7
  167. data/sig/connection/http2.rbs +19 -19
  168. data/sig/connection.rbs +64 -24
  169. data/sig/errors.rbs +22 -3
  170. data/sig/httpx.rbs +5 -4
  171. data/sig/io/ssl.rbs +27 -0
  172. data/sig/io/tcp.rbs +60 -0
  173. data/sig/io/udp.rbs +20 -0
  174. data/sig/io/unix.rbs +27 -0
  175. data/sig/io.rbs +6 -0
  176. data/sig/options.rbs +32 -22
  177. data/sig/parser/http1.rbs +1 -1
  178. data/sig/plugins/{authentication → auth}/basic.rbs +0 -2
  179. data/sig/plugins/{authentication → auth}/digest.rbs +2 -1
  180. data/sig/plugins/auth.rbs +13 -0
  181. data/sig/plugins/{basic_authentication.rbs → basic_auth.rbs} +2 -2
  182. data/sig/plugins/brotli.rbs +22 -0
  183. data/sig/plugins/callbacks.rbs +38 -0
  184. data/sig/plugins/circuit_breaker.rbs +71 -0
  185. data/sig/plugins/compression.rbs +7 -5
  186. data/sig/plugins/cookies/jar.rbs +2 -2
  187. data/sig/plugins/cookies.rbs +2 -0
  188. data/sig/plugins/{digest_authentication.rbs → digest_auth.rbs} +2 -2
  189. data/sig/plugins/follow_redirects.rbs +18 -4
  190. data/sig/plugins/grpc/call.rbs +19 -0
  191. data/sig/plugins/grpc/grpc_encoding.rbs +37 -0
  192. data/sig/plugins/grpc/message.rbs +17 -0
  193. data/sig/plugins/grpc.rbs +7 -32
  194. data/sig/plugins/h2c.rbs +1 -1
  195. data/sig/plugins/{ntlm_authentication.rbs → ntlm_auth.rbs} +2 -2
  196. data/sig/plugins/oauth.rbs +54 -0
  197. data/sig/plugins/proxy/http.rbs +3 -0
  198. data/sig/plugins/proxy/socks4.rbs +9 -6
  199. data/sig/plugins/proxy/socks5.rbs +10 -6
  200. data/sig/plugins/proxy/ssh.rbs +1 -1
  201. data/sig/plugins/proxy.rbs +13 -5
  202. data/sig/plugins/push_promise.rbs +3 -3
  203. data/sig/plugins/rate_limiter.rbs +1 -1
  204. data/sig/plugins/response_cache.rbs +36 -7
  205. data/sig/plugins/retries.rbs +30 -8
  206. data/sig/plugins/stream.rbs +24 -17
  207. data/sig/plugins/upgrade.rbs +5 -3
  208. data/sig/pool.rbs +10 -7
  209. data/sig/request/body.rbs +38 -0
  210. data/sig/request.rbs +15 -24
  211. data/sig/resolver/https.rbs +8 -3
  212. data/sig/resolver/native.rbs +17 -4
  213. data/sig/resolver/resolver.rbs +8 -6
  214. data/sig/resolver/system.rbs +2 -0
  215. data/sig/resolver.rbs +9 -5
  216. data/sig/response/body.rbs +53 -0
  217. data/sig/response/buffer.rbs +24 -0
  218. data/sig/response.rbs +24 -39
  219. data/sig/selector.rbs +1 -1
  220. data/sig/session.rbs +29 -18
  221. data/sig/timers.rbs +18 -8
  222. data/sig/transcoder/body.rbs +4 -3
  223. data/sig/transcoder/deflate.rbs +11 -0
  224. data/sig/transcoder/form.rbs +5 -3
  225. data/sig/transcoder/gzip.rbs +24 -0
  226. data/sig/transcoder/json.rbs +8 -3
  227. data/sig/{plugins → transcoder}/multipart.rbs +15 -19
  228. data/sig/transcoder/utils/body_reader.rbs +15 -0
  229. data/sig/transcoder/utils/deflater.rbs +29 -0
  230. data/sig/transcoder/utils/inflater.rbs +12 -0
  231. data/sig/transcoder/xml.rbs +22 -0
  232. data/sig/transcoder.rbs +24 -9
  233. data/sig/utils.rbs +8 -2
  234. metadata +163 -41
  235. data/lib/httpx/plugins/authentication.rb +0 -20
  236. data/lib/httpx/plugins/basic_authentication.rb +0 -30
  237. data/lib/httpx/plugins/compression/brotli.rb +0 -54
  238. data/lib/httpx/plugins/compression/deflate.rb +0 -49
  239. data/lib/httpx/plugins/compression/gzip.rb +0 -88
  240. data/lib/httpx/plugins/compression.rb +0 -164
  241. data/lib/httpx/plugins/multipart/decoder.rb +0 -187
  242. data/lib/httpx/plugins/multipart.rb +0 -84
  243. data/lib/httpx/registry.rb +0 -85
  244. data/sig/plugins/authentication.rbs +0 -11
  245. data/sig/plugins/compression/brotli.rbs +0 -21
  246. data/sig/plugins/compression/deflate.rbs +0 -17
  247. data/sig/plugins/compression/gzip.rbs +0 -29
  248. data/sig/registry.rbs +0 -12
  249. /data/sig/plugins/{authentication → auth}/ntlm.rbs +0 -0
  250. /data/sig/plugins/{authentication → auth}/socks5.rbs +0 -0
@@ -0,0 +1,18 @@
1
+ # 1.3.0
2
+
3
+ ## Dependencies
4
+
5
+ `http-2` v1.0.0 is replacing `http-2-next` as the HTTP/2 parser.
6
+
7
+ `http-2-next` was forked from `http-2` 5 years ago; its improvements have been merged back to `http-2` recently though, so `http-2-next` willl therefore no longer be maintained.
8
+
9
+ ## Improvements
10
+
11
+ Request-specific options (`:params`, `:form`, `:json` and `:xml`) are now separately kept by the request, which allows them to share `HTTPX::Options`, and reduce the number of copying / allocations.
12
+
13
+ This means that `HTTPX::Options` will throw an error if you initialize an object which such keys; this should not happen, as this class is considered internal and you should not be using it directly.
14
+
15
+ ## Fixes
16
+
17
+ * support for the `datadog` gem v2.0.0 in its adapter has been unblocked, now that the gem has been released.
18
+ * loading the `:cookies` plugin was making the `Session#build_request` private.
@@ -0,0 +1,17 @@
1
+ # 1.3.1
2
+
3
+ ## Improvements
4
+
5
+ * `:request_timeout` will be applied to all HTTP interactions until the final responses returned to the caller. That includes:
6
+ * all redirect requests/responses (when using the `:follow_redirects` plugin)
7
+ * all retried requests/responses (when using the `:retries` plugin)
8
+ * intermediate requests (such as "100-continue")
9
+ * faraday adapter: allow further plugins of internal session (ex: `builder.adapter(:httpx) { |sess| sess.plugin(:follow_redirects) }...`)
10
+
11
+ ## Bugfixes
12
+
13
+ * fix connection leak on proxy auth failed (407) handling
14
+ * fix busy loop on deferred requests for the duration interval
15
+ * do not further enqueue deferred requests if they have terminated meanwhile.
16
+ * fix busy loop caused by coalescing connections when one of them is on the DNS resolution phase still.
17
+ * faraday adapter: on parallel mode, skip calling `on_complete` when not defined.
@@ -1,57 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- if defined?(::DDTrace) && ::DDTrace::VERSION::STRING >= "1.0.0"
4
- require "datadog/tracing/contrib/integration"
5
- require "datadog/tracing/contrib/configuration/settings"
6
- require "datadog/tracing/contrib/patcher"
3
+ require "datadog/tracing/contrib/integration"
4
+ require "datadog/tracing/contrib/configuration/settings"
5
+ require "datadog/tracing/contrib/patcher"
7
6
 
8
- TRACING_MODULE = Datadog::Tracing
9
- else
10
-
11
- require "ddtrace/contrib/integration"
12
- require "ddtrace/contrib/configuration/settings"
13
- require "ddtrace/contrib/patcher"
14
-
15
- TRACING_MODULE = Datadog
16
- end
17
-
18
- module TRACING_MODULE # rubocop:disable Naming/ClassAndModuleCamelCase
7
+ module Datadog::Tracing
19
8
  module Contrib
20
9
  module HTTPX
21
- if defined?(::DDTrace) && ::DDTrace::VERSION::STRING >= "1.0.0"
22
- METADATA_MODULE = TRACING_MODULE::Metadata
23
-
24
- TYPE_OUTBOUND = TRACING_MODULE::Metadata::Ext::HTTP::TYPE_OUTBOUND
25
-
26
- TAG_PEER_SERVICE = TRACING_MODULE::Metadata::Ext::TAG_PEER_SERVICE
10
+ DATADOG_VERSION = defined?(::DDTrace) ? ::DDTrace::VERSION : ::Datadog::VERSION
27
11
 
28
- TAG_URL = TRACING_MODULE::Metadata::Ext::HTTP::TAG_URL
29
- TAG_METHOD = TRACING_MODULE::Metadata::Ext::HTTP::TAG_METHOD
30
- TAG_TARGET_HOST = TRACING_MODULE::Metadata::Ext::NET::TAG_TARGET_HOST
31
- TAG_TARGET_PORT = TRACING_MODULE::Metadata::Ext::NET::TAG_TARGET_PORT
12
+ METADATA_MODULE = Datadog::Tracing::Metadata
32
13
 
33
- TAG_STATUS_CODE = TRACING_MODULE::Metadata::Ext::HTTP::TAG_STATUS_CODE
14
+ TYPE_OUTBOUND = Datadog::Tracing::Metadata::Ext::HTTP::TYPE_OUTBOUND
34
15
 
35
- else
16
+ TAG_PEER_SERVICE = Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE
36
17
 
37
- METADATA_MODULE = Datadog
18
+ TAG_URL = Datadog::Tracing::Metadata::Ext::HTTP::TAG_URL
19
+ TAG_METHOD = Datadog::Tracing::Metadata::Ext::HTTP::TAG_METHOD
20
+ TAG_TARGET_HOST = Datadog::Tracing::Metadata::Ext::NET::TAG_TARGET_HOST
21
+ TAG_TARGET_PORT = Datadog::Tracing::Metadata::Ext::NET::TAG_TARGET_PORT
38
22
 
39
- TYPE_OUTBOUND = TRACING_MODULE::Ext::HTTP::TYPE_OUTBOUND
40
- TAG_PEER_SERVICE = TRACING_MODULE::Ext::Integration::TAG_PEER_SERVICE
41
- TAG_URL = TRACING_MODULE::Ext::HTTP::URL
42
- TAG_METHOD = TRACING_MODULE::Ext::HTTP::METHOD
43
- TAG_TARGET_HOST = TRACING_MODULE::Ext::NET::TARGET_HOST
44
- TAG_TARGET_PORT = TRACING_MODULE::Ext::NET::TARGET_PORT
45
- TAG_STATUS_CODE = Datadog::Ext::HTTP::STATUS_CODE
46
- PROPAGATOR = TRACING_MODULE::HTTPPropagator
47
-
48
- end
23
+ TAG_STATUS_CODE = Datadog::Tracing::Metadata::Ext::HTTP::TAG_STATUS_CODE
49
24
 
50
25
  # HTTPX Datadog Plugin
51
26
  #
52
- # Enables tracing for httpx requests. A span will be created for each individual requests,
53
- # and it'll trace since the moment it is fed to the connection, until the moment the response is
54
- # fed back to the session.
27
+ # Enables tracing for httpx requests.
28
+ #
29
+ # A span will be created for each request transaction; the span is created lazily only when
30
+ # receiving a response, and it is fed the start time stored inside the tracer object.
55
31
  #
56
32
  module Plugin
57
33
  class RequestTracer
@@ -59,108 +35,179 @@ module TRACING_MODULE # rubocop:disable Naming/ClassAndModuleCamelCase
59
35
 
60
36
  SPAN_REQUEST = "httpx.request"
61
37
 
38
+ # initializes the tracer object on the +request+.
62
39
  def initialize(request)
63
40
  @request = request
41
+ @start_time = nil
42
+
43
+ # request objects are reused, when already buffered requests get rerouted to a different
44
+ # connection due to connection issues, or when they already got a response, but need to
45
+ # be retried. In such situations, the original span needs to be extended for the former,
46
+ # while a new is required for the latter.
47
+ request.on(:idle) { reset }
48
+ # the span is initialized when the request is buffered in the parser, which is the closest
49
+ # one gets to actually sending the request.
50
+ request.on(:headers) { call }
51
+ end
52
+
53
+ # sets up the span start time, while preparing the on response callback.
54
+ def call(*args)
55
+ return if @start_time
56
+
57
+ start(*args)
58
+
59
+ @request.once(:response, &method(:finish))
60
+ end
61
+
62
+ private
63
+
64
+ # just sets the span init time. It can be passed a +start_time+ in cases where
65
+ # this is collected outside the request transaction.
66
+ def start(start_time = now)
67
+ @start_time = start_time
64
68
  end
65
69
 
66
- def call
67
- return unless tracing_enabled?
70
+ # resets the start time for already finished request transactions.
71
+ def reset
72
+ return unless @start_time
73
+
74
+ start
75
+ end
76
+
77
+ # creates the span from the collected +@start_time+ to what the +response+ state
78
+ # contains. It also resets internal state to allow this object to be reused.
79
+ def finish(response)
80
+ return unless @start_time
81
+
82
+ span = initialize_span
68
83
 
69
- @request.on(:response, &method(:finish))
84
+ return unless span
70
85
 
71
- verb = @request.verb.to_s.upcase
86
+ if response.is_a?(::HTTPX::ErrorResponse)
87
+ span.set_error(response.error)
88
+ else
89
+ span.set_tag(TAG_STATUS_CODE, response.status.to_s)
90
+
91
+ span.set_error(::HTTPX::HTTPError.new(response)) if response.status >= 400 && response.status <= 599
92
+ end
93
+
94
+ span.finish
95
+ ensure
96
+ @start_time = nil
97
+ end
98
+
99
+ # return a span initialized with the +@request+ state.
100
+ def initialize_span
101
+ verb = @request.verb
72
102
  uri = @request.uri
73
103
 
74
- @span = build_span
104
+ span = create_span(@request)
75
105
 
76
- @span.resource = verb
106
+ span.resource = verb
77
107
 
78
108
  # Add additional request specific tags to the span.
79
109
 
80
- @span.set_tag(TAG_URL, @request.path)
81
- @span.set_tag(TAG_METHOD, verb)
110
+ span.set_tag(TAG_URL, @request.path)
111
+ span.set_tag(TAG_METHOD, verb)
82
112
 
83
- @span.set_tag(TAG_TARGET_HOST, uri.host)
84
- @span.set_tag(TAG_TARGET_PORT, uri.port.to_s)
113
+ span.set_tag(TAG_TARGET_HOST, uri.host)
114
+ span.set_tag(TAG_TARGET_PORT, uri.port.to_s)
85
115
 
86
116
  # Tag as an external peer service
87
- @span.set_tag(TAG_PEER_SERVICE, @span.service)
117
+ span.set_tag(TAG_PEER_SERVICE, span.service)
88
118
 
89
- propagate_headers if @configuration[:distributed_tracing]
119
+ if configuration[:distributed_tracing]
120
+ propagate_trace_http(
121
+ Datadog::Tracing.active_trace.to_digest,
122
+ @request.headers
123
+ )
124
+ end
90
125
 
91
126
  # Set analytics sample rate
92
- if Contrib::Analytics.enabled?(@configuration[:analytics_enabled])
93
- Contrib::Analytics.set_sample_rate(@span, @configuration[:analytics_sample_rate])
127
+ if Contrib::Analytics.enabled?(configuration[:analytics_enabled])
128
+ Contrib::Analytics.set_sample_rate(span, configuration[:analytics_sample_rate])
94
129
  end
130
+
131
+ span
95
132
  rescue StandardError => e
96
133
  Datadog.logger.error("error preparing span for http request: #{e}")
97
134
  Datadog.logger.error(e.backtrace)
98
135
  end
99
136
 
100
- def finish(response)
101
- return unless @span
102
-
103
- if response.is_a?(::HTTPX::ErrorResponse)
104
- @span.set_error(response.error)
105
- else
106
- @span.set_tag(TAG_STATUS_CODE, response.status.to_s)
107
-
108
- @span.set_error(::HTTPX::HTTPError.new(response)) if response.status >= 400 && response.status <= 599
109
- end
110
-
111
- @span.finish
137
+ def now
138
+ ::Datadog::Core::Utils::Time.now.utc
112
139
  end
113
140
 
114
- private
141
+ def configuration
142
+ @configuration ||= Datadog.configuration.tracing[:httpx, @request.uri.host]
143
+ end
115
144
 
116
- if defined?(::DDTrace) && ::DDTrace::VERSION::STRING >= "1.0.0"
145
+ if Gem::Version.new(DATADOG_VERSION::STRING) >= Gem::Version.new("2.0.0")
146
+ def propagate_trace_http(digest, headers)
147
+ Datadog::Tracing::Contrib::HTTP.inject(digest, headers)
148
+ end
117
149
 
118
- def build_span
119
- TRACING_MODULE.trace(
150
+ def create_span(request)
151
+ Datadog::Tracing.trace(
120
152
  SPAN_REQUEST,
121
- service: service_name(@request.uri.host, configuration, Datadog.configuration_for(self)),
122
- span_type: TYPE_OUTBOUND
153
+ service: service_name(request.uri.host, configuration, Datadog.configuration_for(self)),
154
+ type: TYPE_OUTBOUND,
155
+ start_time: @start_time
123
156
  )
124
157
  end
125
-
126
- def propagate_headers
127
- TRACING_MODULE::Propagation::HTTP.inject!(TRACING_MODULE.active_trace, @request.headers)
128
- end
129
-
130
- def configuration
131
- @configuration ||= Datadog.configuration.tracing[:httpx, @request.uri.host]
158
+ else
159
+ def propagate_trace_http(digest, headers)
160
+ Datadog::Tracing::Propagation::HTTP.inject!(digest, headers)
132
161
  end
133
162
 
134
- def tracing_enabled?
135
- TRACING_MODULE.enabled?
136
- end
137
- else
138
- def build_span
139
- service_name = configuration[:split_by_domain] ? @request.uri.host : configuration[:service_name]
140
- configuration[:tracer].trace(
163
+ def create_span(request)
164
+ Datadog::Tracing.trace(
141
165
  SPAN_REQUEST,
142
- service: service_name,
143
- span_type: TYPE_OUTBOUND
166
+ service: service_name(request.uri.host, configuration, Datadog.configuration_for(self)),
167
+ span_type: TYPE_OUTBOUND,
168
+ start_time: @start_time
144
169
  )
145
170
  end
171
+ end
172
+ end
146
173
 
147
- def propagate_headers
148
- Datadog::HTTPPropagator.inject!(@span.context, @request.headers)
149
- end
174
+ module RequestMethods
175
+ # intercepts request initialization to inject the tracing logic.
176
+ def initialize(*)
177
+ super
150
178
 
151
- def configuration
152
- @configuration ||= Datadog.configuration[:httpx, @request.uri.host]
153
- end
179
+ return unless Datadog::Tracing.enabled?
154
180
 
155
- def tracing_enabled?
156
- configuration[:tracer].enabled
157
- end
181
+ RequestTracer.new(self)
158
182
  end
159
183
  end
160
184
 
161
185
  module ConnectionMethods
162
- def send(request)
163
- RequestTracer.new(request).call
186
+ attr_reader :init_time
187
+
188
+ def initialize(*)
189
+ super
190
+
191
+ @init_time = ::Datadog::Core::Utils::Time.now.utc
192
+ end
193
+
194
+ # handles the case when the +error+ happened during name resolution, which meanns
195
+ # that the tracing logic hasn't been injected yet; in such cases, the approximate
196
+ # initial resolving time is collected from the connection, and used as span start time,
197
+ # and the tracing object in inserted before the on response callback is called.
198
+ def handle_error(error, request = nil)
199
+ return super unless Datadog::Tracing.enabled?
200
+
201
+ return super unless error.respond_to?(:connection)
202
+
203
+ @pending.each do |req|
204
+ next if request and request == req
205
+
206
+ RequestTracer.new(req).call(error.connection.init_time)
207
+ end
208
+
209
+ RequestTracer.new(request).call(error.connection.init_time) if request
210
+
164
211
  super
165
212
  end
166
213
  end
@@ -169,7 +216,7 @@ module TRACING_MODULE # rubocop:disable Naming/ClassAndModuleCamelCase
169
216
  module Configuration
170
217
  # Default settings for httpx
171
218
  #
172
- class Settings < TRACING_MODULE::Contrib::Configuration::Settings
219
+ class Settings < Datadog::Tracing::Contrib::Configuration::Settings
173
220
  DEFAULT_ERROR_HANDLER = lambda do |response|
174
221
  Datadog::Ext::HTTP::ERROR_RANGE.cover?(response.status)
175
222
  end
@@ -178,29 +225,82 @@ module TRACING_MODULE # rubocop:disable Naming/ClassAndModuleCamelCase
178
225
  option :distributed_tracing, default: true
179
226
  option :split_by_domain, default: false
180
227
 
181
- option :enabled do |o|
182
- o.default { env_to_bool("DD_TRACE_HTTPX_ENABLED", true) }
183
- o.lazy
184
- end
228
+ if Gem::Version.new(DATADOG_VERSION::STRING) >= Gem::Version.new("1.13.0")
229
+ option :enabled do |o|
230
+ o.type :bool
231
+ o.env "DD_TRACE_HTTPX_ENABLED"
232
+ o.default true
233
+ end
234
+
235
+ option :analytics_enabled do |o|
236
+ o.type :bool
237
+ o.env "DD_TRACE_HTTPX_ANALYTICS_ENABLED"
238
+ o.default false
239
+ end
185
240
 
186
- option :analytics_enabled do |o|
187
- o.default { env_to_bool(%w[DD_TRACE_HTTPX_ANALYTICS_ENABLED DD_HTTPX_ANALYTICS_ENABLED], false) }
188
- o.lazy
241
+ option :analytics_sample_rate do |o|
242
+ o.type :float
243
+ o.env "DD_TRACE_HTTPX_ANALYTICS_SAMPLE_RATE"
244
+ o.default 1.0
245
+ end
246
+ else
247
+ option :enabled do |o|
248
+ o.default { env_to_bool("DD_TRACE_HTTPX_ENABLED", true) }
249
+ o.lazy
250
+ end
251
+
252
+ option :analytics_enabled do |o|
253
+ o.default { env_to_bool(%w[DD_TRACE_HTTPX_ANALYTICS_ENABLED DD_HTTPX_ANALYTICS_ENABLED], false) }
254
+ o.lazy
255
+ end
256
+
257
+ option :analytics_sample_rate do |o|
258
+ o.default { env_to_float(%w[DD_TRACE_HTTPX_ANALYTICS_SAMPLE_RATE DD_HTTPX_ANALYTICS_SAMPLE_RATE], 1.0) }
259
+ o.lazy
260
+ end
189
261
  end
190
262
 
191
- option :analytics_sample_rate do |o|
192
- o.default { env_to_float(%w[DD_TRACE_HTTPX_ANALYTICS_SAMPLE_RATE DD_HTTPX_ANALYTICS_SAMPLE_RATE], 1.0) }
193
- o.lazy
263
+ if defined?(Datadog::Tracing::Contrib::SpanAttributeSchema)
264
+ option :service_name do |o|
265
+ o.default do
266
+ Datadog::Tracing::Contrib::SpanAttributeSchema.fetch_service_name(
267
+ "DD_TRACE_HTTPX_SERVICE_NAME",
268
+ "httpx"
269
+ )
270
+ end
271
+ o.lazy unless Gem::Version.new(DATADOG_VERSION::STRING) >= Gem::Version.new("1.13.0")
272
+ end
273
+ else
274
+ option :service_name do |o|
275
+ o.default do
276
+ ENV.fetch("DD_TRACE_HTTPX_SERVICE_NAME", "httpx")
277
+ end
278
+ o.lazy unless Gem::Version.new(DATADOG_VERSION::STRING) >= Gem::Version.new("1.13.0")
279
+ end
194
280
  end
195
281
 
196
- option :error_handler, default: DEFAULT_ERROR_HANDLER
282
+ option :distributed_tracing, default: true
283
+
284
+ if Gem::Version.new(DATADOG_VERSION::STRING) >= Gem::Version.new("1.15.0")
285
+ option :error_handler do |o|
286
+ o.type :proc
287
+ o.default_proc(&DEFAULT_ERROR_HANDLER)
288
+ end
289
+ elsif Gem::Version.new(DATADOG_VERSION::STRING) >= Gem::Version.new("1.13.0")
290
+ option :error_handler do |o|
291
+ o.type :proc
292
+ o.experimental_default_proc(&DEFAULT_ERROR_HANDLER)
293
+ end
294
+ else
295
+ option :error_handler, default: DEFAULT_ERROR_HANDLER
296
+ end
197
297
  end
198
298
  end
199
299
 
200
300
  # Patcher enables patching of 'httpx' with datadog components.
201
301
  #
202
302
  module Patcher
203
- include TRACING_MODULE::Contrib::Patcher
303
+ include Datadog::Tracing::Contrib::Patcher
204
304
 
205
305
  module_function
206
306
 
@@ -223,7 +323,6 @@ module TRACING_MODULE # rubocop:disable Naming/ClassAndModuleCamelCase
223
323
  class Integration
224
324
  include Contrib::Integration
225
325
 
226
- # MINIMUM_VERSION = Gem::Version.new('0.11.0')
227
326
  MINIMUM_VERSION = Gem::Version.new("0.10.2")
228
327
 
229
328
  register_as :httpx
@@ -240,14 +339,8 @@ module TRACING_MODULE # rubocop:disable Naming/ClassAndModuleCamelCase
240
339
  super && version >= MINIMUM_VERSION
241
340
  end
242
341
 
243
- if defined?(::DDTrace) && ::DDTrace::VERSION::STRING >= "1.0.0"
244
- def new_configuration
245
- Configuration::Settings.new
246
- end
247
- else
248
- def default_configuration
249
- Configuration::Settings.new
250
- end
342
+ def new_configuration
343
+ Configuration::Settings.new
251
344
  end
252
345
 
253
346
  def patcher