opentelemetry-instrumentation-excon 0.21.3 → 0.22.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: a40bd852e201c584c60a28fbc696cfe40e0f893725faab30ca261470aada8208
4
- data.tar.gz: 1af18adaec227b344a108b57257a0b926eb60191a4defceef3ee5646a52556ed
3
+ metadata.gz: 3e1c05833c8e9363a08e5f834fa6307dc9b12c4d89c384bf0e0c7d3eb930a826
4
+ data.tar.gz: 85f86623bcfb2b53e1ce2b84fb3659ef1b47b638a8d1d6788ce8365be3b0b35f
5
5
  SHA512:
6
- metadata.gz: '0931bf63aab79dcd26b43e3e9be495b70a6c742405bf6971dbc5218fd9cc0c9ed31642389158ec00b5e5f53a9f355dcb0548279ab7e9a4481726a80c9b1e676f'
7
- data.tar.gz: 3876e51076218eaef6c1cb325c850dc042bb02f9cb3dd563558ecc518c7903fdfc79d173d0d06e2ba07453d00c73a3936cff1b7b215ff9f183e6c9e8e56d4b06
6
+ metadata.gz: dab9b7e1402204da6c479e14a0ed4c4bb3e46e4d8bb92e831a0f0087476d68a252c79db38e29069dc33233b5d205838154dfc02db94c41dce223d62d013da877
7
+ data.tar.gz: e8e4729e3dba0857621e8141d7aae54d25ed9b0fd6d9236d5ef03e004ab66ce7cda9720ccadffa512264df6a11db469d2fe69ff4fdaa9c7a9769057ceada92a1
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Release History: opentelemetry-instrumentation-excon
2
2
 
3
+ ### v0.22.0 / 2023-11-28
4
+
5
+ * BREAKING CHANGE: Add a connect span to excon
6
+
7
+ * ADDED: Add a connect span to excon
8
+
3
9
  ### v0.21.3 / 2023-11-23
4
10
 
5
11
  * CHANGED: Applied Rubocop Performance Recommendations [#727](https://github.com/open-telemetry/opentelemetry-ruby-contrib/pull/727)
@@ -0,0 +1,41 @@
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 Concerns
10
+ # The untraced hosts concerns allows instrumentation to skip traces on hostnames in an exclusion list.
11
+ # If the current OpenTelemetry context is untraced, all hosts will be treated as untraced.
12
+ # When included in a class that extends OpenTelemetry::Instrumentation::Base, this module defines an option named :untraced_hosts.
13
+ module UntracedHosts
14
+ def self.included(klass)
15
+ klass.instance_eval do
16
+ # untraced_hosts: if a request's address matches any of the `String`
17
+ # or `Regexp` in this array, the instrumentation will not record a
18
+ # `kind = :client` representing the request and will not propagate
19
+ # context in the request.
20
+ option :untraced_hosts, default: [], validate: :array
21
+ end
22
+ end
23
+
24
+ # Checks whether the given host should be treated as untraced.
25
+ # If the current OpenTelemetry context is untraced, all hosts will be treated as untraced.
26
+ # The given host must be a String.
27
+ def untraced?(host)
28
+ OpenTelemetry::Common::Utilities.untraced? || untraced_host?(host)
29
+ end
30
+
31
+ private
32
+
33
+ def untraced_host?(host)
34
+ config[:untraced_hosts].any? do |rule|
35
+ rule.is_a?(Regexp) ? rule.match?(host) : rule == host
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -4,15 +4,20 @@
4
4
  #
5
5
  # SPDX-License-Identifier: Apache-2.0
6
6
 
7
+ require_relative '../concerns/untraced_hosts'
8
+
7
9
  module OpenTelemetry
8
10
  module Instrumentation
9
11
  module Excon
10
12
  # The Instrumentation class contains logic to detect and install the Excon
11
13
  # instrumentation
12
14
  class Instrumentation < OpenTelemetry::Instrumentation::Base
15
+ include OpenTelemetry::Instrumentation::Concerns::UntracedHosts
16
+
13
17
  install do |_config|
14
18
  require_dependencies
15
19
  add_middleware
20
+ patch
16
21
  end
17
22
 
18
23
  present do
@@ -25,11 +30,15 @@ module OpenTelemetry
25
30
 
26
31
  def require_dependencies
27
32
  require_relative 'middlewares/tracer_middleware'
33
+ require_relative 'patches/socket'
28
34
  end
29
35
 
30
36
  def add_middleware
31
- ::Excon.defaults[:middlewares] =
32
- Middlewares::TracerMiddleware.around_default_stack
37
+ ::Excon.defaults[:middlewares] = Middlewares::TracerMiddleware.around_default_stack
38
+ end
39
+
40
+ def patch
41
+ ::Excon::Socket.prepend(Patches::Socket)
33
42
  end
34
43
  end
35
44
  end
@@ -22,24 +22,30 @@ module OpenTelemetry
22
22
  end.freeze
23
23
 
24
24
  def request_call(datum)
25
- begin
26
- unless datum.key?(:otel_span)
27
- http_method = HTTP_METHODS_TO_UPPERCASE[datum[:method]]
28
- attributes = span_creation_attributes(datum, http_method)
29
- tracer.start_span(
30
- HTTP_METHODS_TO_SPAN_NAMES[http_method],
31
- attributes: attributes,
32
- kind: :client
33
- ).tap do |span|
34
- datum[:otel_span] = span
35
- OpenTelemetry::Trace.with_span(span) do
36
- OpenTelemetry.propagation.inject(datum[:headers])
37
- end
38
- end
39
- end
40
- rescue StandardError => e
41
- OpenTelemetry.logger.debug(e.message)
42
- end
25
+ return @stack.request_call(datum) if untraced?(datum)
26
+
27
+ http_method = HTTP_METHODS_TO_UPPERCASE[datum[:method]]
28
+
29
+ attributes = {
30
+ OpenTelemetry::SemanticConventions::Trace::HTTP_METHOD => http_method,
31
+ OpenTelemetry::SemanticConventions::Trace::HTTP_SCHEME => datum[:scheme],
32
+ OpenTelemetry::SemanticConventions::Trace::HTTP_TARGET => datum[:path],
33
+ OpenTelemetry::SemanticConventions::Trace::HTTP_HOST => datum[:host],
34
+ OpenTelemetry::SemanticConventions::Trace::NET_PEER_NAME => datum[:hostname],
35
+ OpenTelemetry::SemanticConventions::Trace::NET_PEER_PORT => datum[:port]
36
+ }
37
+
38
+ peer_service = Excon::Instrumentation.instance.config[:peer_service]
39
+ attributes[OpenTelemetry::SemanticConventions::Trace::PEER_SERVICE] = peer_service if peer_service
40
+ attributes.merge!(OpenTelemetry::Common::HTTP::ClientContext.attributes)
41
+
42
+ span = tracer.start_span(HTTP_METHODS_TO_SPAN_NAMES[http_method], attributes: attributes, kind: :client)
43
+ ctx = OpenTelemetry::Trace.context_with_span(span)
44
+
45
+ datum[:otel_span] = span
46
+ datum[:otel_token] = OpenTelemetry::Context.attach(ctx)
47
+
48
+ OpenTelemetry.propagation.inject(datum[:headers])
43
49
 
44
50
  @stack.request_call(datum)
45
51
  end
@@ -71,43 +77,35 @@ module OpenTelemetry
71
77
  private
72
78
 
73
79
  def handle_response(datum)
74
- if datum.key?(:otel_span)
75
- datum[:otel_span].tap do |span|
76
- return span if span.end_timestamp
80
+ datum.delete(:otel_span)&.tap do |span|
81
+ return unless span.recording?
77
82
 
78
- if datum.key?(:response)
79
- response = datum[:response]
80
- span.set_attribute('http.status_code', response[:status])
81
- span.status = OpenTelemetry::Trace::Status.error unless (100..399).cover?(response[:status].to_i)
82
- end
83
-
84
- span.status = OpenTelemetry::Trace::Status.error("Request has failed: #{datum[:error]}") if datum.key?(:error)
83
+ if datum.key?(:response)
84
+ response = datum[:response]
85
+ span.set_attribute(OpenTelemetry::SemanticConventions::Trace::HTTP_STATUS_CODE, response[:status])
86
+ span.status = OpenTelemetry::Trace::Status.error unless (100..399).cover?(response[:status].to_i)
87
+ end
85
88
 
86
- span.finish
87
- datum.delete(:otel_span)
89
+ if datum.key?(:error)
90
+ span.status = OpenTelemetry::Trace::Status.error('Request has failed')
91
+ span.record_exception(datum[:error])
88
92
  end
93
+
94
+ span.finish
95
+
96
+ OpenTelemetry::Context.detach(datum.delete(:otel_token)) if datum.include?(:otel_token)
89
97
  end
90
98
  rescue StandardError => e
91
- OpenTelemetry.logger.debug(e.message)
92
- end
93
-
94
- def span_creation_attributes(datum, http_method)
95
- instrumentation_attrs = {
96
- 'http.host' => datum[:host],
97
- 'http.method' => http_method,
98
- 'http.scheme' => datum[:scheme],
99
- 'http.target' => datum[:path]
100
- }
101
- config = Excon::Instrumentation.instance.config
102
- instrumentation_attrs['peer.service'] = config[:peer_service] if config[:peer_service]
103
- instrumentation_attrs.merge!(
104
- OpenTelemetry::Common::HTTP::ClientContext.attributes
105
- )
99
+ OpenTelemetry.handle_error(e)
106
100
  end
107
101
 
108
102
  def tracer
109
103
  Excon::Instrumentation.instance.tracer
110
104
  end
105
+
106
+ def untraced?(datum)
107
+ datum.key?(:otel_span) || Excon::Instrumentation.instance.untraced?(datum[:host])
108
+ end
111
109
  end
112
110
  end
113
111
  end
@@ -0,0 +1,58 @@
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 Excon
10
+ module Patches
11
+ # Module to prepend to an Excon Socket for instrumentation
12
+ module Socket
13
+ private
14
+
15
+ def connect
16
+ return super if untraced?
17
+
18
+ if @data[:proxy]
19
+ conn_address = @data.dig(:proxy, :hostname)
20
+ conn_port = @data.dig(:proxy, :port)
21
+ else
22
+ conn_address = @data[:hostname]
23
+ conn_port = @port
24
+ end
25
+
26
+ attributes = { OpenTelemetry::SemanticConventions::Trace::NET_PEER_NAME => conn_address, OpenTelemetry::SemanticConventions::Trace::NET_PEER_PORT => conn_port }.merge!(OpenTelemetry::Common::HTTP::ClientContext.attributes)
27
+
28
+ if is_a?(::Excon::SSLSocket) && @data[:proxy]
29
+ span_name = 'HTTP CONNECT'
30
+ span_kind = :client
31
+ else
32
+ span_name = 'connect'
33
+ span_kind = :internal
34
+ end
35
+
36
+ tracer.in_span(span_name, attributes: attributes, kind: span_kind) do
37
+ super
38
+ end
39
+ end
40
+
41
+ def tracer
42
+ Excon::Instrumentation.instance.tracer
43
+ end
44
+
45
+ def untraced?
46
+ address = if @data[:proxy]
47
+ @data.dig(:proxy, :hostname)
48
+ else
49
+ @data[:hostname]
50
+ end
51
+
52
+ Excon::Instrumentation.instance.untraced?(address)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -7,7 +7,7 @@
7
7
  module OpenTelemetry
8
8
  module Instrumentation
9
9
  module Excon
10
- VERSION = '0.21.3'
10
+ VERSION = '0.22.0'
11
11
  end
12
12
  end
13
13
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opentelemetry-instrumentation-excon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.3
4
+ version: 0.22.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: 2023-11-23 00:00:00.000000000 Z
11
+ date: 2023-11-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: opentelemetry-api
@@ -219,18 +219,20 @@ files:
219
219
  - README.md
220
220
  - lib/opentelemetry-instrumentation-excon.rb
221
221
  - lib/opentelemetry/instrumentation.rb
222
+ - lib/opentelemetry/instrumentation/concerns/untraced_hosts.rb
222
223
  - lib/opentelemetry/instrumentation/excon.rb
223
224
  - lib/opentelemetry/instrumentation/excon/instrumentation.rb
224
225
  - lib/opentelemetry/instrumentation/excon/middlewares/tracer_middleware.rb
226
+ - lib/opentelemetry/instrumentation/excon/patches/socket.rb
225
227
  - lib/opentelemetry/instrumentation/excon/version.rb
226
228
  homepage: https://github.com/open-telemetry/opentelemetry-ruby-contrib
227
229
  licenses:
228
230
  - Apache-2.0
229
231
  metadata:
230
- changelog_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-excon/0.21.3/file/CHANGELOG.md
232
+ changelog_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-excon/0.22.0/file/CHANGELOG.md
231
233
  source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby-contrib/tree/main/instrumentation/excon
232
234
  bug_tracker_uri: https://github.com/open-telemetry/opentelemetry-ruby-contrib/issues
233
- documentation_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-excon/0.21.3
235
+ documentation_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-excon/0.22.0
234
236
  post_install_message:
235
237
  rdoc_options: []
236
238
  require_paths: