opentelemetry-instrumentation-net_http 0.23.1 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 073c17f67fe6d843befe7c1b827b64e073219b0e459e041c49d56baf261309e3
4
- data.tar.gz: 1d3567120c88754301390af30f3e717268dc3221d33778082f7cd921a4e97c40
3
+ metadata.gz: da13afb78f87be6a3f4584ce952380fc280a32ed21a885998023590524b9e298
4
+ data.tar.gz: d9a4e0615c0eb4460f163606a430ea87869c7ccd74aa862e608537dcf5b4572c
5
5
  SHA512:
6
- metadata.gz: 4551dcb001400d831dd3e8556d7876fd8fa1dcbb1be764399ac6a263466784825e42b10a18975145a948b7502048fef69e3ac960196551fec286be402559341f
7
- data.tar.gz: e1ac201aabadd5c71ad3453430e304e81268ba988ff39491c97e6f13225c6937464b25e591912cc67a9d03768b63b1a6fff5371d6752ff8a1cbc216c54d9578a
6
+ metadata.gz: 9843b00941ccb409e8bf569bbb4e543976eb3b76ffd4965dcdd4fe553bd829f94de3ce4507b6ab3ad010f3fbbd6a45243b7aa39856bd743ac1dfb3a92b1bbe6d
7
+ data.tar.gz: cb09892cfe86b2032b84fedc9c38f40bd5bcfbfd1bcc6ed729596f3a629517870a314799c84388adc7f79d6e1341bf02787862ac83ebfdaf71421ac6b45651d9
data/CHANGELOG.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # Release History: opentelemetry-instrumentation-net_http
2
2
 
3
- ### v0.23.1 / 2025-07-29
3
+ ### v0.24.0 / 2025-08-26
4
+
5
+ * ADDED: Add `OTEL_SEMCONV_STABILITY_OPT_IN` environment variable compatibility [#1572](https://github.com/open-telemetry/opentelemetry-ruby-contrib/pull/1572)
6
+
7
+ ### v0.23.1 / 2025-08-13
4
8
 
5
9
  * FIXED: net_http and aws_sdk ci fix
6
10
 
@@ -40,30 +44,30 @@
40
44
 
41
45
  ### v0.22.1 / 2023-06-05
42
46
 
43
- * FIXED: Base config options
47
+ * FIXED: Base config options
44
48
 
45
49
  ### v0.22.0 / 2023-04-17
46
50
 
47
- * BREAKING CHANGE: Drop support for EoL Ruby 2.7
51
+ * BREAKING CHANGE: Drop support for EoL Ruby 2.7
48
52
 
49
- * ADDED: Drop support for EoL Ruby 2.7
50
- * FIXED: Drop Rails dependency for ActiveSupport Instrumentation
53
+ * ADDED: Drop support for EoL Ruby 2.7
54
+ * FIXED: Drop Rails dependency for ActiveSupport Instrumentation
51
55
 
52
56
  ### v0.21.1 / 2023-01-14
53
57
 
54
- * FIXED: Add untraced check to the Net::HTTP connect instrumentation
55
- * DOCS: Fix gem homepage
56
- * DOCS: More gem documentation fixes
58
+ * FIXED: Add untraced check to the Net::HTTP connect instrumentation
59
+ * DOCS: Fix gem homepage
60
+ * DOCS: More gem documentation fixes
57
61
 
58
62
  ### v0.21.0 / 2022-10-04
59
63
 
60
64
  * ADDED: Add Net::HTTP :untraced_hosts option
61
- * FIXED: Rename HTTP CONNECT for low level connection spans
65
+ * FIXED: Rename HTTP CONNECT for low level connection spans
62
66
 
63
67
  ### v0.20.0 / 2022-06-09
64
68
 
65
69
  * Upgrading Base dependency version
66
- * FIXED: Broken test file requirements
70
+ * FIXED: Broken test file requirements
67
71
 
68
72
  ### v0.19.5 / 2022-05-05
69
73
 
@@ -71,12 +75,12 @@
71
75
 
72
76
  ### v0.19.4 / 2022-02-02
73
77
 
74
- * FIXED: Clientcontext attrs overwrite in net::http
75
- * FIXED: Excessive hash creation on context attr merging
78
+ * FIXED: Clientcontext attrs overwrite in net::http
79
+ * FIXED: Excessive hash creation on context attr merging
76
80
 
77
81
  ### v0.19.3 / 2021-12-01
78
82
 
79
- * FIXED: Change net attribute names to match the semantic conventions spec for http
83
+ * FIXED: Change net attribute names to match the semantic conventions spec for http
80
84
 
81
85
  ### v0.19.2 / 2021-09-29
82
86
 
@@ -84,13 +88,13 @@
84
88
 
85
89
  ### v0.19.1 / 2021-08-12
86
90
 
87
- * DOCS: Update docs to rely more on environment variable configuration
91
+ * DOCS: Update docs to rely more on environment variable configuration
88
92
 
89
93
  ### v0.19.0 / 2021-06-23
90
94
 
91
- * BREAKING CHANGE: Total order constraint on span.status=
95
+ * BREAKING CHANGE: Total order constraint on span.status=
92
96
 
93
- * FIXED: Total order constraint on span.status=
97
+ * FIXED: Total order constraint on span.status=
94
98
 
95
99
  ### v0.18.0 / 2021-05-21
96
100
 
data/README.md CHANGED
@@ -52,3 +52,19 @@ Apache 2.0 license. See [LICENSE][license-github] for more information.
52
52
  [community-meetings]: https://github.com/open-telemetry/community#community-meetings
53
53
  [slack-channel]: https://cloud-native.slack.com/archives/C01NWKKMKMY
54
54
  [discussions-url]: https://github.com/open-telemetry/opentelemetry-ruby/discussions
55
+
56
+ ## HTTP semantic convention stability
57
+
58
+ In the OpenTelemetry ecosystem, HTTP semantic conventions have now reached a stable state. However, the initial Net::HTTP instrumentation was introduced before this stability was achieved, which resulted in HTTP attributes being based on an older version of the semantic conventions.
59
+
60
+ To facilitate the migration to stable semantic conventions, you can use the `OTEL_SEMCONV_STABILITY_OPT_IN` environment variable. This variable allows you to opt-in to the new stable conventions, ensuring compatibility and future-proofing your instrumentation.
61
+
62
+ When setting the value for `OTEL_SEMCONV_STABILITY_OPT_IN`, you can specify which conventions you wish to adopt:
63
+
64
+ - `http` - Emits the stable HTTP and networking conventions and ceases emitting the old conventions previously emitted by the instrumentation.
65
+ - `http/dup` - Emits both the old and stable HTTP and networking conventions, enabling a phased rollout of the stable semantic conventions.
66
+ - Default behavior (in the absence of either value) is to continue emitting the old HTTP and networking conventions the instrumentation previously emitted.
67
+
68
+ During the transition from old to stable conventions, Net::HTTP instrumentation code comes in three patch versions: `dup`, `old`, and `stable`. These versions are identical except for the attributes they send. Any changes to Net::HTTP instrumentation should consider all three patches.
69
+
70
+ For additional information on migration, please refer to our [documentation](https://opentelemetry.io/docs/specs/semconv/non-normative/http-migration/).
@@ -12,8 +12,9 @@ module OpenTelemetry
12
12
  # instrumentation
13
13
  class Instrumentation < OpenTelemetry::Instrumentation::Base
14
14
  install do |_config|
15
- require_dependencies
16
- patch
15
+ patch_type = determine_semconv
16
+ send(:"require_dependencies_#{patch_type}")
17
+ send(:"patch_#{patch_type}")
17
18
  end
18
19
 
19
20
  present do
@@ -30,12 +31,41 @@ module OpenTelemetry
30
31
 
31
32
  private
32
33
 
33
- def require_dependencies
34
- require_relative 'patches/instrumentation'
34
+ def determine_semconv
35
+ stability_opt_in = ENV.fetch('OTEL_SEMCONV_STABILITY_OPT_IN', '')
36
+ values = stability_opt_in.split(',').map(&:strip)
37
+
38
+ if values.include?('http/dup')
39
+ 'dup'
40
+ elsif values.include?('http')
41
+ 'stable'
42
+ else
43
+ 'old'
44
+ end
45
+ end
46
+
47
+ def require_dependencies_dup
48
+ require_relative 'patches/dup/instrumentation'
49
+ end
50
+
51
+ def require_dependencies_old
52
+ require_relative 'patches/old/instrumentation'
53
+ end
54
+
55
+ def require_dependencies_stable
56
+ require_relative 'patches/stable/instrumentation'
57
+ end
58
+
59
+ def patch_dup
60
+ ::Net::HTTP.prepend(Patches::Dup::Instrumentation)
61
+ end
62
+
63
+ def patch_old
64
+ ::Net::HTTP.prepend(Patches::Old::Instrumentation)
35
65
  end
36
66
 
37
- def patch
38
- ::Net::HTTP.prepend(Patches::Instrumentation)
67
+ def patch_stable
68
+ ::Net::HTTP.prepend(Patches::Stable::Instrumentation)
39
69
  end
40
70
  end
41
71
  end
@@ -0,0 +1,130 @@
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 Net
10
+ module HTTP
11
+ module Patches
12
+ module Dup
13
+ # Module to prepend to Net::HTTP for instrumentation
14
+ module Instrumentation
15
+ USE_SSL_TO_SCHEME = { false => 'http', true => 'https' }.freeze
16
+
17
+ # Constant for the HTTP status range
18
+ HTTP_STATUS_SUCCESS_RANGE = (100..399)
19
+
20
+ def request(req, body = nil, &)
21
+ # Do not trace recursive call for starting the connection
22
+ return super unless started?
23
+
24
+ return super if untraced?
25
+
26
+ attributes = {
27
+ OpenTelemetry::SemanticConventions::Trace::HTTP_METHOD => req.method,
28
+ OpenTelemetry::SemanticConventions::Trace::HTTP_SCHEME => USE_SSL_TO_SCHEME[use_ssl?],
29
+ OpenTelemetry::SemanticConventions::Trace::HTTP_TARGET => req.path,
30
+ OpenTelemetry::SemanticConventions::Trace::NET_PEER_NAME => @address,
31
+ OpenTelemetry::SemanticConventions::Trace::NET_PEER_PORT => @port,
32
+ 'http.request.method' => req.method,
33
+ 'url.scheme' => USE_SSL_TO_SCHEME[use_ssl?],
34
+ 'server.address' => @address,
35
+ 'server.port' => @port
36
+ }
37
+ path, query = split_path_and_query(req.path)
38
+ attributes['url.path'] = path
39
+ attributes['url.query'] = query if query
40
+
41
+ attributes.merge!(OpenTelemetry::Common::HTTP::ClientContext.attributes)
42
+
43
+ tracer.in_span(
44
+ req.method,
45
+ attributes: attributes,
46
+ kind: :client
47
+ ) do |span|
48
+ OpenTelemetry.propagation.inject(req)
49
+
50
+ super.tap do |response|
51
+ annotate_span_with_response!(span, response)
52
+ end
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def connect
59
+ return super if untraced?
60
+
61
+ if proxy?
62
+ conn_address = proxy_address
63
+ conn_port = proxy_port
64
+ else
65
+ conn_address = address
66
+ conn_port = port
67
+ end
68
+
69
+ attributes = {
70
+ OpenTelemetry::SemanticConventions::Trace::NET_PEER_NAME => conn_address,
71
+ OpenTelemetry::SemanticConventions::Trace::NET_PEER_PORT => conn_port,
72
+ 'server.address' => conn_address,
73
+ 'server.port' => conn_port
74
+ }.merge!(OpenTelemetry::Common::HTTP::ClientContext.attributes)
75
+
76
+ if use_ssl? && proxy?
77
+ span_name = 'CONNECT'
78
+ span_kind = :client
79
+ else
80
+ span_name = 'connect'
81
+ span_kind = :internal
82
+ end
83
+
84
+ tracer.in_span(span_name, attributes: attributes, kind: span_kind) do
85
+ super
86
+ end
87
+ end
88
+
89
+ def annotate_span_with_response!(span, response)
90
+ return unless response&.code
91
+
92
+ status_code = response.code.to_i
93
+
94
+ span.set_attribute(OpenTelemetry::SemanticConventions::Trace::HTTP_STATUS_CODE, status_code)
95
+ span.set_attribute('http.response.status_code', status_code)
96
+ span.status = OpenTelemetry::Trace::Status.error unless HTTP_STATUS_SUCCESS_RANGE.cover?(status_code)
97
+ end
98
+
99
+ def tracer
100
+ Net::HTTP::Instrumentation.instance.tracer
101
+ end
102
+
103
+ def untraced?
104
+ untraced_context? || untraced_host?
105
+ end
106
+
107
+ def untraced_host?
108
+ return true if Net::HTTP::Instrumentation.instance.config[:untraced_hosts]&.any? do |host|
109
+ host.is_a?(Regexp) ? host.match?(@address) : host == @address
110
+ end
111
+
112
+ false
113
+ end
114
+
115
+ def untraced_context?
116
+ OpenTelemetry::Common::Utilities.untraced?
117
+ end
118
+
119
+ def split_path_and_query(path)
120
+ path_and_query = path.split('?')
121
+
122
+ [path_and_query[0], path_and_query[1]]
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,113 @@
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 Net
10
+ module HTTP
11
+ module Patches
12
+ module Old
13
+ # Module to prepend to Net::HTTP for instrumentation
14
+ module Instrumentation
15
+ HTTP_METHODS_TO_SPAN_NAMES = Hash.new { |h, k| h[k] = "HTTP #{k}" }
16
+ USE_SSL_TO_SCHEME = { false => 'http', true => 'https' }.freeze
17
+
18
+ # Constant for the HTTP status range
19
+ HTTP_STATUS_SUCCESS_RANGE = (100..399)
20
+
21
+ def request(req, body = nil, &)
22
+ # Do not trace recursive call for starting the connection
23
+ return super unless started?
24
+
25
+ return super if untraced?
26
+
27
+ attributes = {
28
+ OpenTelemetry::SemanticConventions::Trace::HTTP_METHOD => req.method,
29
+ OpenTelemetry::SemanticConventions::Trace::HTTP_SCHEME => USE_SSL_TO_SCHEME[use_ssl?],
30
+ OpenTelemetry::SemanticConventions::Trace::HTTP_TARGET => req.path,
31
+ OpenTelemetry::SemanticConventions::Trace::NET_PEER_NAME => @address,
32
+ OpenTelemetry::SemanticConventions::Trace::NET_PEER_PORT => @port
33
+ }.merge!(OpenTelemetry::Common::HTTP::ClientContext.attributes)
34
+
35
+ tracer.in_span(
36
+ HTTP_METHODS_TO_SPAN_NAMES[req.method],
37
+ attributes: attributes,
38
+ kind: :client
39
+ ) do |span|
40
+ OpenTelemetry.propagation.inject(req)
41
+
42
+ super.tap do |response|
43
+ annotate_span_with_response!(span, response)
44
+ end
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def connect
51
+ return super if untraced?
52
+
53
+ if proxy?
54
+ conn_address = proxy_address
55
+ conn_port = proxy_port
56
+ else
57
+ conn_address = address
58
+ conn_port = port
59
+ end
60
+
61
+ attributes = {
62
+ OpenTelemetry::SemanticConventions::Trace::NET_PEER_NAME => conn_address,
63
+ OpenTelemetry::SemanticConventions::Trace::NET_PEER_PORT => conn_port
64
+ }.merge!(OpenTelemetry::Common::HTTP::ClientContext.attributes)
65
+
66
+ if use_ssl? && proxy?
67
+ span_name = 'HTTP CONNECT'
68
+ span_kind = :client
69
+ else
70
+ span_name = 'connect'
71
+ span_kind = :internal
72
+ end
73
+
74
+ tracer.in_span(span_name, attributes: attributes, kind: span_kind) do
75
+ super
76
+ end
77
+ end
78
+
79
+ def annotate_span_with_response!(span, response)
80
+ return unless response&.code
81
+
82
+ status_code = response.code.to_i
83
+
84
+ span.set_attribute(OpenTelemetry::SemanticConventions::Trace::HTTP_STATUS_CODE, status_code)
85
+ span.status = OpenTelemetry::Trace::Status.error unless HTTP_STATUS_SUCCESS_RANGE.cover?(status_code)
86
+ end
87
+
88
+ def tracer
89
+ Net::HTTP::Instrumentation.instance.tracer
90
+ end
91
+
92
+ def untraced?
93
+ untraced_context? || untraced_host?
94
+ end
95
+
96
+ def untraced_host?
97
+ return true if Net::HTTP::Instrumentation.instance.config[:untraced_hosts]&.any? do |host|
98
+ host.is_a?(Regexp) ? host.match?(@address) : host == @address
99
+ end
100
+
101
+ false
102
+ end
103
+
104
+ def untraced_context?
105
+ OpenTelemetry::Common::Utilities.untraced?
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,122 @@
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 Net
10
+ module HTTP
11
+ module Patches
12
+ module Stable
13
+ # Module to prepend to Net::HTTP for instrumentation
14
+ module Instrumentation
15
+ USE_SSL_TO_SCHEME = { false => 'http', true => 'https' }.freeze
16
+
17
+ # Constant for the HTTP status range
18
+ HTTP_STATUS_SUCCESS_RANGE = (100..399)
19
+
20
+ def request(req, body = nil, &)
21
+ # Do not trace recursive call for starting the connection
22
+ return super unless started?
23
+
24
+ return super if untraced?
25
+
26
+ attributes = {
27
+ 'http.request.method' => req.method,
28
+ 'url.scheme' => USE_SSL_TO_SCHEME[use_ssl?],
29
+ 'server.address' => @address,
30
+ 'server.port' => @port
31
+ }
32
+ path, query = split_path_and_query(req.path)
33
+ attributes['url.path'] = path
34
+ attributes['url.query'] = query if query
35
+
36
+ attributes.merge!(OpenTelemetry::Common::HTTP::ClientContext.attributes)
37
+
38
+ tracer.in_span(
39
+ req.method.to_s,
40
+ attributes: attributes,
41
+ kind: :client
42
+ ) do |span|
43
+ OpenTelemetry.propagation.inject(req)
44
+
45
+ super.tap do |response|
46
+ annotate_span_with_response!(span, response)
47
+ end
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def connect
54
+ return super if untraced?
55
+
56
+ if proxy?
57
+ conn_address = proxy_address
58
+ conn_port = proxy_port
59
+ else
60
+ conn_address = address
61
+ conn_port = port
62
+ end
63
+
64
+ attributes = {
65
+ 'server.address' => conn_address,
66
+ 'server.port' => conn_port
67
+ }.merge!(OpenTelemetry::Common::HTTP::ClientContext.attributes)
68
+
69
+ if use_ssl? && proxy?
70
+ span_name = 'CONNECT'
71
+ span_kind = :client
72
+ else
73
+ span_name = 'connect'
74
+ span_kind = :internal
75
+ end
76
+
77
+ tracer.in_span(span_name, attributes: attributes, kind: span_kind) do
78
+ super
79
+ end
80
+ end
81
+
82
+ def annotate_span_with_response!(span, response)
83
+ return unless response&.code
84
+
85
+ status_code = response.code.to_i
86
+
87
+ span.set_attribute('http.response.status_code', status_code)
88
+ span.status = OpenTelemetry::Trace::Status.error unless HTTP_STATUS_SUCCESS_RANGE.cover?(status_code)
89
+ end
90
+
91
+ def tracer
92
+ Net::HTTP::Instrumentation.instance.tracer
93
+ end
94
+
95
+ def untraced?
96
+ untraced_context? || untraced_host?
97
+ end
98
+
99
+ def untraced_host?
100
+ return true if Net::HTTP::Instrumentation.instance.config[:untraced_hosts]&.any? do |host|
101
+ host.is_a?(Regexp) ? host.match?(@address) : host == @address
102
+ end
103
+
104
+ false
105
+ end
106
+
107
+ def untraced_context?
108
+ OpenTelemetry::Common::Utilities.untraced?
109
+ end
110
+
111
+ def split_path_and_query(path)
112
+ path_and_query = path.split('?')
113
+
114
+ [path_and_query[0], path_and_query[1]]
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
@@ -8,7 +8,7 @@ module OpenTelemetry
8
8
  module Instrumentation
9
9
  module Net
10
10
  module HTTP
11
- VERSION = '0.23.1'
11
+ VERSION = '0.24.0'
12
12
  end
13
13
  end
14
14
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opentelemetry-instrumentation-net_http
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.23.1
4
+ version: 0.24.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - OpenTelemetry Authors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-08-13 00:00:00.000000000 Z
11
+ date: 2025-08-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: opentelemetry-api
@@ -53,16 +53,18 @@ files:
53
53
  - lib/opentelemetry/instrumentation.rb
54
54
  - lib/opentelemetry/instrumentation/net/http.rb
55
55
  - lib/opentelemetry/instrumentation/net/http/instrumentation.rb
56
- - lib/opentelemetry/instrumentation/net/http/patches/instrumentation.rb
56
+ - lib/opentelemetry/instrumentation/net/http/patches/dup/instrumentation.rb
57
+ - lib/opentelemetry/instrumentation/net/http/patches/old/instrumentation.rb
58
+ - lib/opentelemetry/instrumentation/net/http/patches/stable/instrumentation.rb
57
59
  - lib/opentelemetry/instrumentation/net/http/version.rb
58
60
  homepage: https://github.com/open-telemetry/opentelemetry-ruby-contrib
59
61
  licenses:
60
62
  - Apache-2.0
61
63
  metadata:
62
- changelog_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-net_http/0.23.1/file/CHANGELOG.md
64
+ changelog_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-net_http/0.24.0/file/CHANGELOG.md
63
65
  source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby-contrib/tree/main/instrumentation/net_http
64
66
  bug_tracker_uri: https://github.com/open-telemetry/opentelemetry-ruby-contrib/issues
65
- documentation_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-net_http/0.23.1
67
+ documentation_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-net_http/0.24.0
66
68
  post_install_message:
67
69
  rdoc_options: []
68
70
  require_paths:
@@ -1,111 +0,0 @@
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 Net
10
- module HTTP
11
- module Patches
12
- # Module to prepend to Net::HTTP for instrumentation
13
- module Instrumentation
14
- HTTP_METHODS_TO_SPAN_NAMES = Hash.new { |h, k| h[k] = "HTTP #{k}" }
15
- USE_SSL_TO_SCHEME = { false => 'http', true => 'https' }.freeze
16
-
17
- # Constant for the HTTP status range
18
- HTTP_STATUS_SUCCESS_RANGE = (100..399)
19
-
20
- def request(req, body = nil, &)
21
- # Do not trace recursive call for starting the connection
22
- return super unless started?
23
-
24
- return super if untraced?
25
-
26
- attributes = {
27
- OpenTelemetry::SemanticConventions::Trace::HTTP_METHOD => req.method,
28
- OpenTelemetry::SemanticConventions::Trace::HTTP_SCHEME => USE_SSL_TO_SCHEME[use_ssl?],
29
- OpenTelemetry::SemanticConventions::Trace::HTTP_TARGET => req.path,
30
- OpenTelemetry::SemanticConventions::Trace::NET_PEER_NAME => @address,
31
- OpenTelemetry::SemanticConventions::Trace::NET_PEER_PORT => @port
32
- }.merge!(OpenTelemetry::Common::HTTP::ClientContext.attributes)
33
-
34
- tracer.in_span(
35
- HTTP_METHODS_TO_SPAN_NAMES[req.method],
36
- attributes: attributes,
37
- kind: :client
38
- ) do |span|
39
- OpenTelemetry.propagation.inject(req)
40
-
41
- super.tap do |response|
42
- annotate_span_with_response!(span, response)
43
- end
44
- end
45
- end
46
-
47
- private
48
-
49
- def connect
50
- return super if untraced?
51
-
52
- if proxy?
53
- conn_address = proxy_address
54
- conn_port = proxy_port
55
- else
56
- conn_address = address
57
- conn_port = port
58
- end
59
-
60
- attributes = {
61
- OpenTelemetry::SemanticConventions::Trace::NET_PEER_NAME => conn_address,
62
- OpenTelemetry::SemanticConventions::Trace::NET_PEER_PORT => conn_port
63
- }.merge!(OpenTelemetry::Common::HTTP::ClientContext.attributes)
64
-
65
- if use_ssl? && proxy?
66
- span_name = 'HTTP CONNECT'
67
- span_kind = :client
68
- else
69
- span_name = 'connect'
70
- span_kind = :internal
71
- end
72
-
73
- tracer.in_span(span_name, attributes: attributes, kind: span_kind) do
74
- super
75
- end
76
- end
77
-
78
- def annotate_span_with_response!(span, response)
79
- return unless response&.code
80
-
81
- status_code = response.code.to_i
82
-
83
- span.set_attribute(OpenTelemetry::SemanticConventions::Trace::HTTP_STATUS_CODE, status_code)
84
- span.status = OpenTelemetry::Trace::Status.error unless HTTP_STATUS_SUCCESS_RANGE.cover?(status_code)
85
- end
86
-
87
- def tracer
88
- Net::HTTP::Instrumentation.instance.tracer
89
- end
90
-
91
- def untraced?
92
- untraced_context? || untraced_host?
93
- end
94
-
95
- def untraced_host?
96
- return true if Net::HTTP::Instrumentation.instance.config[:untraced_hosts]&.any? do |host|
97
- host.is_a?(Regexp) ? host.match?(@address) : host == @address
98
- end
99
-
100
- false
101
- end
102
-
103
- def untraced_context?
104
- OpenTelemetry::Common::Utilities.untraced?
105
- end
106
- end
107
- end
108
- end
109
- end
110
- end
111
- end