opentelemetry-instrumentation-action_pack 0.8.0 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +41 -2
- data/lib/opentelemetry/instrumentation/action_pack/handlers/action_controller.rb +77 -0
- data/lib/opentelemetry/instrumentation/action_pack/handlers.rb +38 -0
- data/lib/opentelemetry/instrumentation/action_pack/instrumentation.rb +29 -3
- data/lib/opentelemetry/instrumentation/action_pack/version.rb +1 -1
- metadata +19 -18
- data/lib/opentelemetry/instrumentation/action_pack/patches/action_controller/metal.rb +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5af8d8cb9038f564234140ffaa6d87f1b07ecb7021e4fe579ec5efc938b2898e
|
4
|
+
data.tar.gz: '091d78c0c499b98b31a31ea31aa6f0990f8cabe53dab62dd532036985def42ef'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e7782f0b1b04ab4a019677bd81a68c01954af5ece9a7f3b0073a764490241fed82b8173cc435fcbbcd7ec46786e1237a7b5e4406982de61674ad8285aafe60c
|
7
|
+
data.tar.gz: 97404fce81bd10262a19e129f6397aeaabe39ae54850a0f3d085952e6264e1392617727bab6a1fd22837338d48b2e603444a2392499168a0872abd0b62a71f06
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Release History: opentelemetry-instrumentation-action_pack
|
2
2
|
|
3
|
+
### v0.10.0 / 2024-11-19
|
4
|
+
|
5
|
+
* ADDED: Use Semconv Naming For ActionPack
|
6
|
+
|
7
|
+
### v0.9.0 / 2024-01-09
|
8
|
+
|
9
|
+
* BREAKING CHANGE: Use ActiveSupport instead of patches #703
|
10
|
+
|
3
11
|
### v0.8.0 / 2023-11-22
|
4
12
|
|
5
13
|
* BREAKING CHANGE: Drop Rails 6.0 EOL
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@ The Action Pack instrumentation is a community-maintained instrumentation for th
|
|
6
6
|
|
7
7
|
Install the gem using:
|
8
8
|
|
9
|
-
```
|
9
|
+
```console
|
10
10
|
gem install opentelemetry-instrumentation-action_pack
|
11
11
|
```
|
12
12
|
|
@@ -30,6 +30,43 @@ OpenTelemetry::SDK.configure do |c|
|
|
30
30
|
end
|
31
31
|
```
|
32
32
|
|
33
|
+
## Active Support Instrumentation
|
34
|
+
|
35
|
+
Earlier versions of this instrumentation relied on patching custom `dispatch` hooks from Rails's [Action Controller](https://github.com/rails/rails/blob/main/actionpack/lib/action_controller/metal.rb#L224) to extract request information.
|
36
|
+
|
37
|
+
This instrumentation now relies on `ActiveSupport::Notifications` and registers a custom Subscriber that listens to relevant events to modify the Rack span.
|
38
|
+
|
39
|
+
See the table below for details of what [Rails Framework Hook Events](https://guides.rubyonrails.org/active_support_instrumentation.html#action-controller) are recorded by this instrumentation:
|
40
|
+
|
41
|
+
| Event Name | Subscribe? | Creates Span? | Notes |
|
42
|
+
| - | - | - | - |
|
43
|
+
| `process_action.action_controller` | :white_check_mark: | :x: | It modifies the existing Rack span |
|
44
|
+
|
45
|
+
## Semantic Conventions
|
46
|
+
|
47
|
+
This instrumentation generally uses [HTTP server semantic conventions](https://opentelemetry.io/docs/specs/semconv/http/http-spans/) to update the existing Rack span.
|
48
|
+
|
49
|
+
For Rails 7.1+, the span name is updated to match the HTTP method and route that was matched for the request using [`ActionDispatch::Request#route_uri_pattern`](https://api.rubyonrails.org/classes/ActionDispatch/Request.html#method-i-route_uri_pattern), e.g.: `GET /users/:id`
|
50
|
+
|
51
|
+
For older versions of Rails the span name is updated to match the HTTP method, controller, and action name that was the target of the request, e.g.: `GET /example/index`
|
52
|
+
|
53
|
+
> ![NOTE]: Users may override the `span_naming` option to default to Legacy Span Naming Behavior that uses the controller's class name and action in Ruby documentation syntax, e.g. `ExampleController#index`.
|
54
|
+
|
55
|
+
This instrumentation does not emit any custom attributes.
|
56
|
+
|
57
|
+
| Attribute Name | Type | Notes |
|
58
|
+
| - | - | - |
|
59
|
+
| `code.namespace` | String | `ActionController` class name |
|
60
|
+
| `code.function` | String | `ActionController` action name e.g. `index`, `show`, `edit`, etc... |
|
61
|
+
| `http.route` | String | (Rails 7.1+) the route that was matched for the request |
|
62
|
+
| `http.target` | String | The `request.filtered_path` |
|
63
|
+
|
64
|
+
### Error Handling for Action Controller
|
65
|
+
|
66
|
+
If an error is triggered by Action Controller (such as a 500 internal server error), Action Pack will typically employ the default `ActionDispatch::PublicExceptions.new(Rails.public_path)` as the `exceptions_app`, as detailed in the [documentation](https://guides.rubyonrails.org/configuring.html#config-exceptions-app).
|
67
|
+
|
68
|
+
The error object will be retained within `payload[:exception_object]`. Additionally, its storage in `request.env['action_dispatch.exception']` is contingent upon the configuration of `action_dispatch.show_exceptions` in Rails.
|
69
|
+
|
33
70
|
## Examples
|
34
71
|
|
35
72
|
Example usage can be seen in the `./example/trace_demonstration.rb` file [here](https://github.com/open-telemetry/opentelemetry-ruby-contrib/blob/main/instrumentation/action_pack/example/trace_demonstration.ru)
|
@@ -38,7 +75,7 @@ Example usage can be seen in the `./example/trace_demonstration.rb` file [here](
|
|
38
75
|
|
39
76
|
The `opentelemetry-instrumentation-action_pack` gem source is [on github][repo-github], along with related gems including `opentelemetry-api` and `opentelemetry-sdk`.
|
40
77
|
|
41
|
-
The OpenTelemetry Ruby gems are maintained by the OpenTelemetry
|
78
|
+
The OpenTelemetry Ruby gems are maintained by the OpenTelemetry Ruby special interest group (SIG). You can get involved by joining us on our [GitHub Discussions][discussions-url], [Slack Channel][slack-channel] or attending our weekly meeting. See the [meeting calendar][community-meetings] for dates and times. For more information on this and other language SIGs, see the OpenTelemetry [community page][ruby-sig].
|
42
79
|
|
43
80
|
## License
|
44
81
|
|
@@ -49,4 +86,6 @@ The `opentelemetry-instrumentation-action_pack` gem is distributed under the Apa
|
|
49
86
|
[license-github]: https://github.com/open-telemetry/opentelemetry-ruby-contrib/blob/main/LICENSE
|
50
87
|
[ruby-sig]: https://github.com/open-telemetry/community#ruby-sig
|
51
88
|
[community-meetings]: https://github.com/open-telemetry/community#community-meetings
|
89
|
+
[slack-channel]: https://cloud-native.slack.com/archives/C01NWKKMKMY
|
52
90
|
[discussions-url]: https://github.com/open-telemetry/opentelemetry-ruby/discussions
|
91
|
+
[rails-home]: https://rubyonrails.org/
|
@@ -0,0 +1,77 @@
|
|
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 ActionPack
|
10
|
+
module Handlers
|
11
|
+
# Action Controller handler to handle the notification from Active Support
|
12
|
+
class ActionController
|
13
|
+
# @param config [Hash] of instrumentation options
|
14
|
+
def initialize(config)
|
15
|
+
@config = config
|
16
|
+
@span_naming = config.fetch(:span_naming)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Invoked by ActiveSupport::Notifications at the start of the instrumentation block
|
20
|
+
#
|
21
|
+
# @param _name [String] of the event (unused)
|
22
|
+
# @param _id [String] of the event (unused)
|
23
|
+
# @param payload [Hash] the payload passed as a method argument
|
24
|
+
# @return [Hash] the payload passed as a method argument
|
25
|
+
def start(_name, _id, payload)
|
26
|
+
span_name, attributes = to_span_name_and_attributes(payload)
|
27
|
+
|
28
|
+
span = OpenTelemetry::Instrumentation::Rack.current_span
|
29
|
+
span.name = span_name
|
30
|
+
span.add_attributes(attributes)
|
31
|
+
rescue StandardError => e
|
32
|
+
OpenTelemetry.handle_error(exception: e)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Invoked by ActiveSupport::Notifications at the end of the instrumentation block
|
36
|
+
#
|
37
|
+
# @param _name [String] of the event (unused)
|
38
|
+
# @param _id [String] of the event (unused)
|
39
|
+
# @param payload [Hash] the payload passed as a method argument
|
40
|
+
# @return [Hash] the payload passed as a method argument
|
41
|
+
def finish(_name, _id, payload)
|
42
|
+
span = OpenTelemetry::Instrumentation::Rack.current_span
|
43
|
+
span.record_exception(payload[:exception_object]) if payload[:exception_object]
|
44
|
+
rescue StandardError => e
|
45
|
+
OpenTelemetry.handle_error(exception: e)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# Extracts the span name and attributes from the payload
|
51
|
+
#
|
52
|
+
# @param payload [Hash] the payload passed from ActiveSupport::Notifications
|
53
|
+
# @return [Array<String, Hash>] the span name and attributes
|
54
|
+
def to_span_name_and_attributes(payload)
|
55
|
+
request = payload[:request]
|
56
|
+
http_route = request.route_uri_pattern if request.respond_to?(:route_uri_pattern)
|
57
|
+
|
58
|
+
attributes = {
|
59
|
+
OpenTelemetry::SemanticConventions::Trace::CODE_NAMESPACE => String(payload[:controller]),
|
60
|
+
OpenTelemetry::SemanticConventions::Trace::CODE_FUNCTION => String(payload[:action])
|
61
|
+
}
|
62
|
+
attributes[OpenTelemetry::SemanticConventions::Trace::HTTP_ROUTE] = http_route if http_route
|
63
|
+
attributes[OpenTelemetry::SemanticConventions::Trace::HTTP_TARGET] = request.filtered_path if request.filtered_path != request.fullpath
|
64
|
+
|
65
|
+
if @span_naming == :semconv
|
66
|
+
return ["#{request.method} #{http_route.gsub('(.:format)', '')}", attributes] if http_route
|
67
|
+
|
68
|
+
return ["#{request.method} /#{payload.dig(:params, :controller)}/#{payload.dig(:params, :action)}", attributes]
|
69
|
+
end
|
70
|
+
|
71
|
+
["#{payload[:controller]}##{payload[:action]}", attributes]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright The OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
require_relative 'handlers/action_controller'
|
8
|
+
|
9
|
+
module OpenTelemetry
|
10
|
+
module Instrumentation
|
11
|
+
module ActionPack
|
12
|
+
# Module that contains custom event handlers, which are used to generate spans per event
|
13
|
+
module Handlers
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def subscribe
|
17
|
+
return unless Array(@subscriptions).empty?
|
18
|
+
|
19
|
+
config = ActionPack::Instrumentation.instance.config
|
20
|
+
handlers_by_pattern = {
|
21
|
+
'process_action.action_controller' => Handlers::ActionController.new(config)
|
22
|
+
}
|
23
|
+
|
24
|
+
@subscriptions = handlers_by_pattern.map do |key, handler|
|
25
|
+
::ActiveSupport::Notifications.subscribe(key, handler)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Removes Event Handler Subscriptions for Action Controller notifications
|
30
|
+
# @note this method is not thread-safe and should not be used in a multi-threaded context
|
31
|
+
def unsubscribe
|
32
|
+
@subscriptions&.each { |subscriber| ::ActiveSupport::Notifications.unsubscribe(subscriber) }
|
33
|
+
@subscriptions = nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -7,7 +7,31 @@
|
|
7
7
|
module OpenTelemetry
|
8
8
|
module Instrumentation
|
9
9
|
module ActionPack
|
10
|
-
# The Instrumentation class contains logic to detect and install the ActionPack instrumentation
|
10
|
+
# The {OpenTelemetry::Instrumentation::ActionPack::Instrumentation} class contains logic to detect and install the ActionPack instrumentation
|
11
|
+
#
|
12
|
+
# Installation and configuration of this instrumentation is done within the
|
13
|
+
# {https://www.rubydoc.info/gems/opentelemetry-sdk/OpenTelemetry/SDK#configure-instance_method OpenTelemetry::SDK#configure}
|
14
|
+
# block, calling {https://www.rubydoc.info/gems/opentelemetry-sdk/OpenTelemetry%2FSDK%2FConfigurator:use use()}
|
15
|
+
# or {https://www.rubydoc.info/gems/opentelemetry-sdk/OpenTelemetry%2FSDK%2FConfigurator:use_all use_all()}.
|
16
|
+
#
|
17
|
+
# ## Configuration keys and options
|
18
|
+
#
|
19
|
+
# ### `:span_naming`
|
20
|
+
#
|
21
|
+
# Specifies how the span names are set. Can be one of:
|
22
|
+
#
|
23
|
+
# - `:semconv` **(default)** - The span name will use HTTP semantic conventions '{method http.route}', for example `GET /users/:id`
|
24
|
+
# - `:class` - The span name will appear as '<ActionController class name>#<action>',
|
25
|
+
# for example `UsersController#show`.
|
26
|
+
#
|
27
|
+
# @example An explicit default configuration
|
28
|
+
# OpenTelemetry::SDK.configure do |c|
|
29
|
+
# c.use_all({
|
30
|
+
# 'OpenTelemetry::Instrumentation::ActionPack' => {
|
31
|
+
# span_naming: :class
|
32
|
+
# },
|
33
|
+
# })
|
34
|
+
# end
|
11
35
|
class Instrumentation < OpenTelemetry::Instrumentation::Base
|
12
36
|
MINIMUM_VERSION = Gem::Version.new('6.1.0')
|
13
37
|
|
@@ -17,6 +41,8 @@ module OpenTelemetry
|
|
17
41
|
patch
|
18
42
|
end
|
19
43
|
|
44
|
+
option :span_naming, default: :semconv, validate: %i[semconv class]
|
45
|
+
|
20
46
|
present do
|
21
47
|
defined?(::ActionController)
|
22
48
|
end
|
@@ -32,11 +58,11 @@ module OpenTelemetry
|
|
32
58
|
end
|
33
59
|
|
34
60
|
def patch
|
35
|
-
|
61
|
+
Handlers.subscribe
|
36
62
|
end
|
37
63
|
|
38
64
|
def require_dependencies
|
39
|
-
require_relative '
|
65
|
+
require_relative 'handlers'
|
40
66
|
end
|
41
67
|
|
42
68
|
def require_railtie
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opentelemetry-instrumentation-action_pack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.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:
|
11
|
+
date: 2024-11-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: opentelemetry-api
|
@@ -123,47 +123,47 @@ dependencies:
|
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0.3'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
126
|
+
name: rake
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
|
-
- - "
|
129
|
+
- - "~>"
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: '
|
131
|
+
version: '13.0'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
|
-
- - "
|
136
|
+
- - "~>"
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: '
|
138
|
+
version: '13.0'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
140
|
+
name: rubocop
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
143
|
- - "~>"
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version:
|
145
|
+
version: 1.68.0
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
150
|
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version:
|
152
|
+
version: 1.68.0
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
|
-
name: rubocop
|
154
|
+
name: rubocop-performance
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
156
156
|
requirements:
|
157
157
|
- - "~>"
|
158
158
|
- !ruby/object:Gem::Version
|
159
|
-
version: 1.
|
159
|
+
version: 1.22.0
|
160
160
|
type: :development
|
161
161
|
prerelease: false
|
162
162
|
version_requirements: !ruby/object:Gem::Requirement
|
163
163
|
requirements:
|
164
164
|
- - "~>"
|
165
165
|
- !ruby/object:Gem::Version
|
166
|
-
version: 1.
|
166
|
+
version: 1.22.0
|
167
167
|
- !ruby/object:Gem::Dependency
|
168
168
|
name: simplecov
|
169
169
|
requirement: !ruby/object:Gem::Requirement
|
@@ -184,14 +184,14 @@ dependencies:
|
|
184
184
|
requirements:
|
185
185
|
- - "~>"
|
186
186
|
- !ruby/object:Gem::Version
|
187
|
-
version:
|
187
|
+
version: 3.24.0
|
188
188
|
type: :development
|
189
189
|
prerelease: false
|
190
190
|
version_requirements: !ruby/object:Gem::Requirement
|
191
191
|
requirements:
|
192
192
|
- - "~>"
|
193
193
|
- !ruby/object:Gem::Version
|
194
|
-
version:
|
194
|
+
version: 3.24.0
|
195
195
|
- !ruby/object:Gem::Dependency
|
196
196
|
name: yard
|
197
197
|
requirement: !ruby/object:Gem::Requirement
|
@@ -220,18 +220,19 @@ files:
|
|
220
220
|
- lib/opentelemetry-instrumentation-action_pack.rb
|
221
221
|
- lib/opentelemetry/instrumentation.rb
|
222
222
|
- lib/opentelemetry/instrumentation/action_pack.rb
|
223
|
+
- lib/opentelemetry/instrumentation/action_pack/handlers.rb
|
224
|
+
- lib/opentelemetry/instrumentation/action_pack/handlers/action_controller.rb
|
223
225
|
- lib/opentelemetry/instrumentation/action_pack/instrumentation.rb
|
224
|
-
- lib/opentelemetry/instrumentation/action_pack/patches/action_controller/metal.rb
|
225
226
|
- lib/opentelemetry/instrumentation/action_pack/railtie.rb
|
226
227
|
- lib/opentelemetry/instrumentation/action_pack/version.rb
|
227
228
|
homepage: https://github.com/open-telemetry/opentelemetry-ruby-contrib
|
228
229
|
licenses:
|
229
230
|
- Apache-2.0
|
230
231
|
metadata:
|
231
|
-
changelog_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-action_pack/0.
|
232
|
+
changelog_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-action_pack/0.10.0/file/CHANGELOG.md
|
232
233
|
source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby-contrib/tree/main/instrumentation/action_pack
|
233
234
|
bug_tracker_uri: https://github.com/open-telemetry/opentelemetry-ruby-contrib/issues
|
234
|
-
documentation_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-action_pack/0.
|
235
|
+
documentation_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-action_pack/0.10.0
|
235
236
|
post_install_message:
|
236
237
|
rdoc_options: []
|
237
238
|
require_paths:
|
@@ -1,40 +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 ActionPack
|
10
|
-
module Patches
|
11
|
-
module ActionController
|
12
|
-
# Module to prepend to ActionController::Metal for instrumentation
|
13
|
-
module Metal
|
14
|
-
def dispatch(name, request, response)
|
15
|
-
rack_span = OpenTelemetry::Instrumentation::Rack.current_span
|
16
|
-
if rack_span.recording?
|
17
|
-
rack_span.name = "#{self.class.name}##{name}" unless request.env['action_dispatch.exception']
|
18
|
-
|
19
|
-
attributes_to_append = {
|
20
|
-
OpenTelemetry::SemanticConventions::Trace::CODE_NAMESPACE => self.class.name,
|
21
|
-
OpenTelemetry::SemanticConventions::Trace::CODE_FUNCTION => String(name)
|
22
|
-
}
|
23
|
-
attributes_to_append[OpenTelemetry::SemanticConventions::Trace::HTTP_TARGET] = request.filtered_path if request.filtered_path != request.fullpath
|
24
|
-
rack_span.add_attributes(attributes_to_append)
|
25
|
-
end
|
26
|
-
|
27
|
-
super(name, request, response)
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
def instrumentation_config
|
33
|
-
ActionPack::Instrumentation.instance.config
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|