http_instrumentation 1.0.1 → 1.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/README.md +15 -1
- data/VERSION +1 -1
- data/http_instrumentation.gemspec +1 -1
- data/lib/http_instrumentation/instrumentation/ethon_hook.rb +11 -2
- data/lib/http_instrumentation/instrumentation/excon_hook.rb +9 -5
- data/lib/http_instrumentation/instrumentation/httpclient_hook.rb +2 -2
- data/lib/http_instrumentation/instrumentation/net_http_hook.rb +11 -6
- data/lib/http_instrumentation/instrumentation.rb +47 -20
- data/lib/http_instrumentation.rb +34 -23
- metadata +4 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2deee15a4609f8d50a706613af0805d53bc54beaf3e17f65b68f17c17453fed9
|
|
4
|
+
data.tar.gz: a3a76bc88fe4a5b799b59a807ac665dcd4b6f52f280236f7b8b804425a01846f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 932361a2de24b64de68929b61379e1d8f01acce64f3f03070070ccfb9da8a369329c7703f84f774e236c69a2343dde4c5a6add5fd21add2db9025cdde3515a7b
|
|
7
|
+
data.tar.gz: fa77a297e489a26894c6f49961a5f057bfb239385a93d96b0252892db411922e9e2c75d0abb9de663fe059d883d9e07f06a043ae27b7704a4e868c97a49d4eb8
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,27 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## 1.0.2
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- Requiring the gem now loads the ActiveSupport framework itself instead of just `active_support/notifications`, which is not self-sufficient on ActiveSupport 7+ and raised `NameError: uninitialized constant ActiveSupport::IsolatedExecutionState` on the first request if the host application had not already loaded ActiveSupport.
|
|
11
|
+
- The httpclient and excon instrumentation now forward blocks passed to the instrumented methods, so streaming response blocks are no longer silently ignored when the aliasing strategy is used.
|
|
12
|
+
- The excon instrumentation now encodes query parameters passed as a hash when building the URL for the event payload, so `access_token` parameters are properly stripped from the `:uri` payload value instead of leaking through in unparseable form.
|
|
13
|
+
- The aliased flag on instrumentation modules is now set before the instrumented method is swapped in, so a request on another thread can no longer hit a window during installation where it would raise `NoMethodError`.
|
|
14
|
+
- Removed the nonexistent `:net_http2` entry from `HTTPInstrumentation::IMPLEMENTATIONS`; no hook for it was ever implemented.
|
|
15
|
+
- `HTTPInstrumentation.initialize!` now accepts a single symbol for the `only` option instead of raising `NoMethodError`.
|
|
16
|
+
- The `except` option to `HTTPInstrumentation.initialize!` now excludes the listed libraries instead of instrumenting only those libraries.
|
|
17
|
+
- Requests made with relative URLs (e.g. a patron session with a `base_url`) no longer raise `URI::InvalidURIError` from the instrumentation after the request completes.
|
|
18
|
+
- Installing the instrumentation is now protected by a mutex so concurrent calls to `initialize!` cannot install the aliased methods twice, which would have caused infinite recursion on subsequent requests.
|
|
19
|
+
- The excon instrumentation now reports per-request values (path, query, etc.) instead of letting the connection's defaults override them in the event payload.
|
|
20
|
+
- The event payload now always includes the `:count` key even when the request raises an error.
|
|
21
|
+
- The net/http instrumentation no longer lets an error raised while building the event payload escape to the caller, matching the behavior of the other hooks.
|
|
22
|
+
- The ethon instrumentation clears the request info captured from `http_request` after each `perform`, so reusing an easy handle without going through `http_request` no longer reports the previous request's method and URL. The URL set directly on the handle is now also reported as a fallback.
|
|
23
|
+
- The `:url` payload value no longer includes an explicit port for URLs using the default port for their scheme.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
- The minimum required Ruby version has been updated to 2.6.
|
|
27
|
+
|
|
7
28
|
## 1.0.1
|
|
8
29
|
|
|
9
30
|
### Fixed
|
data/README.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/bdurand/http_instrumentation/actions/workflows/continuous_integration.yml)
|
|
4
4
|
[](https://github.com/testdouble/standard)
|
|
5
|
+
[](https://badge.fury.io/rb/http_instrumentation)
|
|
5
6
|
|
|
6
7
|
This gem adds instrumentation to a variety of the most commonly used Ruby HTTP client libraries via ActiveSupport notifications. The goal is to add a common instrumentation interface across all the HTTP client libraries used by an application (including ones installed as dependencies of other gems).
|
|
7
8
|
|
|
@@ -19,6 +20,8 @@ This gem adds instrumentation to a variety of the most commonly used Ruby HTTP c
|
|
|
19
20
|
|
|
20
21
|
Note that several other popular HTTP client libraries like [Faraday](https://github.com/lostisland/faraday), [HTTParty](https://github.com/jnunemaker/httparty), and [RestClient](https://github.com/rest-client/rest-client) are built on top of these low level libraries.
|
|
21
22
|
|
|
23
|
+
A few code paths are not instrumented: curb requests that don't go through `Curl::Easy#http` (e.g. the native `http_get` and `http_post` helpers) and httpclient streaming responses.
|
|
24
|
+
|
|
22
25
|
## Usage
|
|
23
26
|
|
|
24
27
|
To capture information about HTTP requests, simply subscribe to the `request.http` events with [ActiveSupport notifications](https://api.rubyonrails.org/classes/ActiveSupport/Notifications.html) (note that you should really use `monotonic_subscribe` instead of `subscribe` to avoid issues with clock adjustments).
|
|
@@ -63,6 +66,17 @@ HTTPX.get("https://example.com/r1", "https://example.com/r2")
|
|
|
63
66
|
# => HTTP request: client: httpx, count: 2, duration: 150ms
|
|
64
67
|
```
|
|
65
68
|
|
|
69
|
+
### Instrumenting Libraries Loaded Later
|
|
70
|
+
|
|
71
|
+
All supported libraries that have already been loaded are automatically instrumented when this gem is required. Instrumentation cannot be removed once it has been installed.
|
|
72
|
+
|
|
73
|
+
If an HTTP client library is loaded after this gem, you can call `HTTPInstrumentation.initialize!` again to instrument it. The `only` and `except` options can be used to limit which libraries are instrumented.
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
require "httpx"
|
|
77
|
+
HTTPInstrumentation.initialize!(only: [:httpx])
|
|
78
|
+
```
|
|
79
|
+
|
|
66
80
|
### Security
|
|
67
81
|
|
|
68
82
|
The `:uri` element in the event payload will be sanitized to remove any user/password elements encoded in the URL as well as any `access_token` query parameters.
|
|
@@ -115,7 +129,7 @@ You can also take advantage of the existing instrumentation and just override th
|
|
|
115
129
|
```ruby
|
|
116
130
|
class MyHttpClient
|
|
117
131
|
def get(url)
|
|
118
|
-
HTTPInstrumentation.client("my_client")
|
|
132
|
+
HTTPInstrumentation.client("my_client") do
|
|
119
133
|
Net::HTTP.get(URI(url))
|
|
120
134
|
end
|
|
121
135
|
end
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.2
|
|
@@ -61,14 +61,23 @@ module HTTPInstrumentation
|
|
|
61
61
|
|
|
62
62
|
def perform(*args)
|
|
63
63
|
HTTPInstrumentation.instrument("ethon") do |payload|
|
|
64
|
+
payload[:http_method] = @http_instrumentation_method
|
|
65
|
+
begin
|
|
66
|
+
payload[:url] = (@http_instrumentation_url || url)
|
|
67
|
+
rescue
|
|
68
|
+
payload[:url] = @http_instrumentation_url
|
|
69
|
+
end
|
|
70
|
+
# Clear the request info so it isn't reported again if the handle
|
|
71
|
+
# is reused without going through http_request.
|
|
72
|
+
@http_instrumentation_method = nil
|
|
73
|
+
@http_instrumentation_url = nil
|
|
74
|
+
|
|
64
75
|
retval = if HTTPInstrumentation::Instrumentation::EthonHook::Easy.aliased
|
|
65
76
|
perform_without_http_instrumentation(*args)
|
|
66
77
|
else
|
|
67
78
|
super
|
|
68
79
|
end
|
|
69
80
|
|
|
70
|
-
payload[:http_method] = @http_instrumentation_method
|
|
71
|
-
payload[:url] = @http_instrumentation_url
|
|
72
81
|
begin
|
|
73
82
|
payload[:status_code] = response_code
|
|
74
83
|
rescue
|
|
@@ -21,27 +21,31 @@ module HTTPInstrumentation
|
|
|
21
21
|
attr_accessor :aliased
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
def request(params = {})
|
|
24
|
+
def request(params = {}, &block)
|
|
25
25
|
HTTPInstrumentation.instrument("excon") do |payload|
|
|
26
26
|
response = if HTTPInstrumentation::Instrumentation::ExconHook.aliased
|
|
27
|
-
request_without_http_instrumentation(params)
|
|
27
|
+
request_without_http_instrumentation(params, &block)
|
|
28
28
|
else
|
|
29
29
|
super
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
begin
|
|
33
33
|
info = params
|
|
34
|
+
# Merge connection defaults under the per-request params so the
|
|
35
|
+
# request values win.
|
|
34
36
|
if respond_to?(:connection)
|
|
35
|
-
info =
|
|
37
|
+
info = connection.merge(params)
|
|
36
38
|
elsif respond_to?(:data)
|
|
37
|
-
info =
|
|
39
|
+
info = data.merge(params)
|
|
38
40
|
end
|
|
39
41
|
|
|
40
42
|
scheme = info[:scheme]&.downcase
|
|
41
43
|
default_port = ((scheme == "https") ? 443 : 80)
|
|
42
44
|
port = info[:port]
|
|
45
|
+
query = info[:query]
|
|
46
|
+
query = URI.encode_www_form(query) if query.is_a?(Hash)
|
|
43
47
|
payload[:http_method] = (info[:http_method] || info[:method])
|
|
44
|
-
payload[:url] = "#{scheme}://#{info[:host]}#{":#{port}" unless port == default_port}#{info[:path]}#{"?#{
|
|
48
|
+
payload[:url] = "#{scheme}://#{info[:host]}#{":#{port}" unless port == default_port}#{info[:path]}#{"?#{query}" unless query.to_s.empty?}"
|
|
45
49
|
payload[:status_code] = response.status
|
|
46
50
|
rescue
|
|
47
51
|
end
|
|
@@ -21,10 +21,10 @@ module HTTPInstrumentation
|
|
|
21
21
|
attr_accessor :aliased
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
def do_get_block(request, *args)
|
|
24
|
+
def do_get_block(request, *args, &block)
|
|
25
25
|
HTTPInstrumentation.instrument("httpclient") do |payload|
|
|
26
26
|
response = if HTTPInstrumentation::Instrumentation::HTTPClientHook.aliased
|
|
27
|
-
do_get_block_without_http_instrumentation(request, *args)
|
|
27
|
+
do_get_block_without_http_instrumentation(request, *args, &block)
|
|
28
28
|
else
|
|
29
29
|
super
|
|
30
30
|
end
|
|
@@ -37,12 +37,17 @@ module HTTPInstrumentation
|
|
|
37
37
|
super
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
begin
|
|
41
|
+
default_port = (use_ssl? ? 443 : 80)
|
|
42
|
+
scheme = (use_ssl? ? "https" : "http")
|
|
43
|
+
url = "#{scheme}://#{address}#{":#{port}" unless port == default_port}#{req.path}"
|
|
44
|
+
payload[:http_method] = req.method
|
|
45
|
+
payload[:url] = url
|
|
46
|
+
payload[:status_code] = response.code
|
|
47
|
+
rescue
|
|
48
|
+
# Instrumentation must never break the request; if the payload can't
|
|
49
|
+
# be built, return the response without the extra fields.
|
|
50
|
+
end
|
|
46
51
|
|
|
47
52
|
response
|
|
48
53
|
end
|
|
@@ -12,6 +12,12 @@ require_relative "instrumentation/typhoeus_hook"
|
|
|
12
12
|
|
|
13
13
|
module HTTPInstrumentation
|
|
14
14
|
module Instrumentation
|
|
15
|
+
# Lock to prevent concurrent calls from installing the same hooks twice;
|
|
16
|
+
# double aliasing would point the _without_http_instrumentation method at
|
|
17
|
+
# the instrumented method itself, causing infinite recursion.
|
|
18
|
+
INSTRUMENT_LOCK = Mutex.new
|
|
19
|
+
private_constant :INSTRUMENT_LOCK
|
|
20
|
+
|
|
15
21
|
class << self
|
|
16
22
|
# Helper method to add an instrumentation module to methods on a class. The
|
|
17
23
|
# methods must be defined in the instrumentation module.
|
|
@@ -23,43 +29,64 @@ module HTTPInstrumentation
|
|
|
23
29
|
# may have already prepended the methods. Aliasing is the default strategy because
|
|
24
30
|
# prepending after aliasing will work, but aliasing after prepending will not.
|
|
25
31
|
def instrument!(klass, instrumentation_module, methods)
|
|
26
|
-
|
|
32
|
+
INSTRUMENT_LOCK.synchronize do
|
|
33
|
+
return if klass.include?(instrumentation_module)
|
|
27
34
|
|
|
28
|
-
|
|
35
|
+
methods = Array(methods).collect(&:to_sym)
|
|
29
36
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
if HTTPInstrumentation.force_prepend? || methods_defined_in_module?(klass, methods)
|
|
38
|
+
klass.prepend(instrumentation_module)
|
|
39
|
+
instrumentation_module.aliased = false
|
|
40
|
+
else
|
|
41
|
+
methods.each do |method|
|
|
42
|
+
instrumentation_module.alias_method("#{method}_with_http_instrumentation", method)
|
|
43
|
+
end
|
|
37
44
|
|
|
38
|
-
|
|
45
|
+
klass.include(instrumentation_module)
|
|
39
46
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
swap_methods = methods.reject { |method| defines_method?(klass, "#{method}_without_http_instrumentation") }
|
|
48
|
+
|
|
49
|
+
swap_methods.each do |method|
|
|
50
|
+
klass.alias_method("#{method}_without_http_instrumentation", method)
|
|
51
|
+
end
|
|
44
52
|
|
|
45
|
-
|
|
53
|
+
# The aliased flag must be set before the instrumented methods are
|
|
54
|
+
# swapped in; a call landing in between would take the super branch
|
|
55
|
+
# and raise NoMethodError since the module was included, not prepended.
|
|
56
|
+
instrumentation_module.aliased = true
|
|
57
|
+
|
|
58
|
+
swap_methods.each do |method|
|
|
59
|
+
klass.alias_method(method, "#{method}_with_http_instrumentation")
|
|
60
|
+
end
|
|
61
|
+
end
|
|
46
62
|
end
|
|
47
63
|
end
|
|
48
64
|
|
|
49
65
|
private
|
|
50
66
|
|
|
51
|
-
|
|
52
|
-
|
|
67
|
+
# Returns true if any of the methods are defined in a module in the class's
|
|
68
|
+
# ancestry rather than directly on the class itself. This covers both modules
|
|
69
|
+
# prepended in front of the class and modules included behind it. In either
|
|
70
|
+
# case the aliasing strategy cannot be used: including the instrumentation
|
|
71
|
+
# module would insert it ahead of the module that defines the method, so
|
|
72
|
+
# aliasing the method afterward would capture the instrumented method itself
|
|
73
|
+
# and cause infinite recursion.
|
|
74
|
+
def methods_defined_in_module?(klass, methods)
|
|
75
|
+
defined_in_module = false
|
|
53
76
|
|
|
54
77
|
klass.ancestors.each do |mod|
|
|
55
78
|
next unless mod.is_a?(Module) && !mod.is_a?(Class)
|
|
56
79
|
|
|
57
80
|
module_methods = mod.instance_methods(false) + mod.private_instance_methods(false)
|
|
58
|
-
|
|
59
|
-
break if
|
|
81
|
+
defined_in_module = (module_methods & methods).any?
|
|
82
|
+
break if defined_in_module
|
|
60
83
|
end
|
|
61
84
|
|
|
62
|
-
|
|
85
|
+
defined_in_module
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def defines_method?(klass, method)
|
|
89
|
+
klass.method_defined?(method) || klass.private_method_defined?(method)
|
|
63
90
|
end
|
|
64
91
|
end
|
|
65
92
|
end
|
data/lib/http_instrumentation.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "active_support"
|
|
3
4
|
require "active_support/notifications"
|
|
4
5
|
|
|
5
6
|
require_relative "http_instrumentation/instrumentation"
|
|
@@ -13,7 +14,6 @@ module HTTPInstrumentation
|
|
|
13
14
|
:httpclient,
|
|
14
15
|
:httpx,
|
|
15
16
|
:net_http,
|
|
16
|
-
:net_http2,
|
|
17
17
|
:patron,
|
|
18
18
|
:typhoeus
|
|
19
19
|
].freeze
|
|
@@ -29,8 +29,8 @@ module HTTPInstrumentation
|
|
|
29
29
|
# @param except [Array<Symbol>] List of libraries to not instrument.
|
|
30
30
|
# @return [void]
|
|
31
31
|
def initialize!(only: nil, except: nil)
|
|
32
|
-
list = (only || IMPLEMENTATIONS)
|
|
33
|
-
list
|
|
32
|
+
list = Array(only || IMPLEMENTATIONS)
|
|
33
|
+
list -= Array(except) if except
|
|
34
34
|
|
|
35
35
|
Instrumentation::CurbHook.instrument! if list.include?(:curb)
|
|
36
36
|
Instrumentation::EthonHook.instrument! if list.include?(:ethon)
|
|
@@ -45,6 +45,9 @@ module HTTPInstrumentation
|
|
|
45
45
|
|
|
46
46
|
# Silence instrumentation for the duration of the block.
|
|
47
47
|
#
|
|
48
|
+
# Note that silencing is stored in fiber-local storage, so it does not
|
|
49
|
+
# propagate into other threads or fibers spawned within the block.
|
|
50
|
+
#
|
|
48
51
|
# @return [Object] the return value of the block
|
|
49
52
|
def silence(&block)
|
|
50
53
|
save_val = Thread.current[:http_instrumentation_silence]
|
|
@@ -101,25 +104,7 @@ module HTTPInstrumentation
|
|
|
101
104
|
return yield(payload) if silenced?
|
|
102
105
|
|
|
103
106
|
ActiveSupport::Notifications.instrument(EVENT, payload) do
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
payload[:http_method] = normalize_http_method(payload[:http_method]) if payload.include?(:http_method)
|
|
107
|
-
|
|
108
|
-
if payload.include?(:url)
|
|
109
|
-
uri = sanitized_uri(payload[:url])
|
|
110
|
-
if uri
|
|
111
|
-
payload[:url] = uri_without_query_string(uri)
|
|
112
|
-
payload[:uri] = uri
|
|
113
|
-
else
|
|
114
|
-
payload[:url] = payload[:url]&.to_s
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
payload[:status_code] = payload[:status_code]&.to_i if payload.include?(:status_code)
|
|
119
|
-
|
|
120
|
-
payload[:count] = (payload.include?(:count) ? payload[:count].to_i : 1)
|
|
121
|
-
|
|
122
|
-
retval
|
|
107
|
+
instrument_request(payload, &block)
|
|
123
108
|
end
|
|
124
109
|
end
|
|
125
110
|
|
|
@@ -133,6 +118,29 @@ module HTTPInstrumentation
|
|
|
133
118
|
|
|
134
119
|
private
|
|
135
120
|
|
|
121
|
+
# Yield the block with instrumentation silenced and then normalize the
|
|
122
|
+
# payload. The payload is normalized even if the block raises an error so
|
|
123
|
+
# that events for failed requests still include the normalized keys.
|
|
124
|
+
def instrument_request(payload)
|
|
125
|
+
silence { yield(payload) }
|
|
126
|
+
ensure
|
|
127
|
+
payload[:http_method] = normalize_http_method(payload[:http_method]) if payload.include?(:http_method)
|
|
128
|
+
|
|
129
|
+
if payload.include?(:url)
|
|
130
|
+
uri = sanitized_uri(payload[:url])
|
|
131
|
+
if uri
|
|
132
|
+
payload[:url] = uri_without_query_string(uri)
|
|
133
|
+
payload[:uri] = uri
|
|
134
|
+
else
|
|
135
|
+
payload[:url] = payload[:url]&.to_s
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
payload[:status_code] = payload[:status_code]&.to_i if payload.include?(:status_code)
|
|
140
|
+
|
|
141
|
+
payload[:count] = (payload.include?(:count) ? payload[:count].to_i : 1)
|
|
142
|
+
end
|
|
143
|
+
|
|
136
144
|
# Turn the given value into a lowercase symbol.
|
|
137
145
|
def normalize_http_method(method)
|
|
138
146
|
return nil if method.nil?
|
|
@@ -171,7 +179,10 @@ module HTTPInstrumentation
|
|
|
171
179
|
end
|
|
172
180
|
|
|
173
181
|
def uri_without_query_string(uri)
|
|
174
|
-
|
|
182
|
+
stripped = uri.dup
|
|
183
|
+
stripped.query = nil if stripped.respond_to?(:query=)
|
|
184
|
+
stripped.fragment = nil if stripped.respond_to?(:fragment=)
|
|
185
|
+
stripped.to_s
|
|
175
186
|
end
|
|
176
187
|
end
|
|
177
188
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: http_instrumentation
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brian Durand
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: activesupport
|
|
@@ -38,7 +37,6 @@ dependencies:
|
|
|
38
37
|
- - ">="
|
|
39
38
|
- !ruby/object:Gem::Version
|
|
40
39
|
version: '0'
|
|
41
|
-
description:
|
|
42
40
|
email:
|
|
43
41
|
- bbdurand@gmail.com
|
|
44
42
|
executables: []
|
|
@@ -65,7 +63,6 @@ homepage: https://github.com/bdurand/http_instrumentation
|
|
|
65
63
|
licenses:
|
|
66
64
|
- MIT
|
|
67
65
|
metadata: {}
|
|
68
|
-
post_install_message:
|
|
69
66
|
rdoc_options: []
|
|
70
67
|
require_paths:
|
|
71
68
|
- lib
|
|
@@ -73,15 +70,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
73
70
|
requirements:
|
|
74
71
|
- - ">="
|
|
75
72
|
- !ruby/object:Gem::Version
|
|
76
|
-
version: '2.
|
|
73
|
+
version: '2.6'
|
|
77
74
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
75
|
requirements:
|
|
79
76
|
- - ">="
|
|
80
77
|
- !ruby/object:Gem::Version
|
|
81
78
|
version: '0'
|
|
82
79
|
requirements: []
|
|
83
|
-
rubygems_version:
|
|
84
|
-
signing_key:
|
|
80
|
+
rubygems_version: 4.0.3
|
|
85
81
|
specification_version: 4
|
|
86
82
|
summary: ActiveSupoprt instrumentation for a variety of Ruby HTTP client libraries.
|
|
87
83
|
test_files: []
|