eventboss 1.9.5 → 1.9.7
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 +12 -0
- data/README.md +11 -0
- data/lib/eventboss/error_handlers/sentry.rb +8 -0
- data/lib/eventboss/long_poller.rb +3 -1
- data/lib/eventboss/publisher.rb +35 -6
- data/lib/eventboss/sentry/configure.rb +11 -0
- data/lib/eventboss/sentry/context.rb +35 -0
- data/lib/eventboss/sentry/error_handler.rb +15 -0
- data/lib/eventboss/sentry/integration.rb +15 -0
- data/lib/eventboss/sentry/server_middleware.rb +95 -0
- data/lib/eventboss/version.rb +1 -1
- metadata +6 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 32c271ea01136f0e14f98ae6163f543f58edd8d45dd7cc0aa30c7facfda6fb44
|
4
|
+
data.tar.gz: 7c45094a9e1e205f90759bcf3f11a261cafcef2b9e1e51e65c3948bad9b3ae50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a2e07d2f3c12b4e3f5c5c5c319b9f6663c498b8e398e6da7e955fcec98372601d3f0365d60d9dd32f7ae891d79bc5c6d824fb574f1a85e6d710013106516f434
|
7
|
+
data.tar.gz: 12884bb40cfd6ee48b294e10c4b92ab2cb230ee32274dc3d271a4f348c9bbf174d7a72ed455f314034af8e9579ae97e9e88d67b44a82b47c526b4bfb7b2da52e
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
6
|
|
7
|
+
## [1.9.7]
|
8
|
+
|
9
|
+
- Fix undefined method 'set_data' for nil span in Sentry integration
|
10
|
+
|
11
|
+
## [1.9.6]
|
12
|
+
|
13
|
+
### Added
|
14
|
+
- Enhanced Sentry integration
|
15
|
+
|
16
|
+
### Deprecated
|
17
|
+
- `Eventboss::ErrorHandlers::Sentry` is now deprecated in favor of `Eventboss::Sentry::ErrorHandler`
|
18
|
+
|
7
19
|
## [1.9.2] - 2025-01-21
|
8
20
|
|
9
21
|
- Fix typo in instance var during shut down
|
data/README.md
CHANGED
@@ -157,6 +157,17 @@ Eventboss.configure do |config|
|
|
157
157
|
end
|
158
158
|
```
|
159
159
|
|
160
|
+
### Sentry Integration
|
161
|
+
|
162
|
+
Eventboss provides built-in integration with [Sentry](https://sentry.io/) for error monitoring and performance tracking. The simplest way to enable Sentry integration is to require the configuration module:
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
require 'eventboss/sentry/configure'
|
166
|
+
```
|
167
|
+
|
168
|
+
For more advanced configuration options, you can manually configure the integration. Please inspect [lib/eventboss/sentry/configure.rb](lib/eventboss/sentry/configure.rb) to see options.
|
169
|
+
```
|
170
|
+
|
160
171
|
### Middlewares
|
161
172
|
|
162
173
|
Server middlewares intercept the execution of your `Listeners`. You can use to extract and run common functions on every message received.
|
@@ -1,6 +1,14 @@
|
|
1
1
|
module Eventboss
|
2
2
|
module ErrorHandlers
|
3
3
|
class Sentry
|
4
|
+
def initialize
|
5
|
+
warn "[DEPRECATED] Eventboss::ErrorHandlers::Sentry is deprecated. " \
|
6
|
+
"Use Eventboss::Sentry::ErrorHandler instead. " \
|
7
|
+
"For automatic configuration, require 'eventboss/sentry/configure'. " \
|
8
|
+
"This class will be removed in a future version."
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
4
12
|
def call(exception, context = {})
|
5
13
|
eventboss_context = { component: 'eventboss' }
|
6
14
|
eventboss_context[:action] = context[:processor].class.to_s if context[:processor]
|
@@ -73,7 +73,9 @@ module Eventboss
|
|
73
73
|
@client.receive_message(
|
74
74
|
queue_url: queue.url,
|
75
75
|
max_number_of_messages: 10,
|
76
|
-
wait_time_seconds: TIME_WAIT
|
76
|
+
wait_time_seconds: TIME_WAIT,
|
77
|
+
attribute_names: ['SentTimestamp', 'ApproximateReceiveCount'],
|
78
|
+
message_attribute_names: ['sentry-trace', 'baggage', 'sentry_user']
|
77
79
|
).messages
|
78
80
|
end
|
79
81
|
end
|
data/lib/eventboss/publisher.rb
CHANGED
@@ -10,19 +10,48 @@ module Eventboss
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def publish(payload)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
message: json_payload(payload)
|
17
|
-
)
|
13
|
+
with_sentry_span do
|
14
|
+
sns_client.publish(**build_sns_params(payload))
|
15
|
+
end
|
18
16
|
end
|
19
17
|
|
20
18
|
private
|
21
19
|
|
22
20
|
attr_reader :event_name, :sns_client, :configuration, :source
|
23
21
|
|
22
|
+
def sentry_enabled?
|
23
|
+
defined?(::Eventboss::Sentry::Integration) && ::Sentry.initialized?
|
24
|
+
end
|
25
|
+
|
26
|
+
def build_sns_params(payload)
|
27
|
+
{
|
28
|
+
topic_arn: Topic.build_arn(event_name: event_name, source_app: source),
|
29
|
+
message: json_payload(payload),
|
30
|
+
message_attributes: sentry_enabled? ? build_sns_message_attributes : {}
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def with_sentry_span
|
35
|
+
return yield unless sentry_enabled?
|
36
|
+
|
37
|
+
queue_name = Queue.build_name(destination: source, event_name: event_name, env: Eventboss.env, source_app: source)
|
38
|
+
|
39
|
+
::Sentry.with_child_span(op: 'queue.publish', description: "Eventboss push #{source}/#{event_name}") do |span|
|
40
|
+
span.set_data(::Sentry::Span::DataConventions::MESSAGING_DESTINATION_NAME, ::Eventboss::Sentry::Context.queue_name_for_sentry(queue_name)) if span
|
41
|
+
|
42
|
+
message = yield
|
43
|
+
|
44
|
+
span.set_data(::Sentry::Span::DataConventions::MESSAGING_MESSAGE_ID, message.message_id) if span
|
45
|
+
message
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
24
49
|
def json_payload(payload)
|
25
50
|
payload.is_a?(String) ? payload : payload.to_json
|
26
51
|
end
|
52
|
+
|
53
|
+
def build_sns_message_attributes
|
54
|
+
::Eventboss::Sentry::Context.build_sns_message_attributes
|
55
|
+
end
|
27
56
|
end
|
28
|
-
end
|
57
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'integration'
|
4
|
+
|
5
|
+
# Auto configure eventboss to use sentry
|
6
|
+
|
7
|
+
Eventboss.configure do |config|
|
8
|
+
config.server_middleware.add Eventboss::Sentry::ServerMiddleware
|
9
|
+
config.error_handlers << Eventboss::Sentry::ErrorHandler.new
|
10
|
+
end
|
11
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Eventboss
|
2
|
+
module Sentry
|
3
|
+
class Context
|
4
|
+
# since sentry has env selector, we can remove it from queue names
|
5
|
+
QUEUES_WITHOUT_ENV = Hash.new do |hash, key|
|
6
|
+
hash[key] = key
|
7
|
+
.gsub(/-#{Eventboss.env}-deadletter$/, '-ENV-deadletter')
|
8
|
+
.gsub(/-#{Eventboss.env}$/, '-ENV')
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.queue_name_for_sentry(queue_name)
|
12
|
+
QUEUES_WITHOUT_ENV[queue_name]
|
13
|
+
end
|
14
|
+
|
15
|
+
# Constructs SNS message attributes for Sentry trace propagation.
|
16
|
+
def self.build_sns_message_attributes
|
17
|
+
attributes = ::Sentry.get_trace_propagation_headers
|
18
|
+
.slice('sentry-trace', 'baggage')
|
19
|
+
.transform_values do |header_value|
|
20
|
+
{ string_value: header_value, data_type: 'String' }
|
21
|
+
end
|
22
|
+
|
23
|
+
user = ::Sentry.get_current_scope&.user
|
24
|
+
if user && !user.empty?
|
25
|
+
attributes['sentry_user'] = {
|
26
|
+
string_value: user.to_json,
|
27
|
+
data_type: 'String'
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
attributes
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Eventboss
|
2
|
+
module Sentry
|
3
|
+
class ErrorHandler
|
4
|
+
def call(exception, _context = {})
|
5
|
+
return unless ::Sentry.initialized?
|
6
|
+
|
7
|
+
Eventboss::Sentry::Integration.capture_exception(
|
8
|
+
exception,
|
9
|
+
contexts: { eventboss: { } },
|
10
|
+
hint: { background: false }
|
11
|
+
)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'sentry-ruby'
|
2
|
+
require 'sentry/integrable'
|
3
|
+
require_relative 'error_handler'
|
4
|
+
require_relative 'context'
|
5
|
+
require_relative 'server_middleware'
|
6
|
+
|
7
|
+
module Eventboss
|
8
|
+
module Sentry
|
9
|
+
class Integration
|
10
|
+
extend ::Sentry::Integrable
|
11
|
+
|
12
|
+
register_integration name: "eventboss", version: Eventboss::VERSION
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Eventboss
|
2
|
+
module Sentry
|
3
|
+
class ServerMiddleware < Eventboss::Middleware::Base
|
4
|
+
OP_NAME = 'queue.process'
|
5
|
+
SPAN_ORIGIN = 'auto.queue.eventboss'
|
6
|
+
|
7
|
+
def call(work)
|
8
|
+
return yield unless ::Sentry.initialized?
|
9
|
+
|
10
|
+
::Sentry.clone_hub_to_current_thread
|
11
|
+
scope = ::Sentry.get_current_scope
|
12
|
+
scope.clear
|
13
|
+
if (user = extract_sentry_user(work))
|
14
|
+
scope.set_user(user)
|
15
|
+
end
|
16
|
+
scope.set_tags(queue: extract_queue_name(work), message_id: work.message.message_id)
|
17
|
+
scope.set_transaction_name(extract_transaction_name(work), source: :task)
|
18
|
+
transaction = start_transaction(scope, work)
|
19
|
+
|
20
|
+
if transaction
|
21
|
+
scope.set_span(transaction)
|
22
|
+
transaction.set_data(::Sentry::Span::DataConventions::MESSAGING_MESSAGE_ID, work.message.message_id)
|
23
|
+
transaction.set_data(::Sentry::Span::DataConventions::MESSAGING_DESTINATION_NAME, extract_queue_name(work))
|
24
|
+
|
25
|
+
if (latency = extract_latency(work.message))
|
26
|
+
transaction.set_data(::Sentry::Span::DataConventions::MESSAGING_MESSAGE_RECEIVE_LATENCY, latency)
|
27
|
+
end
|
28
|
+
|
29
|
+
if (retry_count = extract_receive_count(work.message))
|
30
|
+
transaction.set_data(::Sentry::Span::DataConventions::MESSAGING_MESSAGE_RETRY_COUNT, retry_count)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
begin
|
35
|
+
yield
|
36
|
+
rescue StandardError
|
37
|
+
finish_transaction(transaction, 500)
|
38
|
+
raise
|
39
|
+
end
|
40
|
+
|
41
|
+
finish_transaction(transaction, 200)
|
42
|
+
end
|
43
|
+
|
44
|
+
def start_transaction(scope, work)
|
45
|
+
options = {
|
46
|
+
name: scope.transaction_name,
|
47
|
+
source: scope.transaction_source,
|
48
|
+
op: OP_NAME,
|
49
|
+
origin: SPAN_ORIGIN
|
50
|
+
}
|
51
|
+
|
52
|
+
env = {
|
53
|
+
'sentry-trace' => work.message.message_attributes['sentry-trace']&.string_value,
|
54
|
+
'baggage' => work.message.message_attributes['baggage']&.string_value
|
55
|
+
}
|
56
|
+
|
57
|
+
transaction = ::Sentry.continue_trace(env, **options)
|
58
|
+
::Sentry.start_transaction(transaction: transaction, **options)
|
59
|
+
end
|
60
|
+
|
61
|
+
def finish_transaction(transaction, status)
|
62
|
+
return unless transaction
|
63
|
+
|
64
|
+
transaction.set_http_status(status)
|
65
|
+
transaction.finish
|
66
|
+
end
|
67
|
+
|
68
|
+
def extract_sentry_user(work)
|
69
|
+
if (value = work.message.message_attributes["sentry_user"]&.string_value)
|
70
|
+
JSON.parse(value)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def extract_transaction_name(work)
|
75
|
+
"Eventboss/#{work.listener.to_s}"
|
76
|
+
end
|
77
|
+
|
78
|
+
def extract_queue_name(work)
|
79
|
+
::Eventboss::Sentry::Context.queue_name_for_sentry(work.queue.name)
|
80
|
+
end
|
81
|
+
|
82
|
+
def extract_latency(message)
|
83
|
+
if sent_timestamp = message.attributes.fetch('SentTimestamp', nil)
|
84
|
+
Time.now - Time.at(sent_timestamp.to_i / 1000.0)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def extract_receive_count(message)
|
89
|
+
if receive_count = message.attributes.fetch('ApproximateReceiveCount', nil)
|
90
|
+
receive_count.to_i - 1
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/lib/eventboss/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eventboss
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.9.
|
4
|
+
version: 1.9.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- AirHelp
|
@@ -157,6 +157,11 @@ files:
|
|
157
157
|
- lib/eventboss/safe_thread.rb
|
158
158
|
- lib/eventboss/scripts.rb
|
159
159
|
- lib/eventboss/sender.rb
|
160
|
+
- lib/eventboss/sentry/configure.rb
|
161
|
+
- lib/eventboss/sentry/context.rb
|
162
|
+
- lib/eventboss/sentry/error_handler.rb
|
163
|
+
- lib/eventboss/sentry/integration.rb
|
164
|
+
- lib/eventboss/sentry/server_middleware.rb
|
160
165
|
- lib/eventboss/sns_client.rb
|
161
166
|
- lib/eventboss/topic.rb
|
162
167
|
- lib/eventboss/unit_of_work.rb
|