sentry-ruby 0.1.3 → 4.1.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 +69 -0
- data/Gemfile +6 -1
- data/README.md +88 -8
- data/Rakefile +3 -1
- data/lib/sentry-ruby.rb +38 -3
- data/lib/sentry/background_worker.rb +37 -0
- data/lib/sentry/benchmarks/benchmark_transport.rb +14 -0
- data/lib/sentry/breadcrumb.rb +7 -7
- data/lib/sentry/breadcrumb/sentry_logger.rb +10 -26
- data/lib/sentry/breadcrumb_buffer.rb +2 -5
- data/lib/sentry/client.rb +25 -7
- data/lib/sentry/configuration.rb +88 -87
- data/lib/sentry/dsn.rb +6 -3
- data/lib/sentry/event.rb +32 -26
- data/lib/sentry/hub.rb +13 -2
- data/lib/sentry/interfaces/request.rb +1 -31
- data/lib/sentry/rack.rb +2 -2
- data/lib/sentry/rack/{capture_exception.rb → capture_exceptions.rb} +20 -11
- data/lib/sentry/rack/interface.rb +22 -0
- data/lib/sentry/rake.rb +17 -0
- data/lib/sentry/scope.rb +27 -5
- data/lib/sentry/span.rb +132 -0
- data/lib/sentry/transaction.rb +157 -0
- data/lib/sentry/transaction_event.rb +29 -0
- data/lib/sentry/transport.rb +16 -24
- data/lib/sentry/transport/http_transport.rb +8 -8
- data/lib/sentry/utils/request_id.rb +16 -0
- data/lib/sentry/version.rb +1 -1
- data/sentry-ruby.gemspec +1 -0
- metadata +25 -4
- data/lib/sentry/transport/state.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: 517c3e0bc0ab170dbd508034bf74b3a9ba62a1a32f13a992ba84d65f81249e01
|
4
|
+
data.tar.gz: 8a86690e05e1695f15e2da33002ecd52b4596ef8dbd2e9c0a7461f94a8868906
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3cc45e503a6ed19a5cc507ab0791087e432b612581498e84403fd806e0d9538ff02f57c2fbb64294ba9895514218bca05610f637a8708a752e6eaf42fa61bfaa
|
7
|
+
data.tar.gz: 9eb027f449b6bdee43316e3b78364d1680d56442b5f34ec82b49059a9f28418a51448e24e45318efb022e526b62e067e410a8e78eb3b67678f1e18ce46866004
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,74 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 4.1.0
|
4
|
+
|
5
|
+
- Separate rack integration [#1138](https://github.com/getsentry/sentry-ruby/pull/1138)
|
6
|
+
- Fixes [#1136](https://github.com/getsentry/sentry-ruby/pull/1136)
|
7
|
+
- Fix event sampling [#1144](https://github.com/getsentry/sentry-ruby/pull/1144)
|
8
|
+
- Merge & rename 2 Rack middlewares [#1147](https://github.com/getsentry/sentry-ruby/pull/1147)
|
9
|
+
- Fixes [#1153](https://github.com/getsentry/sentry-ruby/pull/1153)
|
10
|
+
- Removed `Sentry::Rack::Tracing` middleware and renamed `Sentry::Rack::CaptureException` to `Sentry::Rack::CaptureExceptions`.
|
11
|
+
- Deep-copy spans [#1148](https://github.com/getsentry/sentry-ruby/pull/1148)
|
12
|
+
- Move span recorder related code from Span to Transaction [#1149](https://github.com/getsentry/sentry-ruby/pull/1149)
|
13
|
+
- Check SDK initialization before running integrations [#1151](https://github.com/getsentry/sentry-ruby/pull/1151)
|
14
|
+
- Fixes [#1145](https://github.com/getsentry/sentry-ruby/pull/1145)
|
15
|
+
- Refactor transport [#1154](https://github.com/getsentry/sentry-ruby/pull/1154)
|
16
|
+
- Implement non-blocking event sending [#1155](https://github.com/getsentry/sentry-ruby/pull/1155)
|
17
|
+
- Added `background_worker_threads` configuration option.
|
18
|
+
|
19
|
+
### Noticeable Changes
|
20
|
+
|
21
|
+
#### Middleware Changes
|
22
|
+
|
23
|
+
`Sentry::Rack::Tracing` is now removed. And `Sentry::Rack::CaptureException` has been renamed to `Sentry::Rack::CaptureExceptions`.
|
24
|
+
|
25
|
+
#### Events Are Sent Asynchronously
|
26
|
+
|
27
|
+
`sentry-ruby` now sends events asynchronously by default. The functionality works like this:
|
28
|
+
|
29
|
+
1. When the SDK is initialized, a `Sentry::BackgroundWorker` will be initialized too.
|
30
|
+
2. When an event is passed to `Client#capture_event`, instead of sending it directly with `Client#send_event`, we'll let the worker do it.
|
31
|
+
3. The worker will have a number of threads. And the one of the idle threads will pick the job and call `Client#send_event`.
|
32
|
+
- If all the threads are busy, new jobs will be put into a queue, which has a limit of 30.
|
33
|
+
- If the queue size is exceeded, new events will be dropped.
|
34
|
+
|
35
|
+
However, if you still prefer to use your own async approach, that's totally fine. If you have `config.async` set, the worker won't initialize a thread pool and won't be used either.
|
36
|
+
|
37
|
+
This functionality also introduces a new `background_worker_threads` config option. It allows you to decide how many threads should the worker hold. By default, the value will be the number of the processors your machine has. For example, if your machine has 4 processors, the value would be 4.
|
38
|
+
|
39
|
+
Of course, you can always override the value to fit your use cases, like
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
config.background_worker_threads = 5 # the worker will have 5 threads for sending events
|
43
|
+
```
|
44
|
+
|
45
|
+
You can also disable this new non-blocking behaviour by giving a `0` value:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
config.background_worker_threads = 0 # all events will be sent synchronously
|
49
|
+
```
|
50
|
+
|
51
|
+
## 4.0.1
|
52
|
+
|
53
|
+
- Add rake integration: [1137](https://github.com/getsentry/sentry-ruby/pull/1137)
|
54
|
+
- Make Event's interfaces accessible: [1135](https://github.com/getsentry/sentry-ruby/pull/1135)
|
55
|
+
- ActiveSupportLogger should only record events that has a started time: [1132](https://github.com/getsentry/sentry-ruby/pull/1132)
|
56
|
+
|
57
|
+
## 4.0.0
|
58
|
+
|
59
|
+
- Only documents update for the official release and no API/feature changes.
|
60
|
+
|
61
|
+
## 0.3.0
|
62
|
+
|
63
|
+
- Major API changes: [1123](https://github.com/getsentry/sentry-ruby/pull/1123)
|
64
|
+
- Support event hint: [1122](https://github.com/getsentry/sentry-ruby/pull/1122)
|
65
|
+
- Add request-id tag to events: [1120](https://github.com/getsentry/sentry-ruby/pull/1120) (by @tvec)
|
66
|
+
|
67
|
+
## 0.2.0
|
68
|
+
|
69
|
+
- Multiple fixes and refactorings
|
70
|
+
- Tracing support
|
71
|
+
|
3
72
|
## 0.1.3
|
4
73
|
|
5
74
|
Fix require reference
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -7,6 +7,8 @@
|
|
7
7
|
|
8
8
|
# sentry-ruby, the Ruby Client for Sentry
|
9
9
|
|
10
|
+
**The old `sentry-raven` client has entered maintenance mode and was moved to [here](https://github.com/getsentry/sentry-ruby/tree/master/sentry-raven).**
|
11
|
+
|
10
12
|
---
|
11
13
|
|
12
14
|
|
@@ -17,7 +19,7 @@
|
|
17
19
|
[![SemVer](https://api.dependabot.com/badges/compatibility_score?dependency-name=sentry-ruby&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=sentry-ruby&package-manager=bundler&version-scheme=semver)
|
18
20
|
|
19
21
|
|
20
|
-
[Documentation](https://docs.sentry.io/
|
22
|
+
[Documentation](https://docs.sentry.io/platforms/ruby/) | [Bug Tracker](https://github.com/getsentry/sentry-ruby/issues) | [Forum](https://forum.sentry.io/) | IRC: irc.freenode.net, #sentry
|
21
23
|
|
22
24
|
The official Ruby-language client and integration layer for the [Sentry](https://github.com/getsentry/sentry) error reporting API.
|
23
25
|
|
@@ -26,6 +28,10 @@ The official Ruby-language client and integration layer for the [Sentry](https:/
|
|
26
28
|
|
27
29
|
We test on Ruby 2.4, 2.5, 2.6 and 2.7 at the latest patchlevel/teeny version. We also support JRuby 9.0.
|
28
30
|
|
31
|
+
## Migrate From sentry-raven
|
32
|
+
|
33
|
+
If you're using `sentry-raven`, we recommend you to migrate to this new SDK. You can find the benefits of migrating and how to do it in our [migration guide](https://docs.sentry.io/platforms/ruby/migration/).
|
34
|
+
|
29
35
|
## Getting Started
|
30
36
|
|
31
37
|
### Install
|
@@ -70,17 +76,46 @@ Sentry.init do |config|
|
|
70
76
|
end
|
71
77
|
```
|
72
78
|
|
79
|
+
### Performance Monitoring
|
80
|
+
|
81
|
+
You can activate performance monitoring by enabling traces sampling:
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
Sentry.init do |config|
|
85
|
+
# set a uniform sample rate between 0.0 and 1.0
|
86
|
+
config.traces_sample_rate = 0.2
|
87
|
+
|
88
|
+
# or control sampling dynamically
|
89
|
+
config.traces_sampler = lambda do |sampling_context|
|
90
|
+
# sampling_context[:transaction_context] contains the information about the transaction
|
91
|
+
# sampling_context[:parent_sampled] contains the transaction's parent's sample decision
|
92
|
+
true # return value can be a boolean or a float between 0.0 and 1.0
|
93
|
+
end
|
94
|
+
end
|
95
|
+
```
|
96
|
+
|
97
|
+
To lean more about performance monitoring, please visit the [official documentation](https://docs.sentry.io/platforms/ruby/performance).
|
98
|
+
|
73
99
|
### Usage
|
74
100
|
|
75
101
|
`sentry-ruby` has a default integration with `Rack`, so you only need to use the middleware in your application like:
|
76
102
|
|
77
|
-
```
|
78
|
-
require 'rack'
|
103
|
+
```ruby
|
79
104
|
require 'sentry-ruby'
|
80
105
|
|
81
|
-
|
106
|
+
Sentry.init do |config|
|
107
|
+
config.dsn = 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
108
|
+
|
109
|
+
# To activate performance monitoring, set one of these options.
|
110
|
+
# We recommend adjusting the value in production:
|
111
|
+
config.traces_sample_rate = 0.5
|
112
|
+
# or
|
113
|
+
config.traces_sampler = lambda do |context|
|
114
|
+
true
|
115
|
+
end
|
116
|
+
end
|
82
117
|
|
83
|
-
|
118
|
+
use Sentry::Rack::CaptureExceptions
|
84
119
|
```
|
85
120
|
|
86
121
|
Otherwise, Sentry you can always use the capture helpers manually
|
@@ -104,9 +139,9 @@ We also provide integrations with popular frameworks/libraries with the related
|
|
104
139
|
|
105
140
|
You're all set - but there's a few more settings you may want to know about too!
|
106
141
|
|
107
|
-
####
|
142
|
+
#### Blocking v.s. Non-blocking
|
108
143
|
|
109
|
-
|
144
|
+
**Before version 4.1.0**, `sentry-ruby` sends every event immediately. But it can be configured to send asynchronously:
|
110
145
|
|
111
146
|
```ruby
|
112
147
|
config.async = lambda { |event|
|
@@ -130,6 +165,41 @@ class SentryJob < ActiveJob::Base
|
|
130
165
|
end
|
131
166
|
```
|
132
167
|
|
168
|
+
|
169
|
+
**After version 4.1.0**, `sentry-ruby` sends events asynchronously by default. The functionality works like this:
|
170
|
+
|
171
|
+
1. When the SDK is initialized, a `Sentry::BackgroundWorker` will be initialized too.
|
172
|
+
2. When an event is passed to `Client#capture_event`, instead of sending it directly with `Client#send_event`, we'll let the worker do it.
|
173
|
+
3. The worker will have a number of threads. And the one of the idle threads will pick the job and call `Client#send_event`.
|
174
|
+
- If all the threads are busy, new jobs will be put into a queue, which has a limit of 30.
|
175
|
+
- If the queue size is exceeded, new events will be dropped.
|
176
|
+
|
177
|
+
However, if you still prefer to use your own async approach, that's totally fine. If you have `config.async` set, the worker won't initialize a thread pool and won't be used either.
|
178
|
+
|
179
|
+
##### About `Sentry::BackgroundWorker`
|
180
|
+
|
181
|
+
- The worker is built on top of the [concurrent-ruby](https://github.com/ruby-concurrency/concurrent-ruby) gem's [ThreadPoolExecutor](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ThreadPoolExecutor.html), which is also used by Rails ActiveJob's async adapter. This should minimize the risk of messing up client applications with our own thread pool implementaion.
|
182
|
+
|
183
|
+
This functionality also introduces a new `background_worker_threads` config option. It allows you to decide how many threads should the worker hold. By default, the value will be the number of the processors your machine has. For example, if your machine has 4 processors, the value would be 4.
|
184
|
+
|
185
|
+
Of course, you can always override the value to fit your use cases, like
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
config.background_worker_threads = 5 # the worker will have 5 threads for sending events
|
189
|
+
```
|
190
|
+
|
191
|
+
You can also disable this new non-blocking behaviour by giving a `0` value:
|
192
|
+
|
193
|
+
```ruby
|
194
|
+
config.background_worker_threads = 0 # all events will be sent synchronously
|
195
|
+
```
|
196
|
+
|
197
|
+
If you want to send a particular event immediately, you can use event hints to do it:
|
198
|
+
|
199
|
+
```ruby
|
200
|
+
Sentry.capture_message("send me now!", hint: { background: false })
|
201
|
+
```
|
202
|
+
|
133
203
|
#### Contexts
|
134
204
|
|
135
205
|
In sentry-ruby, every event will inherit their contextual data from the current scope. So you can enrich the event's data by configuring the current scope like:
|
@@ -148,6 +218,15 @@ end
|
|
148
218
|
Sentry.capture_exception(exception) # the event will carry all those information now
|
149
219
|
```
|
150
220
|
|
221
|
+
Or use top-level setters
|
222
|
+
|
223
|
+
|
224
|
+
```ruby
|
225
|
+
Sentry.set_user(id: 1, email: "test@example.com")
|
226
|
+
Sentry.set_tags(tag_1: "foo", tag_2: "bar")
|
227
|
+
Sentry.set_extras(order_number: 1234, tickets_count: 4)
|
228
|
+
```
|
229
|
+
|
151
230
|
Or build up a temporary scope for local information:
|
152
231
|
|
153
232
|
```ruby
|
@@ -172,7 +251,8 @@ Sentry.capture_exception(exception, tags: {foo: "bar"})
|
|
172
251
|
|
173
252
|
## More Information
|
174
253
|
|
175
|
-
* [Documentation](https://docs.sentry.io/
|
254
|
+
* [Documentation](https://docs.sentry.io/platforms/ruby/)
|
176
255
|
* [Bug Tracker](https://github.com/getsentry/sentry-ruby/issues)
|
177
256
|
* [Forum](https://forum.sentry.io/)
|
178
257
|
- [Discord](https://discord.gg/ez5KZN7)
|
258
|
+
|
data/Rakefile
CHANGED
data/lib/sentry-ruby.rb
CHANGED
@@ -1,10 +1,26 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
require "time"
|
3
|
+
|
1
4
|
require "sentry/version"
|
2
5
|
require "sentry/core_ext/object/deep_dup"
|
3
6
|
require "sentry/configuration"
|
4
7
|
require "sentry/logger"
|
5
8
|
require "sentry/event"
|
9
|
+
require "sentry/transaction_event"
|
10
|
+
require "sentry/span"
|
11
|
+
require "sentry/transaction"
|
6
12
|
require "sentry/hub"
|
7
|
-
require "sentry/
|
13
|
+
require "sentry/background_worker"
|
14
|
+
|
15
|
+
def safely_require(lib)
|
16
|
+
begin
|
17
|
+
require lib
|
18
|
+
rescue LoadError
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
safely_require "sentry/rake"
|
23
|
+
safely_require "sentry/rack"
|
8
24
|
|
9
25
|
module Sentry
|
10
26
|
class Error < StandardError
|
@@ -20,7 +36,17 @@ module Sentry
|
|
20
36
|
META
|
21
37
|
end
|
22
38
|
|
39
|
+
def self.utc_now
|
40
|
+
Time.now.utc
|
41
|
+
end
|
42
|
+
|
23
43
|
class << self
|
44
|
+
extend Forwardable
|
45
|
+
|
46
|
+
def_delegators :get_current_scope, :set_tags, :set_extras, :set_user
|
47
|
+
|
48
|
+
attr_accessor :background_worker
|
49
|
+
|
24
50
|
def init(&block)
|
25
51
|
config = Configuration.new
|
26
52
|
yield(config)
|
@@ -29,6 +55,11 @@ module Sentry
|
|
29
55
|
hub = Hub.new(client, scope)
|
30
56
|
Thread.current[THREAD_LOCAL] = hub
|
31
57
|
@main_hub = hub
|
58
|
+
@background_worker = Sentry::BackgroundWorker.new(config)
|
59
|
+
end
|
60
|
+
|
61
|
+
def initialized?
|
62
|
+
!!@main_hub
|
32
63
|
end
|
33
64
|
|
34
65
|
def get_main_hub
|
@@ -39,8 +70,8 @@ module Sentry
|
|
39
70
|
configuration.logger
|
40
71
|
end
|
41
72
|
|
42
|
-
def
|
43
|
-
get_current_scope.breadcrumbs
|
73
|
+
def add_breadcrumb(breadcrumb, &block)
|
74
|
+
get_current_scope.breadcrumbs.record(breadcrumb, &block)
|
44
75
|
end
|
45
76
|
|
46
77
|
def configuration
|
@@ -92,6 +123,10 @@ module Sentry
|
|
92
123
|
get_current_hub.capture_message(message, **options, &block)
|
93
124
|
end
|
94
125
|
|
126
|
+
def start_transaction(**options)
|
127
|
+
get_current_hub.start_transaction(**options)
|
128
|
+
end
|
129
|
+
|
95
130
|
def last_event_id
|
96
131
|
get_current_hub.last_event_id
|
97
132
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "concurrent/executor/thread_pool_executor"
|
2
|
+
require "concurrent/executor/immediate_executor"
|
3
|
+
|
4
|
+
module Sentry
|
5
|
+
class BackgroundWorker
|
6
|
+
attr_reader :max_queue, :number_of_threads
|
7
|
+
|
8
|
+
def initialize(configuration)
|
9
|
+
@max_queue = 30
|
10
|
+
@number_of_threads = configuration.background_worker_threads
|
11
|
+
|
12
|
+
@executor =
|
13
|
+
if configuration.async?
|
14
|
+
configuration.logger.debug(LOGGER_PROGNAME) { "config.async is set, BackgroundWorker is disabled" }
|
15
|
+
Concurrent::ImmediateExecutor.new
|
16
|
+
elsif @number_of_threads == 0
|
17
|
+
configuration.logger.debug(LOGGER_PROGNAME) { "config.background_worker_threads is set to 0, all events will be sent synchronously" }
|
18
|
+
Concurrent::ImmediateExecutor.new
|
19
|
+
else
|
20
|
+
configuration.logger.debug(LOGGER_PROGNAME) { "initialized a background worker with #{@number_of_threads} threads" }
|
21
|
+
|
22
|
+
Concurrent::ThreadPoolExecutor.new(
|
23
|
+
min_threads: 0,
|
24
|
+
max_threads: @number_of_threads,
|
25
|
+
max_queue: @max_queue,
|
26
|
+
fallback_policy: :discard
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def perform(&block)
|
32
|
+
@executor.post do
|
33
|
+
block.call
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/sentry/breadcrumb.rb
CHANGED
@@ -2,13 +2,13 @@ module Sentry
|
|
2
2
|
class Breadcrumb
|
3
3
|
attr_accessor :category, :data, :message, :level, :timestamp, :type
|
4
4
|
|
5
|
-
def initialize
|
6
|
-
@category =
|
7
|
-
@data = {}
|
8
|
-
@level =
|
9
|
-
@message =
|
10
|
-
@timestamp =
|
11
|
-
@type =
|
5
|
+
def initialize(category: nil, data: nil, message: nil, timestamp: nil, level: nil, type: nil)
|
6
|
+
@category = category
|
7
|
+
@data = data || {}
|
8
|
+
@level = level
|
9
|
+
@message = message
|
10
|
+
@timestamp = timestamp || Sentry.utc_now.to_i
|
11
|
+
@type = type
|
12
12
|
end
|
13
13
|
|
14
14
|
def to_hash
|
@@ -58,17 +58,15 @@ module Sentry
|
|
58
58
|
last_crumb = current_breadcrumbs.peek
|
59
59
|
# try to avoid dupes from logger broadcasts
|
60
60
|
if last_crumb.nil? || last_crumb.message != message
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
end
|
71
|
-
end
|
61
|
+
level = Sentry::Breadcrumb::SentryLogger::LEVELS.fetch(severity, nil)
|
62
|
+
crumb = Sentry::Breadcrumb.new(
|
63
|
+
level: level,
|
64
|
+
category: category,
|
65
|
+
message: message,
|
66
|
+
type: severity >= 3 ? "error" : level
|
67
|
+
)
|
68
|
+
|
69
|
+
Sentry.add_breadcrumb(crumb)
|
72
70
|
end
|
73
71
|
end
|
74
72
|
|
@@ -80,21 +78,7 @@ module Sentry
|
|
80
78
|
end
|
81
79
|
|
82
80
|
def current_breadcrumbs
|
83
|
-
Sentry.breadcrumbs
|
84
|
-
end
|
85
|
-
end
|
86
|
-
module OldBreadcrumbsSentryLogger
|
87
|
-
def self.included(base)
|
88
|
-
base.class_eval do
|
89
|
-
include Sentry::Breadcrumbs::SentryLogger
|
90
|
-
alias_method :add_without_sentry, :add
|
91
|
-
alias_method :add, :add_with_sentry
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def add_with_sentry(*args)
|
96
|
-
add_breadcrumb(*args)
|
97
|
-
add_without_sentry(*args)
|
81
|
+
Sentry.get_current_scope.breadcrumbs
|
98
82
|
end
|
99
83
|
end
|
100
84
|
end
|