rage-rb 1.19.1 → 1.20.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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/Appraisals +19 -0
  4. data/CHANGELOG.md +20 -0
  5. data/CODE_OF_CONDUCT.md +13 -17
  6. data/Gemfile +3 -0
  7. data/README.md +60 -63
  8. data/Rakefile +14 -0
  9. data/lib/rage/all.rb +3 -0
  10. data/lib/rage/cable/cable.rb +11 -7
  11. data/lib/rage/cable/channel.rb +6 -1
  12. data/lib/rage/cable/connection.rb +4 -0
  13. data/lib/rage/cable/router.rb +14 -9
  14. data/lib/rage/configuration.rb +235 -21
  15. data/lib/rage/controller/api.rb +50 -45
  16. data/lib/rage/cookies.rb +7 -23
  17. data/lib/rage/deferred/context.rb +30 -2
  18. data/lib/rage/deferred/deferred.rb +18 -6
  19. data/lib/rage/deferred/metadata.rb +39 -0
  20. data/lib/rage/deferred/middleware_chain.rb +67 -0
  21. data/lib/rage/deferred/task.rb +45 -17
  22. data/lib/rage/events/events.rb +3 -3
  23. data/lib/rage/events/subscriber.rb +36 -25
  24. data/lib/rage/fiber.rb +33 -31
  25. data/lib/rage/fiber_scheduler.rb +6 -2
  26. data/lib/rage/logger/logger.rb +7 -1
  27. data/lib/rage/middleware/body_finalizer.rb +14 -0
  28. data/lib/rage/middleware/cors.rb +12 -12
  29. data/lib/rage/middleware/request_id.rb +1 -1
  30. data/lib/rage/openapi/openapi.rb +2 -2
  31. data/lib/rage/response.rb +12 -7
  32. data/lib/rage/rspec.rb +17 -17
  33. data/lib/rage/setup.rb +2 -2
  34. data/lib/rage/telemetry/handler.rb +131 -0
  35. data/lib/rage/telemetry/spans/await_fiber.rb +50 -0
  36. data/lib/rage/telemetry/spans/broadcast_cable_stream.rb +50 -0
  37. data/lib/rage/telemetry/spans/create_websocket_connection.rb +50 -0
  38. data/lib/rage/telemetry/spans/dispatch_fiber.rb +48 -0
  39. data/lib/rage/telemetry/spans/enqueue_deferred_task.rb +52 -0
  40. data/lib/rage/telemetry/spans/process_cable_action.rb +56 -0
  41. data/lib/rage/telemetry/spans/process_cable_connection.rb +56 -0
  42. data/lib/rage/telemetry/spans/process_controller_action.rb +56 -0
  43. data/lib/rage/telemetry/spans/process_deferred_task.rb +54 -0
  44. data/lib/rage/telemetry/spans/process_event_subscriber.rb +54 -0
  45. data/lib/rage/telemetry/spans/publish_event.rb +54 -0
  46. data/lib/rage/telemetry/spans/spawn_fiber.rb +50 -0
  47. data/lib/rage/telemetry/telemetry.rb +121 -0
  48. data/lib/rage/telemetry/tracer.rb +97 -0
  49. data/lib/rage/version.rb +1 -1
  50. data/rage.gemspec +5 -4
  51. metadata +42 -9
@@ -0,0 +1,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # The class allows developers to define telemetry handlers that observe and react to specific span executions.
5
+ #
6
+ # Handlers are defined by subclassing `Rage::Telemetry::Handler` and using the `handle` class method
7
+ # to specify which spans to observe and which methods to invoke when those spans are executed.
8
+ #
9
+ # See {Rage::Telemetry::Spans} for a list of available spans and arguments passed to the handler methods.
10
+ #
11
+ # Each handler method is expected to call `yield` to pass control to the next handler in the stack or the framework's core logic.
12
+ # The call to `yield` returns an instance of {Rage::Telemetry::SpanResult} which contains information about the span execution.
13
+ #
14
+ # @example
15
+ # class MyTelemetryHandler < Rage::Telemetry::Handler
16
+ # handle "controller.action.process", with: :create_span
17
+ #
18
+ # def create_span(name:)
19
+ # MyObservabilitySDK.in_span(name) do
20
+ # yield
21
+ # end
22
+ # end
23
+ # end
24
+ #
25
+ class Rage::Telemetry::Handler
26
+ class << self
27
+ # @private
28
+ attr_accessor :handlers_map
29
+
30
+ # Defines which spans the handler will observe and which method to invoke for those spans.
31
+ #
32
+ # @param span_ids [Array<String>] one or more span IDs to observe; supports wildcards (`*`) to match multiple spans
33
+ # @param with [Symbol] the method name to invoke when the specified spans are executed
34
+ # @param except [String, Array<String>, nil] optional list of span IDs to exclude from observation; supports wildcards (`*`) to match multiple spans
35
+ # @raise [ArgumentError] if any specified span ID is unknown or if no spans match a wildcard ID
36
+ #
37
+ # @example Observe a specific span
38
+ # class MyTelemetryHandler < Rage::Telemetry::Handler
39
+ # handle "controller.action.process", with: :my_handler_method
40
+ #
41
+ # def my_handler_method
42
+ # # ...
43
+ # end
44
+ # end
45
+ #
46
+ # @example Observe multiple spans with wildcards
47
+ # class MyTelemetryHandler < Rage::Telemetry::Handler
48
+ # handle "cable.*", with: :my_handler_method
49
+ #
50
+ # def my_handler_method
51
+ # # ...
52
+ # end
53
+ # end
54
+ #
55
+ # @example Observe all spans except specific ones
56
+ # class MyTelemetryHandler < Rage::Telemetry::Handler
57
+ # handle "*", except: "core.fiber.dispatch", with: :my_handler_method
58
+ #
59
+ # def my_handler_method
60
+ # # ...
61
+ # end
62
+ # end
63
+ #
64
+ def handle(*span_ids, with:, except: nil)
65
+ resolved_span_ids = resolve_span_ids(span_ids)
66
+
67
+ if except
68
+ resolved_span_ids -= resolve_span_ids(Array(except))
69
+ end
70
+
71
+ if @handlers_map.nil?
72
+ @handlers_map = {}
73
+ elsif @handlers_map.frozen?
74
+ @handlers_map = @handlers_map.transform_values(&:dup)
75
+ end
76
+
77
+ resolved_span_ids.each do |span_id|
78
+ @handlers_map[span_id] ||= Set.new
79
+ @handlers_map[span_id] << with
80
+ end
81
+ end
82
+
83
+ # @private
84
+ def inherited(klass)
85
+ klass.handlers_map = @handlers_map.freeze
86
+ end
87
+
88
+ private
89
+
90
+ def resolve_span_ids(span_ids)
91
+ all_span_ids = Rage::Telemetry.__registry.keys
92
+ return all_span_ids if span_ids.include?("*")
93
+
94
+ exact_span_ids, wildcard_span_ids = [], []
95
+
96
+ # separate span IDs based on whether they contain wildcards
97
+ span_ids.each do |span_id|
98
+ if span_id.include?("*")
99
+ wildcard_span_ids << span_id
100
+ else
101
+ exact_span_ids << span_id
102
+ end
103
+ end
104
+
105
+ # validate exact span IDs
106
+ resolved_span_ids = []
107
+
108
+ exact_span_ids.each do |span_id|
109
+ unless all_span_ids.include?(span_id)
110
+ raise ArgumentError, "Unknown span ID '#{span_id}'"
111
+ end
112
+
113
+ resolved_span_ids << span_id
114
+ end
115
+
116
+ # validate and resolve wildcard span IDs
117
+ wildcard_span_ids.each do |span_id|
118
+ matcher = Regexp.new(span_id.gsub("*", "\\w+").gsub(".", "\\."))
119
+ matched_span_ids = all_span_ids.select { |id| id.match?(matcher) }
120
+
121
+ unless matched_span_ids.any?
122
+ raise ArgumentError, "No spans match the wildcard ID '#{span_id}'"
123
+ end
124
+
125
+ resolved_span_ids += matched_span_ids
126
+ end
127
+
128
+ resolved_span_ids
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # The **core.fiber.await** span wraps the processing of the {Fiber.await} call.
5
+ #
6
+ # This span is started when a fiber begins awaiting other fibers, and ends when all awaited fibers have completed.
7
+ # See {handle handle} for the list of arguments passed to handler methods.
8
+ #
9
+ # @see Rage::Telemetry::Handler Rage::Telemetry::Handler
10
+ #
11
+ class Rage::Telemetry::Spans::AwaitFiber
12
+ class << self
13
+ # @private
14
+ def id
15
+ "core.fiber.await"
16
+ end
17
+
18
+ # @private
19
+ def span_parameters
20
+ %w[fibers:]
21
+ end
22
+
23
+ # @private
24
+ def handler_arguments
25
+ {
26
+ name: '"Fiber.await"',
27
+ fibers: "Array(fibers)"
28
+ }
29
+ end
30
+
31
+ # @!parse [ruby]
32
+ # # @param id ["core.fiber.await"] ID of the span
33
+ # # @param name ["Fiber.await"] human-readable name of the operation
34
+ # # @param fibers [Array<Fiber>] the fibers the current fiber is awaiting
35
+ # # @yieldreturn [Rage::Telemetry::SpanResult]
36
+ # #
37
+ # # @example
38
+ # # class MyTelemetryHandler < Rage::Telemetry::Handler
39
+ # # handle "core.fiber.await", with: :my_handler
40
+ # #
41
+ # # def my_handler(id:, name:, fibers:)
42
+ # # yield
43
+ # # end
44
+ # # end
45
+ # # @note Rage automatically detects which parameters your handler method accepts and only passes those parameters.
46
+ # # You can omit any of the parameters described here.
47
+ # def handle(id:, name:, fibers:)
48
+ # end
49
+ end
50
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # The **cable.stream.broadcast** span wraps the process of broadcasting a message to a `Rage::Cable` stream.
5
+ #
6
+ # This span is started when {Rage::Cable.broadcast Rage::Cable.broadcast} is called, and ends when the broadcast operation is complete.
7
+ # See {handle handle} for the list of arguments passed to handler methods.
8
+ #
9
+ # @see Rage::Telemetry::Handler Rage::Telemetry::Handler
10
+ #
11
+ class Rage::Telemetry::Spans::BroadcastCableStream
12
+ class << self
13
+ # @private
14
+ def id
15
+ "cable.stream.broadcast"
16
+ end
17
+
18
+ # @private
19
+ def span_parameters
20
+ %w[stream:]
21
+ end
22
+
23
+ # @private
24
+ def handler_arguments
25
+ {
26
+ name: '"Rage::Cable.broadcast"',
27
+ stream: "stream"
28
+ }
29
+ end
30
+
31
+ # @!parse [ruby]
32
+ # # @param id ["cable.stream.broadcast"] ID of the span
33
+ # # @param name ["Rage::Cable.broadcast"] human-readable name of the operation
34
+ # # @param stream [String] the name of the stream to which the message is being broadcasted
35
+ # # @yieldreturn [Rage::Telemetry::SpanResult]
36
+ # #
37
+ # # @example
38
+ # # class MyTelemetryHandler < Rage::Telemetry::Handler
39
+ # # handle "cable.stream.broadcast", with: :my_handler
40
+ # #
41
+ # # def my_handler(id:, name:, stream:)
42
+ # # yield
43
+ # # end
44
+ # # end
45
+ # # @note Rage automatically detects which parameters your handler method accepts and only passes those parameters.
46
+ # # You can omit any of the parameters described here.
47
+ # def handle(id:, name:, stream:)
48
+ # end
49
+ end
50
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # The **cable.websocket.handshake** span wraps the WebSocket connection handshake process.
5
+ #
6
+ # This span is started when a WebSocket connection is being established and is finished once the handshake is complete.
7
+ # See {handle handle} for the list of arguments passed to handler methods.
8
+ #
9
+ # @see Rage::Telemetry::Handler Rage::Telemetry::Handler
10
+ #
11
+ class Rage::Telemetry::Spans::CreateWebsocketConnection
12
+ class << self
13
+ # @private
14
+ def id
15
+ "cable.websocket.handshake"
16
+ end
17
+
18
+ # @private
19
+ def span_parameters
20
+ %w[env:]
21
+ end
22
+
23
+ # @private
24
+ def handler_arguments
25
+ {
26
+ name: '"WebSocket.handshake"',
27
+ env: "env"
28
+ }
29
+ end
30
+
31
+ # @!parse [ruby]
32
+ # # @param id ["cable.websocket.handshake"] ID of the span
33
+ # # @param name ["WebSocket.handshake"] human-readable name of the operation
34
+ # # @param env [Hash] Rack environment hash that will be attached to the underlying WebSocket connection, allowing you to associate arbitrary data with the connection
35
+ # # @yieldreturn [Rage::Telemetry::SpanResult]
36
+ # #
37
+ # # @example
38
+ # # class MyTelemetryHandler < Rage::Telemetry::Handler
39
+ # # handle "cable.websocket.handshake", with: :my_handler
40
+ # #
41
+ # # def my_handler(id:, name:, env:)
42
+ # # yield
43
+ # # end
44
+ # # end
45
+ # # @note Rage automatically detects which parameters your handler method accepts and only passes those parameters.
46
+ # # You can omit any of the parameters described here.
47
+ # def handle(id:, name:, env:)
48
+ # end
49
+ end
50
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # The **core.fiber.dispatch** span tracks the scheduling and processing of system-level fibers created by the framework to process requests and deferred tasks.
5
+ #
6
+ # This span is started when a system fiber begins processing and ends when the fiber has completed processing.
7
+ # See {handle handle} for the list of arguments passed to handler methods.
8
+ #
9
+ # @see Rage::Telemetry::Handler Rage::Telemetry::Handler
10
+ #
11
+ class Rage::Telemetry::Spans::DispatchFiber
12
+ class << self
13
+ # @private
14
+ def id
15
+ "core.fiber.dispatch"
16
+ end
17
+
18
+ # @private
19
+ def span_parameters
20
+ []
21
+ end
22
+
23
+ # @private
24
+ def handler_arguments
25
+ {
26
+ name: '"Fiber.dispatch"'
27
+ }
28
+ end
29
+
30
+ # @!parse [ruby]
31
+ # # @param id ["core.fiber.dispatch"] ID of the span
32
+ # # @param name ["Fiber.dispatch"] human-readable name of the operation
33
+ # # @yieldreturn [Rage::Telemetry::SpanResult]
34
+ # #
35
+ # # @example
36
+ # # class MyTelemetryHandler < Rage::Telemetry::Handler
37
+ # # handle "core.fiber.dispatch", with: :my_handler
38
+ # #
39
+ # # def my_handler(id:, name:)
40
+ # # yield
41
+ # # end
42
+ # # end
43
+ # # @note Rage automatically detects which parameters your handler method accepts and only passes those parameters.
44
+ # # You can omit any of the parameters described here.
45
+ # def handle(id:, name:)
46
+ # end
47
+ end
48
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # The **deferred.task.enqueue** span tracks the enqueuing of a deferred task.
5
+ #
6
+ # This span is triggered when a deferred task is enqueued.
7
+ # See {handle handle} for the list of arguments passed to handler methods.
8
+ #
9
+ # @see Rage::Telemetry::Handler Rage::Telemetry::Handler
10
+ #
11
+ class Rage::Telemetry::Spans::EnqueueDeferredTask
12
+ class << self
13
+ # @private
14
+ def id
15
+ "deferred.task.enqueue"
16
+ end
17
+
18
+ # @private
19
+ def span_parameters
20
+ %w[task_class: context:]
21
+ end
22
+
23
+ # @private
24
+ def handler_arguments
25
+ {
26
+ name: '"#{task_class}#enqueue"',
27
+ task_class: "task_class",
28
+ task_context: "Rage::Deferred::Context.get_or_create_user_context(context)"
29
+ }
30
+ end
31
+
32
+ # @!parse [ruby]
33
+ # # @param id ["deferred.task.enqueue"] ID of the span
34
+ # # @param name [String] human-readable name of the operation (e.g., `SendConfirmationEmail#enqueue`)
35
+ # # @param task_class [Class] the deferred task being enqueued
36
+ # # @param task_context [Hash] the context is serialized together with the deferred task and allows passing data between telemetry handlers or deferred middleware without exposing it to the task itself
37
+ # # @yieldreturn [Rage::Telemetry::SpanResult]
38
+ # #
39
+ # # @example
40
+ # # class MyTelemetryHandler < Rage::Telemetry::Handler
41
+ # # handle "deferred.task.enqueue", with: :my_handler
42
+ # #
43
+ # # def my_handler(id:, name:, task_class:, task_context:)
44
+ # # yield
45
+ # # end
46
+ # # end
47
+ # # @note Rage automatically detects which parameters your handler method accepts and only passes those parameters.
48
+ # # You can omit any of the parameters described here.
49
+ # def handle(id:, name:, task_class:, task_context:)
50
+ # end
51
+ end
52
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # The **cable.action.process** span wraps the processing of a single {Rage::Cable Rage::Cable} channel action.
5
+ #
6
+ # This span is started just before the action method is invoked on the channel, and is ended immediately after the action method returns.
7
+ # See {handle handle} for the list of arguments passed to handler methods.
8
+ #
9
+ # @see Rage::Telemetry::Handler Rage::Telemetry::Handler
10
+ #
11
+ class Rage::Telemetry::Spans::ProcessCableAction
12
+ class << self
13
+ # @private
14
+ def id
15
+ "cable.action.process"
16
+ end
17
+
18
+ # @private
19
+ def span_parameters
20
+ %w[channel: data: action:]
21
+ end
22
+
23
+ # @private
24
+ def handler_arguments
25
+ {
26
+ name: '"#{channel.class}##{action}"',
27
+ channel: "channel",
28
+ action: "action",
29
+ data: "data",
30
+ env: "channel.__connection.env"
31
+ }
32
+ end
33
+
34
+ # @!parse [ruby]
35
+ # # @param id ["cable.action.process"] ID of the span
36
+ # # @param name [String] human-readable name of the operation (e.g., `ChatChannel#receive`)
37
+ # # @param channel [Rage::Cable::Channel] the channel instance processing the action
38
+ # # @param action [Symbol] the name of the action method being invoked
39
+ # # @param data [Hash, nil] the data payload sent with the action
40
+ # # @param env [Hash] the Rack environment associated with the WebSocket connection
41
+ # # @yieldreturn [Rage::Telemetry::SpanResult]
42
+ # #
43
+ # # @example
44
+ # # class MyTelemetryHandler < Rage::Telemetry::Handler
45
+ # # handle "cable.action.process", with: :my_handler
46
+ # #
47
+ # # def my_handler(id:, name:, channel:, action:, data:, env:)
48
+ # # yield
49
+ # # end
50
+ # # end
51
+ # # @note Rage automatically detects which parameters your handler method accepts and only passes those parameters.
52
+ # # You can omit any of the parameters described here.
53
+ # def handle(id:, name:, channel:, action:, data:, env:)
54
+ # end
55
+ end
56
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # The **cable.connection.process** span wraps the processing of a connection action in {Rage::Cable Rage::Cable}.
5
+ #
6
+ # This span is started just before the action method is invoked on the channel, and is ended immediately after the action method returns.
7
+ # See {handle handle} for the list of arguments passed to handler methods.
8
+ #
9
+ # @see Rage::Telemetry::Handler Rage::Telemetry::Handler
10
+ #
11
+ class Rage::Telemetry::Spans::ProcessCableConnection
12
+ class << self
13
+ # @private
14
+ def id
15
+ "cable.connection.process"
16
+ end
17
+
18
+ # @private
19
+ def span_parameters
20
+ %w[connection: env: action:]
21
+ end
22
+
23
+ # @private
24
+ def handler_arguments
25
+ {
26
+ name: '"#{connection.class}##{action}"',
27
+ connection: "connection",
28
+ request: "connection.request",
29
+ action: "action",
30
+ env: "env"
31
+ }
32
+ end
33
+
34
+ # @!parse [ruby]
35
+ # # @param id ["cable.connection.process"] ID of the span
36
+ # # @param name [String] human-readable name of the operation (e.g., `RageCable::Connection#connect`)
37
+ # # @param connection [Rage::Cable::Connection] the connection being processed
38
+ # # @param request [Rage::Request] the request object associated with the WebSocket connection
39
+ # # @param action [:connect, :disconnect] the action being performed on the connection
40
+ # # @param env [Hash] the Rack environment associated with the WebSocket connection
41
+ # # @yieldreturn [Rage::Telemetry::SpanResult]
42
+ # #
43
+ # # @example
44
+ # # class MyTelemetryHandler < Rage::Telemetry::Handler
45
+ # # handle "cable.connection.process", with: :my_handler
46
+ # #
47
+ # # def my_handler(id:, name:, connection:, request:, action:, env:)
48
+ # # yield
49
+ # # end
50
+ # # end
51
+ # # @note Rage automatically detects which parameters your handler method accepts and only passes those parameters.
52
+ # # You can omit any of the parameters described here.
53
+ # def handle(id:, name:, connection:, request:, action:, env:)
54
+ # end
55
+ end
56
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # The **controller.action.process** span wraps the processing of a controller action.
5
+ #
6
+ # This span is emitted for every controller action that is executed.
7
+ # See {handle handle} for the list of arguments passed to handler methods.
8
+ #
9
+ # @see Rage::Telemetry::Handler Rage::Telemetry::Handler
10
+ #
11
+ class Rage::Telemetry::Spans::ProcessControllerAction
12
+ class << self
13
+ # @private
14
+ def id
15
+ "controller.action.process"
16
+ end
17
+
18
+ # @private
19
+ def span_parameters
20
+ %w[controller: params:]
21
+ end
22
+
23
+ # @private
24
+ def handler_arguments
25
+ {
26
+ name: '"#{controller.class}##{params[:action]}"',
27
+ controller: "controller",
28
+ request: "controller.request",
29
+ response: "controller.response",
30
+ env: "controller.__env"
31
+ }
32
+ end
33
+
34
+ # @!parse [ruby]
35
+ # # @param id ["controller.action.process"] ID of the span
36
+ # # @param name [String] human-readable name of the operation (e.g., `"UsersController#index"`)
37
+ # # @param controller [RageController::API] the controller instance being executed
38
+ # # @param request [Rage::Request] the request object associated with the action
39
+ # # @param response [Rage::Response] the response object associated with the action
40
+ # # @param env [Hash] the Rack environment
41
+ # # @yieldreturn [Rage::Telemetry::SpanResult]
42
+ # #
43
+ # # @example
44
+ # # class MyTelemetryHandler < Rage::Telemetry::Handler
45
+ # # handle "controller.action.process", with: :my_handler
46
+ # #
47
+ # # def my_handler(id:, name:, controller:, request:, response:, env:)
48
+ # # yield
49
+ # # end
50
+ # # end
51
+ # # @note Rage automatically detects which parameters your handler method accepts and only passes those parameters.
52
+ # # You can omit any of the parameters described here.
53
+ # def handle(id:, name:, controller:, request:, response:, env:)
54
+ # end
55
+ end
56
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # The **deferred.task.process** span tracks the processing of a deferred task.
5
+ #
6
+ # This span is started when a deferred task begins processing and ends when the task has completed processing.
7
+ # See {handle handle} for the list of arguments passed to handler methods.
8
+ #
9
+ # @see Rage::Telemetry::Handler Rage::Telemetry::Handler
10
+ #
11
+ class Rage::Telemetry::Spans::ProcessDeferredTask
12
+ class << self
13
+ # @private
14
+ def id
15
+ "deferred.task.process"
16
+ end
17
+
18
+ # @private
19
+ def span_parameters
20
+ %w[task: context:]
21
+ end
22
+
23
+ # @private
24
+ def handler_arguments
25
+ {
26
+ name: '"#{task.class}#perform"',
27
+ task: "task",
28
+ task_class: "task.class",
29
+ task_context: "Rage::Deferred::Context.get_or_create_user_context(context)"
30
+ }
31
+ end
32
+
33
+ # @!parse [ruby]
34
+ # # @param id ["deferred.task.process"] ID of the span
35
+ # # @param name [String] human-readable name of the operation (e.g., `SendConfirmationEmail#perform`)
36
+ # # @param task [Rage::Deferred::Task] the deferred task being processed
37
+ # # @param task_class [Class] the class of the deferred task being processed
38
+ # # @param task_context [Hash] the context is serialized together with the deferred task and allows passing data between telemetry handlers or deferred middleware without exposing it to the task itself
39
+ # # @yieldreturn [Rage::Telemetry::SpanResult]
40
+ # #
41
+ # # @example
42
+ # # class MyTelemetryHandler < Rage::Telemetry::Handler
43
+ # # handle "deferred.task.process", with: :my_handler
44
+ # #
45
+ # # def my_handler(id:, name:, task:, task_class:, task_context:)
46
+ # # yield
47
+ # # end
48
+ # # end
49
+ # # @note Rage automatically detects which parameters your handler method accepts and only passes those parameters.
50
+ # # You can omit any of the parameters described here.
51
+ # def handle(id:, name:, task:, task_class:, task_context:)
52
+ # end
53
+ end
54
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # The **events.subscriber.process** span tracks the processing of an event by a subscriber.
5
+ #
6
+ # This span is started when an event begins processing by a subscriber and ends when the processing has completed.
7
+ # See {handle handle} for the list of arguments passed to handler methods.
8
+ #
9
+ # @see Rage::Telemetry::Handler Rage::Telemetry::Handler
10
+ #
11
+ class Rage::Telemetry::Spans::ProcessEventSubscriber
12
+ class << self
13
+ # @private
14
+ def id
15
+ "events.subscriber.process"
16
+ end
17
+
18
+ # @private
19
+ def span_parameters
20
+ %w[event: context: subscriber:]
21
+ end
22
+
23
+ # @private
24
+ def handler_arguments
25
+ {
26
+ name: '"#{subscriber.class}#call"',
27
+ subscriber: "subscriber",
28
+ event: "event",
29
+ context: "context"
30
+ }
31
+ end
32
+
33
+ # @!parse [ruby]
34
+ # # @param id ["events.subscriber.process"] ID of the span
35
+ # # @param name [String] human-readable name of the operation (e.g., `UpdateRecommendations#call`)
36
+ # # @param subscriber [Rage::Events::Subscriber] the subscriber instance processing the event
37
+ # # @param event [Object] the event being processed
38
+ # # @param context [Object, nil] the additional context passed along with the event
39
+ # # @yieldreturn [Rage::Telemetry::SpanResult]
40
+ # #
41
+ # # @example
42
+ # # class MyTelemetryHandler < Rage::Telemetry::Handler
43
+ # # handle "events.subscriber.process", with: :my_handler
44
+ # #
45
+ # # def my_handler(id:, name:, subscriber:, event:, context:)
46
+ # # yield
47
+ # # end
48
+ # # end
49
+ # # @note Rage automatically detects which parameters your handler method accepts and only passes those parameters.
50
+ # # You can omit any of the parameters described here.
51
+ # def handle(id:, name:, subscriber:, event:, context:)
52
+ # end
53
+ end
54
+ end