sentry-ruby-core 4.4.2 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +2 -0
- data/CHANGELOG.md +2 -0
- data/Gemfile +8 -5
- data/LICENSE.txt +1 -1
- data/README.md +29 -175
- data/bin/console +5 -1
- data/lib/sentry/background_worker.rb +33 -3
- data/lib/sentry/backtrace.rb +1 -3
- data/lib/sentry/breadcrumb/sentry_logger.rb +3 -1
- data/lib/sentry/breadcrumb.rb +28 -2
- data/lib/sentry/breadcrumb_buffer.rb +16 -0
- data/lib/sentry/client.rb +65 -7
- data/lib/sentry/configuration.rb +155 -112
- data/lib/sentry/core_ext/object/deep_dup.rb +4 -0
- data/lib/sentry/core_ext/object/duplicable.rb +2 -0
- data/lib/sentry/dsn.rb +6 -1
- data/lib/sentry/envelope.rb +26 -0
- data/lib/sentry/event.rb +65 -23
- data/lib/sentry/exceptions.rb +2 -0
- data/lib/sentry/hub.rb +31 -5
- data/lib/sentry/integrable.rb +2 -0
- data/lib/sentry/interface.rb +3 -10
- data/lib/sentry/interfaces/exception.rb +13 -3
- data/lib/sentry/interfaces/request.rb +49 -19
- data/lib/sentry/interfaces/single_exception.rb +31 -0
- data/lib/sentry/interfaces/stacktrace.rb +14 -0
- data/lib/sentry/interfaces/stacktrace_builder.rb +39 -10
- data/lib/sentry/interfaces/threads.rb +12 -2
- data/lib/sentry/linecache.rb +3 -0
- data/lib/sentry/net/http.rb +71 -47
- data/lib/sentry/rack/capture_exceptions.rb +2 -0
- data/lib/sentry/rack.rb +2 -1
- data/lib/sentry/rake.rb +33 -9
- data/lib/sentry/release_detector.rb +39 -0
- data/lib/sentry/scope.rb +76 -6
- data/lib/sentry/span.rb +84 -8
- data/lib/sentry/transaction.rb +48 -10
- data/lib/sentry/transaction_event.rb +19 -6
- data/lib/sentry/transport/configuration.rb +4 -2
- data/lib/sentry/transport/dummy_transport.rb +2 -0
- data/lib/sentry/transport/http_transport.rb +57 -38
- data/lib/sentry/transport.rb +80 -19
- data/lib/sentry/utils/argument_checking_helper.rb +2 -0
- data/lib/sentry/utils/custom_inspection.rb +14 -0
- data/lib/sentry/utils/exception_cause_chain.rb +10 -10
- data/lib/sentry/utils/logging_helper.rb +6 -4
- data/lib/sentry/utils/real_ip.rb +9 -1
- data/lib/sentry/utils/request_id.rb +2 -0
- data/lib/sentry/version.rb +3 -1
- data/lib/sentry-ruby.rb +184 -49
- data/sentry-ruby-core.gemspec +2 -3
- data/sentry-ruby.gemspec +2 -3
- metadata +9 -22
- data/.craft.yml +0 -28
- data/lib/sentry/benchmarks/benchmark_transport.rb +0 -14
- data/lib/sentry/rack/deprecations.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f87f499a85374ffedb9efc48ae758ea007a44276d85af7ca7899f4d30d44cd73
|
4
|
+
data.tar.gz: 613088c3759d726b675992785bcfb76996227af0ac5ee04b196140b4f0d17903
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 95bd72a765827b11e63deeb884057e3365590a96e2417185996e4bac3880c2df26daf9fcff36e1c7eb145fbe481b001e6d0113ea7caad8e0f72d88a7e4eb4446
|
7
|
+
data.tar.gz: 39256b355acf287b49bddb5f2e35c2c2fe761723a738165b0a79bd66927a07d5f170a7d6e5eb66dd6e019af8278dbbf0cc6a52238dafa9a3b3bd90e30b805b9e
|
data/.yardopts
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
Individual gem's changelog has been deprecated. Please check the [project changelog](https://github.com/getsentry/sentry-ruby/blob/master/CHANGELOG.md).
|
4
|
+
|
3
5
|
## 4.4.2
|
4
6
|
|
5
7
|
- Fix NoMethodError when SDK's dsn is nil [#1433](https://github.com/getsentry/sentry-ruby/pull/1433)
|
data/Gemfile
CHANGED
@@ -3,21 +3,24 @@ source "https://rubygems.org"
|
|
3
3
|
gem "sentry-ruby-core", path: "./"
|
4
4
|
gem "sentry-ruby", path: "./"
|
5
5
|
|
6
|
-
|
7
|
-
gem "i18n", "<= 1.8.7"
|
6
|
+
gem "rack" unless ENV["WITHOUT_RACK"] == "1"
|
8
7
|
|
9
8
|
gem "rake", "~> 12.0"
|
10
9
|
gem "rspec", "~> 3.0"
|
11
10
|
gem "rspec-retry"
|
12
11
|
gem "webmock"
|
13
12
|
gem "timecop"
|
14
|
-
gem
|
15
|
-
gem "
|
13
|
+
gem 'simplecov'
|
14
|
+
gem "simplecov-cobertura", "~> 1.4"
|
15
|
+
gem "rexml"
|
16
16
|
|
17
|
+
gem "object_tracer"
|
18
|
+
gem "debug", github: "ruby/debug", platform: :ruby if RUBY_VERSION.to_f >= 2.6
|
17
19
|
gem "pry"
|
18
|
-
gem "rack" unless ENV["WITHOUT_RACK"] == "1"
|
19
20
|
|
20
21
|
gem "benchmark-ips"
|
21
22
|
gem "benchmark_driver"
|
22
23
|
gem "benchmark-ipsa"
|
23
24
|
gem "benchmark-memory"
|
25
|
+
|
26
|
+
gem "yard", "~> 0.9.27"
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -10,12 +10,13 @@ _Bad software is everywhere, and we're tired of it. Sentry is on a mission to he
|
|
10
10
|
Sentry SDK for Ruby
|
11
11
|
===========
|
12
12
|
|
13
|
-
| current version | build | coverage | downloads |
|
14
|
-
| --- | ----- | -------- | --------- |
|
15
|
-
| [![Gem Version](https://img.shields.io/gem/v/sentry-ruby?label=sentry-ruby)](https://
|
16
|
-
| [![Gem Version](https://img.shields.io/gem/v/sentry-rails?label=sentry-rails)](https://
|
17
|
-
| [![Gem Version](https://img.shields.io/gem/v/sentry-sidekiq?label=sentry-sidekiq)](https://
|
18
|
-
| [![Gem Version](https://img.shields.io/gem/v/sentry-delayed_job?label=sentry-delayed_job)](https://
|
13
|
+
| current version | build | coverage | downloads |
|
14
|
+
| --- | ----- | -------- | --------- |
|
15
|
+
| [![Gem Version](https://img.shields.io/gem/v/sentry-ruby?label=sentry-ruby)](https://rubygems.org/gems/sentry-ruby) | [![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-ruby%20Test/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_ruby_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-ruby.svg)](https://rubygems.org/gems/sentry-ruby/) |
|
16
|
+
| [![Gem Version](https://img.shields.io/gem/v/sentry-rails?label=sentry-rails)](https://rubygems.org/gems/sentry-rails) | [![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-rails%20Test/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_rails_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-rails.svg)](https://rubygems.org/gems/sentry-rails/) |
|
17
|
+
| [![Gem Version](https://img.shields.io/gem/v/sentry-sidekiq?label=sentry-sidekiq)](https://rubygems.org/gems/sentry-sidekiq) | [![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-sidekiq%20Test/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_sidekiq_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-sidekiq.svg)](https://rubygems.org/gems/sentry-sidekiq/) |
|
18
|
+
| [![Gem Version](https://img.shields.io/gem/v/sentry-delayed_job?label=sentry-delayed_job)](https://rubygems.org/gems/sentry-delayed_job) | [![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-delayed_job%20Test/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_delayed_job_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-delayed_job.svg)](https://rubygems.org/gems/sentry-delayed_job/) |
|
19
|
+
| [![Gem Version](https://img.shields.io/gem/v/sentry-resque?label=sentry-resque)](https://rubygems.org/gems/sentry-resque) | [![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-resque%20Test/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_resque_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-resque.svg)](https://rubygems.org/gems/sentry-resque/) |
|
19
20
|
|
20
21
|
|
21
22
|
|
@@ -46,200 +47,53 @@ and depends on the integrations you want to have, you might also want to install
|
|
46
47
|
gem "sentry-rails"
|
47
48
|
gem "sentry-sidekiq"
|
48
49
|
gem "sentry-delayed_job"
|
49
|
-
|
50
|
+
gem "sentry-resque"
|
50
51
|
```
|
51
52
|
|
52
|
-
###
|
53
|
+
### Configuration
|
53
54
|
|
54
|
-
|
55
|
+
You can use `Sentry.init` to initialize and configure your SDK:
|
55
56
|
|
56
|
-
```bash
|
57
|
-
# Set your SENTRY_DSN environment variable.
|
58
|
-
export SENTRY_DSN=http://public@example.com/project-id
|
59
|
-
```
|
60
57
|
```ruby
|
61
|
-
# Or you can configure the client in the code.
|
62
58
|
Sentry.init do |config|
|
63
|
-
config.dsn =
|
59
|
+
config.dsn = "MY_DSN"
|
64
60
|
end
|
65
|
-
```
|
66
|
-
|
67
|
-
### Sentry doesn't report some kinds of data by default
|
68
|
-
|
69
|
-
**Sentry ignores some exceptions by default** - most of these are related to 404s parameter parsing errors. [For a complete list, see the `IGNORE_DEFAULT` constant](https://github.com/getsentry/sentry-ruby/blob/master/sentry-ruby/lib/sentry/configuration.rb#L151) and the integration gems' `IGNORE_DEFAULT`, like [`sentry-rails`'s](https://github.com/getsentry/sentry-ruby/blob/master/sentry-rails/lib/sentry/rails/configuration.rb#L12)
|
70
|
-
|
71
|
-
Sentry doesn't send personally identifiable information (pii) by default, such as request body, user ip or cookies. If you want those information to be sent, you can use the `send_default_pii` config option:
|
72
61
|
|
73
|
-
```ruby
|
74
|
-
Sentry.init do |config|
|
75
|
-
# other configs
|
76
|
-
config.send_default_pii = true
|
77
|
-
end
|
78
62
|
```
|
79
63
|
|
64
|
+
To learn more about available configuration options, please visit the [official documentation](https://docs.sentry.io/platforms/ruby/configuration/options/).
|
65
|
+
|
80
66
|
### Performance Monitoring
|
81
67
|
|
82
|
-
You can activate performance monitoring by enabling traces sampling:
|
68
|
+
You can activate [performance monitoring](https://docs.sentry.io/platforms/ruby/performance) by enabling traces sampling:
|
83
69
|
|
84
70
|
```ruby
|
85
71
|
Sentry.init do |config|
|
86
72
|
# set a uniform sample rate between 0.0 and 1.0
|
87
73
|
config.traces_sample_rate = 0.2
|
88
|
-
|
89
|
-
#
|
90
|
-
config.traces_sampler = lambda do |sampling_context|
|
91
|
-
# sampling_context[:transaction_context] contains the information about the transaction
|
92
|
-
# sampling_context[:parent_sampled] contains the transaction's parent's sample decision
|
93
|
-
true # return value can be a boolean or a float between 0.0 and 1.0
|
94
|
-
end
|
95
|
-
end
|
96
|
-
```
|
97
|
-
|
98
|
-
To learn more about performance monitoring, please visit the [official documentation](https://docs.sentry.io/platforms/ruby/performance).
|
99
|
-
|
100
|
-
### Usage
|
101
|
-
|
102
|
-
`sentry-ruby` has a default integration with `Rack`, so you only need to use the middleware in your application like:
|
103
|
-
|
104
|
-
```ruby
|
105
|
-
require 'sentry-ruby'
|
106
|
-
|
107
|
-
Sentry.init do |config|
|
108
|
-
config.dsn = 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
109
|
-
|
110
|
-
# To activate performance monitoring, set one of these options.
|
111
|
-
# We recommend adjusting the value in production:
|
112
|
-
config.traces_sample_rate = 0.5
|
113
|
-
# or
|
114
|
-
config.traces_sampler = lambda do |context|
|
115
|
-
true
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
use Sentry::Rack::CaptureExceptions
|
120
|
-
```
|
121
|
-
|
122
|
-
Otherwise, Sentry you can always use the capture helpers manually
|
123
|
-
|
124
|
-
```ruby
|
125
|
-
Sentry.capture_message("hello world!")
|
126
|
-
|
127
|
-
begin
|
128
|
-
1 / 0
|
129
|
-
rescue ZeroDivisionError => exception
|
130
|
-
Sentry.capture_exception(exception)
|
131
|
-
end
|
132
|
-
```
|
133
|
-
|
134
|
-
We also provide integrations with popular frameworks/libraries with the related extensions:
|
135
|
-
|
136
|
-
- [sentry-rails](https://github.com/getsentry/sentry-ruby/tree/master/sentry-rails)
|
137
|
-
- [sentry-sidekiq](https://github.com/getsentry/sentry-ruby/tree/master/sentry-sidekiq)
|
138
|
-
- [sentry-delayed_job](https://github.com/getsentry/sentry-ruby/tree/master/sentry-delayed_job)
|
139
|
-
|
140
|
-
### More configuration
|
141
|
-
|
142
|
-
You're all set - but there's a few more settings you may want to know about too!
|
143
|
-
|
144
|
-
#### Blocking v.s. Non-blocking
|
145
|
-
|
146
|
-
`sentry-ruby` sends events asynchronously by default. The functionality works like this:
|
147
|
-
|
148
|
-
1. When the SDK is initialized, a `Sentry::BackgroundWorker` will be initialized too.
|
149
|
-
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.
|
150
|
-
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`.
|
151
|
-
- If all the threads are busy, new jobs will be put into a queue, which has a limit of 30.
|
152
|
-
- If the queue size is exceeded, new events will be dropped.
|
153
|
-
|
154
|
-
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.
|
155
|
-
|
156
|
-
##### About `Sentry::BackgroundWorker`
|
157
|
-
|
158
|
-
- 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.
|
159
|
-
|
160
|
-
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.
|
161
|
-
|
162
|
-
Of course, you can always override the value to fit your use cases, like
|
163
|
-
|
164
|
-
```ruby
|
165
|
-
config.background_worker_threads = 5 # the worker will have 5 threads for sending events
|
166
|
-
```
|
167
|
-
|
168
|
-
You can also disable this new non-blocking behaviour by giving a `0` value:
|
169
|
-
|
170
|
-
```ruby
|
171
|
-
config.background_worker_threads = 0 # all events will be sent synchronously
|
172
|
-
```
|
173
|
-
|
174
|
-
If you want to send a particular event immediately, you can use event hints to do it:
|
175
|
-
|
176
|
-
```ruby
|
177
|
-
Sentry.capture_message("send me now!", hint: { background: false })
|
178
|
-
```
|
179
|
-
|
180
|
-
##### `config.async`
|
181
|
-
|
182
|
-
You can also use `config.async` to send events with you own worker:
|
183
|
-
|
184
|
-
```ruby
|
185
|
-
config.async = lambda { |event, hint| SentryJob.perform_later(event, hint) }
|
186
|
-
```
|
187
|
-
|
188
|
-
And if you use `sentry-rails`, you can directly use the job we defined for you:
|
189
|
-
|
190
|
-
```ruby
|
191
|
-
config.async = lambda { |event, hint| Sentry::SendEventJob.perform_later(event, hint) }
|
192
|
-
```
|
193
|
-
|
194
|
-
|
195
|
-
#### Contexts
|
196
|
-
|
197
|
-
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:
|
198
|
-
|
199
|
-
```ruby
|
200
|
-
Sentry.configure_scope do |scope|
|
201
|
-
scope.set_user(id: 1, email: "test@example.com")
|
202
|
-
|
203
|
-
scope.set_tag(:tag, "foo")
|
204
|
-
scope.set_tags(tag_1: "foo", tag_2: "bar")
|
205
|
-
|
206
|
-
scope.set_extra(:order_number, 1234)
|
207
|
-
scope.set_extras(order_number: 1234, tickets_count: 4)
|
74
|
+
# you can also use traces_sampler for more fine-grained sampling
|
75
|
+
# please click the link below to learn more
|
208
76
|
end
|
209
|
-
|
210
|
-
Sentry.capture_exception(exception) # the event will carry all those information now
|
211
|
-
```
|
212
|
-
|
213
|
-
Or use top-level setters
|
214
|
-
|
215
|
-
|
216
|
-
```ruby
|
217
|
-
Sentry.set_user(id: 1, email: "test@example.com")
|
218
|
-
Sentry.set_tags(tag_1: "foo", tag_2: "bar")
|
219
|
-
Sentry.set_extras(order_number: 1234, tickets_count: 4)
|
220
77
|
```
|
221
78
|
|
222
|
-
|
223
|
-
|
224
|
-
```ruby
|
225
|
-
Sentry.configure_scope do |scope|
|
226
|
-
scope.set_tags(tag_1: "foo")
|
227
|
-
end
|
79
|
+
To learn more about sampling transactions, please visit the [official documentation](https://docs.sentry.io/platforms/ruby/configuration/sampling/#configuring-the-transaction-sample-rate).
|
228
80
|
|
229
|
-
|
230
|
-
scope.set_tags(tag_1: "bar", tag_2: "baz")
|
81
|
+
### [Migration Guide](https://docs.sentry.io/platforms/ruby/migration/)
|
231
82
|
|
232
|
-
|
233
|
-
end
|
83
|
+
### Integrations
|
234
84
|
|
235
|
-
|
236
|
-
|
85
|
+
- [Rack](https://docs.sentry.io/platforms/ruby/guides/rack/)
|
86
|
+
- [Rails](https://docs.sentry.io/platforms/ruby/guides/rails/)
|
87
|
+
- [Sidekiq](https://docs.sentry.io/platforms/ruby/guides/sidekiq/)
|
88
|
+
- [DelayedJob](https://docs.sentry.io/platforms/ruby/guides/delayed_job/)
|
89
|
+
- [Resque](https://docs.sentry.io/platforms/ruby/guides/resque/)
|
237
90
|
|
238
|
-
|
91
|
+
### Enriching Events
|
239
92
|
|
240
|
-
|
241
|
-
|
242
|
-
|
93
|
+
- [Add more data to the current scope](https://docs.sentry.io/platforms/ruby/guides/rack/enriching-events/scopes/)
|
94
|
+
- [Add custom breadcrumbs](https://docs.sentry.io/platforms/ruby/guides/rack/enriching-events/breadcrumbs/)
|
95
|
+
- [Add contextual data](https://docs.sentry.io/platforms/ruby/guides/rack/enriching-events/context/)
|
96
|
+
- [Add tags](https://docs.sentry.io/platforms/ruby/guides/rack/enriching-events/tags/)
|
243
97
|
|
244
98
|
## Resources
|
245
99
|
|
data/bin/console
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require "bundler/setup"
|
4
|
-
require "sentry
|
4
|
+
require "sentry-ruby"
|
5
5
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -10,5 +10,9 @@ require "sentry/ruby"
|
|
10
10
|
# require "pry"
|
11
11
|
# Pry.start
|
12
12
|
|
13
|
+
# Sentry.init do |config|
|
14
|
+
# config.dsn = 'https://2fb45f003d054a7ea47feb45898f7649@o447951.ingest.sentry.io/5434472'
|
15
|
+
# end
|
16
|
+
|
13
17
|
require "irb"
|
14
18
|
IRB.start(__FILE__)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "concurrent/executor/thread_pool_executor"
|
2
4
|
require "concurrent/executor/immediate_executor"
|
3
5
|
require "concurrent/configuration"
|
@@ -6,12 +8,18 @@ module Sentry
|
|
6
8
|
class BackgroundWorker
|
7
9
|
include LoggingHelper
|
8
10
|
|
9
|
-
attr_reader :max_queue, :number_of_threads
|
11
|
+
attr_reader :max_queue, :number_of_threads
|
12
|
+
# @deprecated Use Sentry.logger to retrieve the current logger instead.
|
13
|
+
attr_reader :logger
|
14
|
+
attr_accessor :shutdown_timeout
|
10
15
|
|
11
16
|
def initialize(configuration)
|
12
17
|
@max_queue = 30
|
18
|
+
@shutdown_timeout = 1
|
13
19
|
@number_of_threads = configuration.background_worker_threads
|
14
20
|
@logger = configuration.logger
|
21
|
+
@debug = configuration.debug
|
22
|
+
@shutdown_callback = nil
|
15
23
|
|
16
24
|
@executor =
|
17
25
|
if configuration.async
|
@@ -23,19 +31,41 @@ module Sentry
|
|
23
31
|
else
|
24
32
|
log_debug("initialized a background worker with #{@number_of_threads} threads")
|
25
33
|
|
26
|
-
Concurrent::ThreadPoolExecutor.new(
|
34
|
+
executor = Concurrent::ThreadPoolExecutor.new(
|
27
35
|
min_threads: 0,
|
28
36
|
max_threads: @number_of_threads,
|
29
37
|
max_queue: @max_queue,
|
30
38
|
fallback_policy: :discard
|
31
39
|
)
|
40
|
+
|
41
|
+
@shutdown_callback = proc do
|
42
|
+
executor.shutdown
|
43
|
+
executor.wait_for_termination(@shutdown_timeout)
|
44
|
+
end
|
45
|
+
|
46
|
+
executor
|
32
47
|
end
|
33
48
|
end
|
34
49
|
|
50
|
+
# if you want to monkey-patch this method, please override `_perform` instead
|
35
51
|
def perform(&block)
|
36
52
|
@executor.post do
|
37
|
-
|
53
|
+
begin
|
54
|
+
_perform(&block)
|
55
|
+
rescue Exception => e
|
56
|
+
log_error("exception happened in background worker", e, debug: @debug)
|
57
|
+
end
|
38
58
|
end
|
39
59
|
end
|
60
|
+
|
61
|
+
def shutdown
|
62
|
+
@shutdown_callback&.call
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def _perform(&block)
|
68
|
+
block.call
|
69
|
+
end
|
40
70
|
end
|
41
71
|
end
|
data/lib/sentry/backtrace.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'logger'
|
2
4
|
|
3
5
|
module Sentry
|
@@ -67,7 +69,7 @@ module Sentry
|
|
67
69
|
type: severity >= 3 ? "error" : level
|
68
70
|
)
|
69
71
|
|
70
|
-
Sentry.add_breadcrumb(crumb)
|
72
|
+
Sentry.add_breadcrumb(crumb, hint: { severity: severity })
|
71
73
|
end
|
72
74
|
end
|
73
75
|
|
data/lib/sentry/breadcrumb.rb
CHANGED
@@ -1,18 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sentry
|
2
4
|
class Breadcrumb
|
3
5
|
DATA_SERIALIZATION_ERROR_MESSAGE = "[data were removed due to serialization issues]"
|
4
6
|
|
5
|
-
|
7
|
+
# @return [String, nil]
|
8
|
+
attr_accessor :category
|
9
|
+
# @return [Hash, nil]
|
10
|
+
attr_accessor :data
|
11
|
+
# @return [String, nil]
|
12
|
+
attr_accessor :level
|
13
|
+
# @return [Time, Integer, nil]
|
14
|
+
attr_accessor :timestamp
|
15
|
+
# @return [String, nil]
|
16
|
+
attr_accessor :type
|
17
|
+
# @return [String, nil]
|
18
|
+
attr_reader :message
|
6
19
|
|
20
|
+
# @param category [String, nil]
|
21
|
+
# @param data [Hash, nil]
|
22
|
+
# @param message [String, nil]
|
23
|
+
# @param timestamp [Time, Integer, nil]
|
24
|
+
# @param level [String, nil]
|
25
|
+
# @param type [String, nil]
|
7
26
|
def initialize(category: nil, data: nil, message: nil, timestamp: nil, level: nil, type: nil)
|
8
27
|
@category = category
|
9
28
|
@data = data || {}
|
10
29
|
@level = level
|
11
|
-
@message = message
|
12
30
|
@timestamp = timestamp || Sentry.utc_now.to_i
|
13
31
|
@type = type
|
32
|
+
self.message = message
|
14
33
|
end
|
15
34
|
|
35
|
+
# @return [Hash]
|
16
36
|
def to_hash
|
17
37
|
{
|
18
38
|
category: @category,
|
@@ -24,6 +44,12 @@ module Sentry
|
|
24
44
|
}
|
25
45
|
end
|
26
46
|
|
47
|
+
# @param message [String]
|
48
|
+
# @return [void]
|
49
|
+
def message=(message)
|
50
|
+
@message = (message || "").byteslice(0..Event::MAX_MESSAGE_SIZE_IN_BYTES)
|
51
|
+
end
|
52
|
+
|
27
53
|
private
|
28
54
|
|
29
55
|
def serialized_data
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "sentry/breadcrumb"
|
2
4
|
|
3
5
|
module Sentry
|
@@ -5,40 +7,54 @@ module Sentry
|
|
5
7
|
DEFAULT_SIZE = 100
|
6
8
|
include Enumerable
|
7
9
|
|
10
|
+
# @return [Array]
|
8
11
|
attr_accessor :buffer
|
9
12
|
|
13
|
+
# @param size [Integer, nil] If it's not provided, it'll fallback to DEFAULT_SIZE
|
10
14
|
def initialize(size = nil)
|
11
15
|
@buffer = Array.new(size || DEFAULT_SIZE)
|
12
16
|
end
|
13
17
|
|
18
|
+
# @param crumb [Breadcrumb]
|
19
|
+
# @return [void]
|
14
20
|
def record(crumb)
|
15
21
|
yield(crumb) if block_given?
|
16
22
|
@buffer.slice!(0)
|
17
23
|
@buffer << crumb
|
18
24
|
end
|
19
25
|
|
26
|
+
# @return [Array]
|
20
27
|
def members
|
21
28
|
@buffer.compact
|
22
29
|
end
|
23
30
|
|
31
|
+
# Returns the last breadcrumb stored in the buffer. If the buffer it's empty, it returns nil.
|
32
|
+
# @return [Breadcrumb, nil]
|
24
33
|
def peek
|
25
34
|
members.last
|
26
35
|
end
|
27
36
|
|
37
|
+
# Iterates through all breadcrumbs.
|
38
|
+
# @param block [Proc]
|
39
|
+
# @yieldparam crumb [Breadcrumb]
|
40
|
+
# @return [Array]
|
28
41
|
def each(&block)
|
29
42
|
members.each(&block)
|
30
43
|
end
|
31
44
|
|
45
|
+
# @return [Boolean]
|
32
46
|
def empty?
|
33
47
|
members.none?
|
34
48
|
end
|
35
49
|
|
50
|
+
# @return [Hash]
|
36
51
|
def to_hash
|
37
52
|
{
|
38
53
|
values: members.map(&:to_hash)
|
39
54
|
}
|
40
55
|
end
|
41
56
|
|
57
|
+
# @return [BreadcrumbBuffer]
|
42
58
|
def dup
|
43
59
|
copy = super
|
44
60
|
copy.buffer = buffer.deep_dup
|