opentelemetry-instrumentation-httpx 0.6.0 → 0.6.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -2
- data/lib/opentelemetry/instrumentation/httpx/dup/plugin.rb +81 -100
- data/lib/opentelemetry/instrumentation/httpx/instrumentation.rb +1 -1
- data/lib/opentelemetry/instrumentation/httpx/old/plugin.rb +70 -89
- data/lib/opentelemetry/instrumentation/httpx/plugin.rb +54 -0
- data/lib/opentelemetry/instrumentation/httpx/stable/plugin.rb +70 -89
- data/lib/opentelemetry/instrumentation/httpx/version.rb +1 -1
- metadata +6 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7f74f31524d99c5a0565edf84892292d068322376584c58b7dc4aabbdea724fd
|
|
4
|
+
data.tar.gz: 74cdecfb4c9c7a7e3fe0164ce3977d53e33d4fa96c140265629b401f1e0dce77
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7f78e75c32d2fd6df5635ffac615ff7fdf7ff987b9ad93970d32d171887184ca2652f081569d843705dd45f715c6a08a592ef461186f02b1c610045a5ffabe11
|
|
7
|
+
data.tar.gz: efa536643cab0d4d878acb262d62ab2936bb0ce82e70368d2bd7c6367a2781afe327eedfaafb08fa6df1e5f4cb91eb63763008f416698b1130d8b834902e57df
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Release History: opentelemetry-instrumentation-httpx
|
|
2
2
|
|
|
3
|
+
### v0.6.1 / 2026-02-27
|
|
4
|
+
|
|
5
|
+
* FIXED: Httpx support to ~> 1.6 adapt to request init_time (#2030)
|
|
6
|
+
|
|
3
7
|
### v0.6.0 / 2026-01-13
|
|
4
8
|
|
|
5
9
|
* ADDED: HTTP Client Semconv v1.17 Span Naming
|
|
@@ -11,7 +15,6 @@
|
|
|
11
15
|
### v0.5.0 / 2025-10-22
|
|
12
16
|
|
|
13
17
|
* BREAKING CHANGE: Min Ruby Version 3.2
|
|
14
|
-
|
|
15
18
|
* ADDED: Min Ruby Version 3.2
|
|
16
19
|
|
|
17
20
|
### v0.4.1 / 2025-09-30
|
|
@@ -33,7 +36,6 @@
|
|
|
33
36
|
### v0.2.0 / 2025-01-16
|
|
34
37
|
|
|
35
38
|
* BREAKING CHANGE: Set minimum supported version to Ruby 3.1
|
|
36
|
-
|
|
37
39
|
* ADDED: Set minimum supported version to Ruby 3.1
|
|
38
40
|
|
|
39
41
|
### v0.1.3 / 2024-11-26
|
|
@@ -8,126 +8,107 @@ module OpenTelemetry
|
|
|
8
8
|
module Instrumentation
|
|
9
9
|
module HTTPX
|
|
10
10
|
module Dup
|
|
11
|
+
# Dup Plugin
|
|
11
12
|
module Plugin
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
module_function
|
|
13
|
+
def self.load_dependencies(klass)
|
|
14
|
+
require_relative '../plugin'
|
|
15
|
+
klass.plugin(HTTPX::Plugin)
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
HTTPX::Plugin.const_set(:RequestTracer, RequestTracer)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
request.on(:idle) do
|
|
26
|
-
span = nil
|
|
27
|
-
end
|
|
28
|
-
# the span is initialized when the request is buffered in the parser, which is the closest
|
|
29
|
-
# one gets to actually sending the request.
|
|
30
|
-
request.on(:headers) do
|
|
31
|
-
next if span
|
|
21
|
+
# Instruments around HTTPX's request/response lifecycle in order to generate
|
|
22
|
+
# an OTEL trace.
|
|
23
|
+
module RequestTracer
|
|
24
|
+
extend self
|
|
32
25
|
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
# initializes tracing on the +request+.
|
|
27
|
+
def call(request)
|
|
28
|
+
span = nil
|
|
35
29
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
# request objects are reused, when already buffered requests get rerouted to a different
|
|
31
|
+
# connection due to connection issues, or when they already got a response, but need to
|
|
32
|
+
# be retried. In such situations, the original span needs to be extended for the former,
|
|
33
|
+
# while a new is required for the latter.
|
|
34
|
+
request.on(:idle) do
|
|
35
|
+
span = nil
|
|
36
|
+
end
|
|
37
|
+
# the span is initialized when the request is buffered in the parser, which is the closest
|
|
38
|
+
# one gets to actually sending the request.
|
|
39
|
+
request.on(:headers) do
|
|
40
|
+
next if span
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
# initial resolving time is collected from the connection, and used as span start time,
|
|
43
|
-
# and the tracing object in inserted before the on response callback is called.
|
|
44
|
-
span = initialize_span(request, response.error.connection.init_time)
|
|
42
|
+
span = initialize_span(request)
|
|
43
|
+
end
|
|
45
44
|
|
|
46
|
-
|
|
45
|
+
request.on(:response) do |response|
|
|
46
|
+
span = initialize_span(request, request.init_time) if !span && request.init_time
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
end
|
|
48
|
+
finish(response, span)
|
|
50
49
|
end
|
|
50
|
+
end
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
if response.is_a?(::HTTPX::ErrorResponse)
|
|
54
|
-
span.record_exception(response.error)
|
|
55
|
-
span.status = Trace::Status.error(response.error.to_s)
|
|
56
|
-
else
|
|
57
|
-
span.set_attribute(OpenTelemetry::SemanticConventions::Trace::HTTP_STATUS_CODE, response.status)
|
|
58
|
-
span.set_attribute('http.response.status_code', response.status)
|
|
59
|
-
|
|
60
|
-
if response.status.between?(400, 599)
|
|
61
|
-
err = ::HTTPX::HTTPError.new(response)
|
|
62
|
-
span.record_exception(err)
|
|
63
|
-
span.status = Trace::Status.error(err.to_s)
|
|
64
|
-
end
|
|
65
|
-
end
|
|
52
|
+
private
|
|
66
53
|
|
|
67
|
-
|
|
68
|
-
|
|
54
|
+
def finish(response, span)
|
|
55
|
+
if response.is_a?(::HTTPX::ErrorResponse)
|
|
56
|
+
span.record_exception(response.error)
|
|
57
|
+
span.status = Trace::Status.error(response.error.to_s)
|
|
58
|
+
else
|
|
59
|
+
span.set_attribute(OpenTelemetry::SemanticConventions::Trace::HTTP_STATUS_CODE, response.status)
|
|
60
|
+
span.set_attribute('http.response.status_code', response.status)
|
|
69
61
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
span_data = HttpHelper.span_attrs_for_dup(verb)
|
|
76
|
-
|
|
77
|
-
config = HTTPX::Instrumentation.instance.config
|
|
78
|
-
|
|
79
|
-
attributes = {
|
|
80
|
-
OpenTelemetry::SemanticConventions::Trace::HTTP_HOST => uri.host,
|
|
81
|
-
OpenTelemetry::SemanticConventions::Trace::HTTP_SCHEME => uri.scheme,
|
|
82
|
-
OpenTelemetry::SemanticConventions::Trace::HTTP_TARGET => uri.path,
|
|
83
|
-
OpenTelemetry::SemanticConventions::Trace::HTTP_URL => "#{uri.scheme}://#{uri.host}",
|
|
84
|
-
OpenTelemetry::SemanticConventions::Trace::NET_PEER_NAME => uri.host,
|
|
85
|
-
OpenTelemetry::SemanticConventions::Trace::NET_PEER_PORT => uri.port,
|
|
86
|
-
'url.scheme' => uri.scheme,
|
|
87
|
-
'url.path' => uri.path,
|
|
88
|
-
'url.full' => "#{uri.scheme}://#{uri.host}",
|
|
89
|
-
'server.address' => uri.host,
|
|
90
|
-
'server.port' => uri.port
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
attributes['url.query'] = uri.query unless uri.query.nil?
|
|
94
|
-
attributes[OpenTelemetry::SemanticConventions::Trace::PEER_SERVICE] = config[:peer_service] if config[:peer_service]
|
|
95
|
-
attributes.merge!(span_data.attributes)
|
|
96
|
-
|
|
97
|
-
span = tracer.start_span(span_data.span_name, attributes: attributes, kind: :client, start_timestamp: start_time)
|
|
98
|
-
|
|
99
|
-
OpenTelemetry::Trace.with_span(span) do
|
|
100
|
-
OpenTelemetry.propagation.inject(request.headers)
|
|
62
|
+
if response.status.between?(400, 599)
|
|
63
|
+
err = ::HTTPX::HTTPError.new(response)
|
|
64
|
+
span.record_exception(err)
|
|
65
|
+
span.status = Trace::Status.error(err.to_s)
|
|
101
66
|
end
|
|
102
|
-
|
|
103
|
-
span
|
|
104
|
-
rescue StandardError => e
|
|
105
|
-
OpenTelemetry.handle_error(exception: e)
|
|
106
67
|
end
|
|
107
68
|
|
|
108
|
-
|
|
109
|
-
HTTPX::Instrumentation.instance.tracer
|
|
110
|
-
end
|
|
69
|
+
span.finish
|
|
111
70
|
end
|
|
112
71
|
|
|
113
|
-
#
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
72
|
+
# return a span initialized with the +@request+ state.
|
|
73
|
+
def initialize_span(request, start_time = ::Time.now)
|
|
74
|
+
verb = request.verb
|
|
75
|
+
uri = request.uri
|
|
76
|
+
|
|
77
|
+
span_data = HttpHelper.span_attrs_for_dup(verb)
|
|
78
|
+
|
|
79
|
+
config = HTTPX::Instrumentation.instance.config
|
|
80
|
+
|
|
81
|
+
attributes = {
|
|
82
|
+
OpenTelemetry::SemanticConventions::Trace::HTTP_HOST => uri.host,
|
|
83
|
+
OpenTelemetry::SemanticConventions::Trace::HTTP_SCHEME => uri.scheme,
|
|
84
|
+
OpenTelemetry::SemanticConventions::Trace::HTTP_TARGET => uri.path,
|
|
85
|
+
OpenTelemetry::SemanticConventions::Trace::HTTP_URL => "#{uri.scheme}://#{uri.host}",
|
|
86
|
+
OpenTelemetry::SemanticConventions::Trace::NET_PEER_NAME => uri.host,
|
|
87
|
+
OpenTelemetry::SemanticConventions::Trace::NET_PEER_PORT => uri.port,
|
|
88
|
+
'url.scheme' => uri.scheme,
|
|
89
|
+
'url.path' => uri.path,
|
|
90
|
+
'url.full' => "#{uri.scheme}://#{uri.host}",
|
|
91
|
+
'server.address' => uri.host,
|
|
92
|
+
'server.port' => uri.port
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
attributes['url.query'] = uri.query unless uri.query.nil?
|
|
96
|
+
attributes[OpenTelemetry::SemanticConventions::Trace::PEER_SERVICE] = config[:peer_service] if config[:peer_service]
|
|
97
|
+
attributes.merge!(span_data.attributes)
|
|
98
|
+
|
|
99
|
+
span = tracer.start_span(span_data.span_name, attributes: attributes, kind: :client, start_timestamp: start_time)
|
|
100
|
+
|
|
101
|
+
OpenTelemetry::Trace.with_span(span) do
|
|
102
|
+
OpenTelemetry.propagation.inject(request.headers)
|
|
119
103
|
end
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
# Connection patch to start monitoring on initialization.
|
|
123
|
-
module ConnectionMethods
|
|
124
|
-
attr_reader :init_time
|
|
125
104
|
|
|
126
|
-
|
|
127
|
-
|
|
105
|
+
span
|
|
106
|
+
rescue StandardError => e
|
|
107
|
+
OpenTelemetry.handle_error(exception: e)
|
|
108
|
+
end
|
|
128
109
|
|
|
129
|
-
|
|
130
|
-
|
|
110
|
+
def tracer
|
|
111
|
+
HTTPX::Instrumentation.instance.tracer
|
|
131
112
|
end
|
|
132
113
|
end
|
|
133
114
|
end
|
|
@@ -8,119 +8,100 @@ module OpenTelemetry
|
|
|
8
8
|
module Instrumentation
|
|
9
9
|
module HTTPX
|
|
10
10
|
module Old
|
|
11
|
+
# Old Plugin
|
|
11
12
|
module Plugin
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
module_function
|
|
13
|
+
def self.load_dependencies(klass)
|
|
14
|
+
require_relative '../plugin'
|
|
15
|
+
klass.plugin(HTTPX::Plugin)
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
# request objects are reused, when already buffered requests get rerouted to a different
|
|
22
|
-
# connection due to connection issues, or when they already got a response, but need to
|
|
23
|
-
# be retried. In such situations, the original span needs to be extended for the former,
|
|
24
|
-
# while a new is required for the latter.
|
|
25
|
-
request.on(:idle) do
|
|
26
|
-
span = nil
|
|
27
|
-
end
|
|
28
|
-
# the span is initialized when the request is buffered in the parser, which is the closest
|
|
29
|
-
# one gets to actually sending the request.
|
|
30
|
-
request.on(:headers) do
|
|
31
|
-
next if span
|
|
32
|
-
|
|
33
|
-
span = initialize_span(request)
|
|
34
|
-
end
|
|
17
|
+
HTTPX::Plugin.const_set(:RequestTracer, RequestTracer)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
35
20
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
21
|
+
# Instruments around HTTPX's request/response lifecycle in order to generate
|
|
22
|
+
# an OTEL trace.
|
|
23
|
+
module RequestTracer
|
|
24
|
+
extend self
|
|
39
25
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
# and the tracing object in inserted before the on response callback is called.
|
|
44
|
-
span = initialize_span(request, response.error.connection.init_time)
|
|
26
|
+
# initializes tracing on the +request+.
|
|
27
|
+
def call(request)
|
|
28
|
+
span = nil
|
|
45
29
|
|
|
46
|
-
|
|
30
|
+
# request objects are reused, when already buffered requests get rerouted to a different
|
|
31
|
+
# connection due to connection issues, or when they already got a response, but need to
|
|
32
|
+
# be retried. In such situations, the original span needs to be extended for the former,
|
|
33
|
+
# while a new is required for the latter.
|
|
34
|
+
request.on(:idle) do
|
|
35
|
+
span = nil
|
|
36
|
+
end
|
|
37
|
+
# the span is initialized when the request is buffered in the parser, which is the closest
|
|
38
|
+
# one gets to actually sending the request.
|
|
39
|
+
request.on(:headers) do
|
|
40
|
+
next if span
|
|
47
41
|
|
|
48
|
-
|
|
49
|
-
end
|
|
42
|
+
span = initialize_span(request)
|
|
50
43
|
end
|
|
51
44
|
|
|
52
|
-
|
|
53
|
-
if
|
|
54
|
-
span.record_exception(response.error)
|
|
55
|
-
span.status = Trace::Status.error(response.error.to_s)
|
|
56
|
-
else
|
|
57
|
-
span.set_attribute(OpenTelemetry::SemanticConventions::Trace::HTTP_STATUS_CODE, response.status)
|
|
58
|
-
|
|
59
|
-
if response.status.between?(400, 599)
|
|
60
|
-
err = ::HTTPX::HTTPError.new(response)
|
|
61
|
-
span.record_exception(err)
|
|
62
|
-
span.status = Trace::Status.error(err.to_s)
|
|
63
|
-
end
|
|
64
|
-
end
|
|
45
|
+
request.on(:response) do |response|
|
|
46
|
+
span = initialize_span(request, request.init_time) if !span && request.init_time
|
|
65
47
|
|
|
66
|
-
span
|
|
48
|
+
finish(response, span)
|
|
67
49
|
end
|
|
50
|
+
end
|
|
68
51
|
|
|
69
|
-
|
|
70
|
-
def initialize_span(request, start_time = ::Time.now)
|
|
71
|
-
verb = request.verb
|
|
72
|
-
uri = request.uri
|
|
52
|
+
private
|
|
73
53
|
|
|
74
|
-
|
|
54
|
+
def finish(response, span)
|
|
55
|
+
if response.is_a?(::HTTPX::ErrorResponse)
|
|
56
|
+
span.record_exception(response.error)
|
|
57
|
+
span.status = Trace::Status.error(response.error.to_s)
|
|
58
|
+
else
|
|
59
|
+
span.set_attribute(OpenTelemetry::SemanticConventions::Trace::HTTP_STATUS_CODE, response.status)
|
|
75
60
|
|
|
76
|
-
|
|
61
|
+
if response.status.between?(400, 599)
|
|
62
|
+
err = ::HTTPX::HTTPError.new(response)
|
|
63
|
+
span.record_exception(err)
|
|
64
|
+
span.status = Trace::Status.error(err.to_s)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
77
67
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
OpenTelemetry::SemanticConventions::Trace::HTTP_SCHEME => uri.scheme,
|
|
81
|
-
OpenTelemetry::SemanticConventions::Trace::HTTP_TARGET => uri.path,
|
|
82
|
-
OpenTelemetry::SemanticConventions::Trace::HTTP_URL => "#{uri.scheme}://#{uri.host}",
|
|
83
|
-
OpenTelemetry::SemanticConventions::Trace::NET_PEER_NAME => uri.host,
|
|
84
|
-
OpenTelemetry::SemanticConventions::Trace::NET_PEER_PORT => uri.port
|
|
85
|
-
}
|
|
68
|
+
span.finish
|
|
69
|
+
end
|
|
86
70
|
|
|
87
|
-
|
|
88
|
-
|
|
71
|
+
# return a span initialized with the +@request+ state.
|
|
72
|
+
def initialize_span(request, start_time = ::Time.now)
|
|
73
|
+
verb = request.verb
|
|
74
|
+
uri = request.uri
|
|
89
75
|
|
|
90
|
-
|
|
76
|
+
span_data = HttpHelper.span_attrs_for_old(verb)
|
|
91
77
|
|
|
92
|
-
|
|
93
|
-
OpenTelemetry.propagation.inject(request.headers)
|
|
94
|
-
end
|
|
78
|
+
config = HTTPX::Instrumentation.instance.config
|
|
95
79
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
OpenTelemetry.
|
|
99
|
-
|
|
80
|
+
attributes = {
|
|
81
|
+
OpenTelemetry::SemanticConventions::Trace::HTTP_HOST => uri.host,
|
|
82
|
+
OpenTelemetry::SemanticConventions::Trace::HTTP_SCHEME => uri.scheme,
|
|
83
|
+
OpenTelemetry::SemanticConventions::Trace::HTTP_TARGET => uri.path,
|
|
84
|
+
OpenTelemetry::SemanticConventions::Trace::HTTP_URL => "#{uri.scheme}://#{uri.host}",
|
|
85
|
+
OpenTelemetry::SemanticConventions::Trace::NET_PEER_NAME => uri.host,
|
|
86
|
+
OpenTelemetry::SemanticConventions::Trace::NET_PEER_PORT => uri.port
|
|
87
|
+
}
|
|
100
88
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
end
|
|
104
|
-
end
|
|
89
|
+
attributes[OpenTelemetry::SemanticConventions::Trace::PEER_SERVICE] = config[:peer_service] if config[:peer_service]
|
|
90
|
+
attributes.merge!(span_data.attributes)
|
|
105
91
|
|
|
106
|
-
|
|
107
|
-
module RequestMethods
|
|
108
|
-
def initialize(*)
|
|
109
|
-
super
|
|
92
|
+
span = tracer.start_span(span_data.span_name, attributes: attributes, kind: :client, start_timestamp: start_time)
|
|
110
93
|
|
|
111
|
-
|
|
94
|
+
OpenTelemetry::Trace.with_span(span) do
|
|
95
|
+
OpenTelemetry.propagation.inject(request.headers)
|
|
112
96
|
end
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
# Connection patch to start monitoring on initialization.
|
|
116
|
-
module ConnectionMethods
|
|
117
|
-
attr_reader :init_time
|
|
118
97
|
|
|
119
|
-
|
|
120
|
-
|
|
98
|
+
span
|
|
99
|
+
rescue StandardError => e
|
|
100
|
+
OpenTelemetry.handle_error(exception: e)
|
|
101
|
+
end
|
|
121
102
|
|
|
122
|
-
|
|
123
|
-
|
|
103
|
+
def tracer
|
|
104
|
+
HTTPX::Instrumentation.instance.tracer
|
|
124
105
|
end
|
|
125
106
|
end
|
|
126
107
|
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright The OpenTelemetry Authors
|
|
4
|
+
#
|
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
|
|
7
|
+
module OpenTelemetry
|
|
8
|
+
module Instrumentation
|
|
9
|
+
module HTTPX
|
|
10
|
+
# Base Plugin
|
|
11
|
+
module Plugin
|
|
12
|
+
# Request patch to initiate the trace on initialization.
|
|
13
|
+
module RequestMethods
|
|
14
|
+
attr_accessor :init_time
|
|
15
|
+
|
|
16
|
+
# intercepts request initialization to inject the tracing logic.
|
|
17
|
+
def initialize(*)
|
|
18
|
+
super
|
|
19
|
+
|
|
20
|
+
@init_time = nil
|
|
21
|
+
|
|
22
|
+
RequestTracer.call(self)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def response=(*)
|
|
26
|
+
# init_time should be set when it's send to a connection.
|
|
27
|
+
# However, there are situations where connection initialization fails.
|
|
28
|
+
# Example is the :ssrf_filter plugin, which raises an error on
|
|
29
|
+
# initialize if the host is an IP which matches against the known set.
|
|
30
|
+
# in such cases, we'll just set here right here.
|
|
31
|
+
@init_time ||= ::Time.now
|
|
32
|
+
|
|
33
|
+
super
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Connection mixin
|
|
38
|
+
module ConnectionMethods
|
|
39
|
+
def initialize(*)
|
|
40
|
+
super
|
|
41
|
+
|
|
42
|
+
@init_time = ::Time.now
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def send(request)
|
|
46
|
+
request.init_time ||= @init_time
|
|
47
|
+
|
|
48
|
+
super
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -8,118 +8,99 @@ module OpenTelemetry
|
|
|
8
8
|
module Instrumentation
|
|
9
9
|
module HTTPX
|
|
10
10
|
module Stable
|
|
11
|
+
# Stable Plugin
|
|
11
12
|
module Plugin
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
module_function
|
|
13
|
+
def self.load_dependencies(klass)
|
|
14
|
+
require_relative '../plugin'
|
|
15
|
+
klass.plugin(HTTPX::Plugin)
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
# request objects are reused, when already buffered requests get rerouted to a different
|
|
22
|
-
# connection due to connection issues, or when they already got a response, but need to
|
|
23
|
-
# be retried. In such situations, the original span needs to be extended for the former,
|
|
24
|
-
# while a new is required for the latter.
|
|
25
|
-
request.on(:idle) do
|
|
26
|
-
span = nil
|
|
27
|
-
end
|
|
28
|
-
# the span is initialized when the request is buffered in the parser, which is the closest
|
|
29
|
-
# one gets to actually sending the request.
|
|
30
|
-
request.on(:headers) do
|
|
31
|
-
next if span
|
|
32
|
-
|
|
33
|
-
span = initialize_span(request)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
request.on(:response) do |response|
|
|
37
|
-
unless span
|
|
38
|
-
next unless response.is_a?(::HTTPX::ErrorResponse) && response.error.respond_to?(:connection)
|
|
17
|
+
HTTPX::Plugin.const_set(:RequestTracer, RequestTracer)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
39
20
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
span = initialize_span(request, response.error.connection.init_time)
|
|
21
|
+
# Instruments around HTTPX's request/response lifecycle in order to generate
|
|
22
|
+
# an OTEL trace.
|
|
23
|
+
module RequestTracer
|
|
24
|
+
extend self
|
|
45
25
|
|
|
46
|
-
|
|
26
|
+
# initializes tracing on the +request+.
|
|
27
|
+
def call(request)
|
|
28
|
+
span = nil
|
|
47
29
|
|
|
48
|
-
|
|
49
|
-
|
|
30
|
+
# request objects are reused, when already buffered requests get rerouted to a different
|
|
31
|
+
# connection due to connection issues, or when they already got a response, but need to
|
|
32
|
+
# be retried. In such situations, the original span needs to be extended for the former,
|
|
33
|
+
# while a new is required for the latter.
|
|
34
|
+
request.on(:idle) do
|
|
35
|
+
span = nil
|
|
50
36
|
end
|
|
37
|
+
# the span is initialized when the request is buffered in the parser, which is the closest
|
|
38
|
+
# one gets to actually sending the request.
|
|
39
|
+
request.on(:headers) do
|
|
40
|
+
next if span
|
|
51
41
|
|
|
52
|
-
|
|
53
|
-
if response.is_a?(::HTTPX::ErrorResponse)
|
|
54
|
-
span.record_exception(response.error)
|
|
55
|
-
span.status = Trace::Status.error(response.error.to_s)
|
|
56
|
-
else
|
|
57
|
-
span.set_attribute('http.response.status_code', response.status)
|
|
58
|
-
|
|
59
|
-
if response.status.between?(400, 599)
|
|
60
|
-
err = ::HTTPX::HTTPError.new(response)
|
|
61
|
-
span.record_exception(err)
|
|
62
|
-
span.status = Trace::Status.error(err.to_s)
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
span.finish
|
|
42
|
+
span = initialize_span(request)
|
|
67
43
|
end
|
|
68
44
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
verb = request.verb
|
|
72
|
-
uri = request.uri
|
|
45
|
+
request.on(:response) do |response|
|
|
46
|
+
span = initialize_span(request, request.init_time) if !span && request.init_time
|
|
73
47
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
48
|
+
finish(response, span)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
77
51
|
|
|
78
|
-
|
|
79
|
-
'url.scheme' => uri.scheme,
|
|
80
|
-
'url.path' => uri.path,
|
|
81
|
-
'url.full' => "#{uri.scheme}://#{uri.host}",
|
|
82
|
-
'server.address' => uri.host,
|
|
83
|
-
'server.port' => uri.port
|
|
84
|
-
}
|
|
85
|
-
attributes['url.query'] = uri.query unless uri.query.nil?
|
|
86
|
-
attributes[OpenTelemetry::SemanticConventions::Trace::PEER_SERVICE] = config[:peer_service] if config[:peer_service]
|
|
87
|
-
attributes.merge!(span_data.attributes)
|
|
52
|
+
private
|
|
88
53
|
|
|
89
|
-
|
|
54
|
+
def finish(response, span)
|
|
55
|
+
if response.is_a?(::HTTPX::ErrorResponse)
|
|
56
|
+
span.record_exception(response.error)
|
|
57
|
+
span.status = Trace::Status.error(response.error.to_s)
|
|
58
|
+
else
|
|
59
|
+
span.set_attribute('http.response.status_code', response.status)
|
|
90
60
|
|
|
91
|
-
|
|
92
|
-
|
|
61
|
+
if response.status.between?(400, 599)
|
|
62
|
+
err = ::HTTPX::HTTPError.new(response)
|
|
63
|
+
span.record_exception(err)
|
|
64
|
+
span.status = Trace::Status.error(err.to_s)
|
|
93
65
|
end
|
|
94
|
-
|
|
95
|
-
span
|
|
96
|
-
rescue StandardError => e
|
|
97
|
-
OpenTelemetry.handle_error(exception: e)
|
|
98
66
|
end
|
|
99
67
|
|
|
100
|
-
|
|
101
|
-
HTTPX::Instrumentation.instance.tracer
|
|
102
|
-
end
|
|
68
|
+
span.finish
|
|
103
69
|
end
|
|
104
70
|
|
|
105
|
-
#
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
71
|
+
# return a span initialized with the +@request+ state.
|
|
72
|
+
def initialize_span(request, start_time = ::Time.now)
|
|
73
|
+
verb = request.verb
|
|
74
|
+
uri = request.uri
|
|
109
75
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
76
|
+
span_data = HttpHelper.span_attrs_for_stable(verb)
|
|
77
|
+
|
|
78
|
+
config = HTTPX::Instrumentation.instance.config
|
|
113
79
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
80
|
+
attributes = {
|
|
81
|
+
'url.scheme' => uri.scheme,
|
|
82
|
+
'url.path' => uri.path,
|
|
83
|
+
'url.full' => "#{uri.scheme}://#{uri.host}",
|
|
84
|
+
'server.address' => uri.host,
|
|
85
|
+
'server.port' => uri.port
|
|
86
|
+
}
|
|
87
|
+
attributes['url.query'] = uri.query unless uri.query.nil?
|
|
88
|
+
attributes[OpenTelemetry::SemanticConventions::Trace::PEER_SERVICE] = config[:peer_service] if config[:peer_service]
|
|
89
|
+
attributes.merge!(span_data.attributes)
|
|
117
90
|
|
|
118
|
-
|
|
119
|
-
super
|
|
91
|
+
span = tracer.start_span(span_data.span_name, attributes: attributes, kind: :client, start_timestamp: start_time)
|
|
120
92
|
|
|
121
|
-
|
|
93
|
+
OpenTelemetry::Trace.with_span(span) do
|
|
94
|
+
OpenTelemetry.propagation.inject(request.headers)
|
|
122
95
|
end
|
|
96
|
+
|
|
97
|
+
span
|
|
98
|
+
rescue StandardError => e
|
|
99
|
+
OpenTelemetry.handle_error(exception: e)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def tracer
|
|
103
|
+
HTTPX::Instrumentation.instance.tracer
|
|
123
104
|
end
|
|
124
105
|
end
|
|
125
106
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: opentelemetry-instrumentation-httpx
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- OpenTelemetry Authors
|
|
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: opentelemetry-instrumentation-base
|
|
@@ -42,17 +41,17 @@ files:
|
|
|
42
41
|
- lib/opentelemetry/instrumentation/httpx/http_helper.rb
|
|
43
42
|
- lib/opentelemetry/instrumentation/httpx/instrumentation.rb
|
|
44
43
|
- lib/opentelemetry/instrumentation/httpx/old/plugin.rb
|
|
44
|
+
- lib/opentelemetry/instrumentation/httpx/plugin.rb
|
|
45
45
|
- lib/opentelemetry/instrumentation/httpx/stable/plugin.rb
|
|
46
46
|
- lib/opentelemetry/instrumentation/httpx/version.rb
|
|
47
47
|
homepage: https://github.com/open-telemetry/opentelemetry-ruby-contrib
|
|
48
48
|
licenses:
|
|
49
49
|
- Apache-2.0
|
|
50
50
|
metadata:
|
|
51
|
-
changelog_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-httpx/0.6.
|
|
51
|
+
changelog_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-httpx/0.6.1/file/CHANGELOG.md
|
|
52
52
|
source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby-contrib/tree/main/instrumentation/http
|
|
53
53
|
bug_tracker_uri: https://github.com/open-telemetry/opentelemetry-ruby-contrib/issues
|
|
54
|
-
documentation_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-httpx/0.6.
|
|
55
|
-
post_install_message:
|
|
54
|
+
documentation_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-httpx/0.6.1
|
|
56
55
|
rdoc_options: []
|
|
57
56
|
require_paths:
|
|
58
57
|
- lib
|
|
@@ -67,8 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
67
66
|
- !ruby/object:Gem::Version
|
|
68
67
|
version: '0'
|
|
69
68
|
requirements: []
|
|
70
|
-
rubygems_version:
|
|
71
|
-
signing_key:
|
|
69
|
+
rubygems_version: 4.0.3
|
|
72
70
|
specification_version: 4
|
|
73
71
|
summary: HTTPX instrumentation for the OpenTelemetry framework
|
|
74
72
|
test_files: []
|