sentry-ruby 0.3.0 → 4.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +71 -0
- data/Gemfile +2 -2
- data/README.md +88 -8
- data/lib/sentry-ruby.rb +39 -10
- data/lib/sentry/background_worker.rb +37 -0
- data/lib/sentry/client.rb +18 -8
- data/lib/sentry/configuration.rb +12 -0
- data/lib/sentry/event.rb +7 -7
- data/lib/sentry/hub.rb +7 -7
- data/lib/sentry/integrable.rb +24 -0
- data/lib/sentry/interfaces/request.rb +0 -21
- data/lib/sentry/rack.rb +3 -3
- data/lib/sentry/rack/capture_exceptions.rb +62 -0
- data/lib/sentry/rack/deprecations.rb +19 -0
- data/lib/sentry/rack/interface.rb +22 -0
- data/lib/sentry/rake.rb +17 -0
- data/lib/sentry/scope.rb +2 -2
- data/lib/sentry/span.rb +5 -28
- data/lib/sentry/transaction.rb +44 -0
- data/lib/sentry/transport.rb +12 -21
- data/lib/sentry/transport/http_transport.rb +3 -6
- data/lib/sentry/version.rb +1 -1
- data/sentry-ruby.gemspec +1 -0
- metadata +28 -5
- data/lib/sentry/rack/capture_exception.rb +0 -45
- data/lib/sentry/rack/tracing.rb +0 -39
- 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: cbe0af63148c410c71208f7bac743d24e224b5265102d645831a9538262961dc
|
4
|
+
data.tar.gz: 9933997d430fc94d400f97b9e2319ab14ccfe1bd2ff42635eda5b13bd4e11621
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a813b4fad61840a850b6dd82451d689272800b5d4e405ab50f80f99cfe69a371f770c1a8151491ccd2f10400822e0e4a98bc8c2ca1265b562139bd7ffc1cdd02
|
7
|
+
data.tar.gz: 1331331801ea39234c96e50e9fc469713efd48ee316e5620ae2c200f97a4a4d88810f942d707fb77dab7b458284ee11cad4b6153632cde4aa6014e2df5a89820
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,76 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 4.1.2
|
4
|
+
|
5
|
+
- before_send callback shouldn't be applied to transaction events [#1167](https://github.com/getsentry/sentry-ruby/pull/1167)
|
6
|
+
- Transaction improvements [#1170](https://github.com/getsentry/sentry-ruby/pull/1170)
|
7
|
+
- Support Ruby 3 [#1172](https://github.com/getsentry/sentry-ruby/pull/1172)
|
8
|
+
- Add Integrable module [#1177](https://github.com/getsentry/sentry-ruby/pull/1177)
|
9
|
+
|
10
|
+
## 4.1.1
|
11
|
+
|
12
|
+
- Fix NoMethodError when sending is not allowed [#1161](https://github.com/getsentry/sentry-ruby/pull/1161)
|
13
|
+
- Add notification for users who still use deprecated middlewares [#1160](https://github.com/getsentry/sentry-ruby/pull/1160)
|
14
|
+
- Improve top-level api safety [#1162](https://github.com/getsentry/sentry-ruby/pull/1162)
|
15
|
+
|
16
|
+
## 4.1.0
|
17
|
+
|
18
|
+
- Separate rack integration [#1138](https://github.com/getsentry/sentry-ruby/pull/1138)
|
19
|
+
- Fixes [#1136](https://github.com/getsentry/sentry-ruby/pull/1136)
|
20
|
+
- Fix event sampling [#1144](https://github.com/getsentry/sentry-ruby/pull/1144)
|
21
|
+
- Merge & rename 2 Rack middlewares [#1147](https://github.com/getsentry/sentry-ruby/pull/1147)
|
22
|
+
- Fixes [#1153](https://github.com/getsentry/sentry-ruby/pull/1153)
|
23
|
+
- Removed `Sentry::Rack::Tracing` middleware and renamed `Sentry::Rack::CaptureException` to `Sentry::Rack::CaptureExceptions`.
|
24
|
+
- Deep-copy spans [#1148](https://github.com/getsentry/sentry-ruby/pull/1148)
|
25
|
+
- Move span recorder related code from Span to Transaction [#1149](https://github.com/getsentry/sentry-ruby/pull/1149)
|
26
|
+
- Check SDK initialization before running integrations [#1151](https://github.com/getsentry/sentry-ruby/pull/1151)
|
27
|
+
- Fixes [#1145](https://github.com/getsentry/sentry-ruby/pull/1145)
|
28
|
+
- Refactor transport [#1154](https://github.com/getsentry/sentry-ruby/pull/1154)
|
29
|
+
- Implement non-blocking event sending [#1155](https://github.com/getsentry/sentry-ruby/pull/1155)
|
30
|
+
- Added `background_worker_threads` configuration option.
|
31
|
+
|
32
|
+
### Noticeable Changes
|
33
|
+
|
34
|
+
#### Middleware Changes
|
35
|
+
|
36
|
+
`Sentry::Rack::Tracing` is now removed. And `Sentry::Rack::CaptureException` has been renamed to `Sentry::Rack::CaptureExceptions`.
|
37
|
+
|
38
|
+
#### Events Are Sent Asynchronously
|
39
|
+
|
40
|
+
`sentry-ruby` now sends events asynchronously by default. The functionality works like this:
|
41
|
+
|
42
|
+
1. When the SDK is initialized, a `Sentry::BackgroundWorker` will be initialized too.
|
43
|
+
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.
|
44
|
+
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`.
|
45
|
+
- If all the threads are busy, new jobs will be put into a queue, which has a limit of 30.
|
46
|
+
- If the queue size is exceeded, new events will be dropped.
|
47
|
+
|
48
|
+
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.
|
49
|
+
|
50
|
+
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.
|
51
|
+
|
52
|
+
Of course, you can always override the value to fit your use cases, like
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
config.background_worker_threads = 5 # the worker will have 5 threads for sending events
|
56
|
+
```
|
57
|
+
|
58
|
+
You can also disable this new non-blocking behaviour by giving a `0` value:
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
config.background_worker_threads = 0 # all events will be sent synchronously
|
62
|
+
```
|
63
|
+
|
64
|
+
## 4.0.1
|
65
|
+
|
66
|
+
- Add rake integration: [1137](https://github.com/getsentry/sentry-ruby/pull/1137)
|
67
|
+
- Make Event's interfaces accessible: [1135](https://github.com/getsentry/sentry-ruby/pull/1135)
|
68
|
+
- ActiveSupportLogger should only record events that has a started time: [1132](https://github.com/getsentry/sentry-ruby/pull/1132)
|
69
|
+
|
70
|
+
## 4.0.0
|
71
|
+
|
72
|
+
- Only documents update for the official release and no API/feature changes.
|
73
|
+
|
3
74
|
## 0.3.0
|
4
75
|
|
5
76
|
- Major API changes: [1123](https://github.com/getsentry/sentry-ruby/pull/1123)
|
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/lib/sentry-ruby.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "forwardable"
|
2
|
+
require "time"
|
2
3
|
|
3
4
|
require "sentry/version"
|
4
5
|
require "sentry/core_ext/object/deep_dup"
|
@@ -9,7 +10,17 @@ require "sentry/transaction_event"
|
|
9
10
|
require "sentry/span"
|
10
11
|
require "sentry/transaction"
|
11
12
|
require "sentry/hub"
|
12
|
-
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"
|
13
24
|
|
14
25
|
module Sentry
|
15
26
|
class Error < StandardError
|
@@ -29,11 +40,24 @@ module Sentry
|
|
29
40
|
Time.now.utc
|
30
41
|
end
|
31
42
|
|
43
|
+
class << self
|
44
|
+
def integrations
|
45
|
+
@integrations ||= {}
|
46
|
+
end
|
47
|
+
|
48
|
+
def register_integration(name, version)
|
49
|
+
meta = { name: "sentry.ruby.#{name}", version: version }.freeze
|
50
|
+
integrations[name.to_s] = meta
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
32
54
|
class << self
|
33
55
|
extend Forwardable
|
34
56
|
|
35
57
|
def_delegators :get_current_scope, :set_tags, :set_extras, :set_user
|
36
58
|
|
59
|
+
attr_accessor :background_worker
|
60
|
+
|
37
61
|
def init(&block)
|
38
62
|
config = Configuration.new
|
39
63
|
yield(config)
|
@@ -42,6 +66,11 @@ module Sentry
|
|
42
66
|
hub = Hub.new(client, scope)
|
43
67
|
Thread.current[THREAD_LOCAL] = hub
|
44
68
|
@main_hub = hub
|
69
|
+
@background_worker = Sentry::BackgroundWorker.new(config)
|
70
|
+
end
|
71
|
+
|
72
|
+
def initialized?
|
73
|
+
!!@main_hub
|
45
74
|
end
|
46
75
|
|
47
76
|
def get_main_hub
|
@@ -61,7 +90,7 @@ module Sentry
|
|
61
90
|
end
|
62
91
|
|
63
92
|
def get_current_client
|
64
|
-
get_current_hub
|
93
|
+
get_current_hub&.current_client
|
65
94
|
end
|
66
95
|
|
67
96
|
def get_current_hub
|
@@ -78,15 +107,15 @@ module Sentry
|
|
78
107
|
end
|
79
108
|
|
80
109
|
def get_current_scope
|
81
|
-
get_current_hub
|
110
|
+
get_current_hub&.current_scope
|
82
111
|
end
|
83
112
|
|
84
113
|
def with_scope(&block)
|
85
|
-
get_current_hub
|
114
|
+
get_current_hub&.with_scope(&block)
|
86
115
|
end
|
87
116
|
|
88
117
|
def configure_scope(&block)
|
89
|
-
get_current_hub
|
118
|
+
get_current_hub&.configure_scope(&block)
|
90
119
|
end
|
91
120
|
|
92
121
|
def send_event(event)
|
@@ -94,23 +123,23 @@ module Sentry
|
|
94
123
|
end
|
95
124
|
|
96
125
|
def capture_event(event)
|
97
|
-
get_current_hub
|
126
|
+
get_current_hub&.capture_event(event)
|
98
127
|
end
|
99
128
|
|
100
129
|
def capture_exception(exception, **options, &block)
|
101
|
-
get_current_hub
|
130
|
+
get_current_hub&.capture_exception(exception, **options, &block)
|
102
131
|
end
|
103
132
|
|
104
133
|
def capture_message(message, **options, &block)
|
105
|
-
get_current_hub
|
134
|
+
get_current_hub&.capture_message(message, **options, &block)
|
106
135
|
end
|
107
136
|
|
108
137
|
def start_transaction(**options)
|
109
|
-
get_current_hub
|
138
|
+
get_current_hub&.start_transaction(**options)
|
110
139
|
end
|
111
140
|
|
112
141
|
def last_event_id
|
113
|
-
get_current_hub
|
142
|
+
get_current_hub&.last_event_id
|
114
143
|
end
|
115
144
|
|
116
145
|
def sys_command(command)
|
@@ -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/client.rb
CHANGED
@@ -20,7 +20,9 @@ module Sentry
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
def capture_event(event, scope, hint =
|
23
|
+
def capture_event(event, scope, hint = {})
|
24
|
+
return unless configuration.sending_allowed?
|
25
|
+
|
24
26
|
scope.apply_to_event(event, hint)
|
25
27
|
|
26
28
|
if configuration.async?
|
@@ -33,22 +35,30 @@ module Sentry
|
|
33
35
|
send_event(event, hint)
|
34
36
|
end
|
35
37
|
else
|
36
|
-
|
38
|
+
if hint.fetch(:background, true)
|
39
|
+
Sentry.background_worker.perform do
|
40
|
+
send_event(event, hint)
|
41
|
+
end
|
42
|
+
else
|
43
|
+
send_event(event, hint)
|
44
|
+
end
|
37
45
|
end
|
38
46
|
|
39
47
|
event
|
40
48
|
end
|
41
49
|
|
42
|
-
def event_from_exception(exception)
|
50
|
+
def event_from_exception(exception, hint = {})
|
51
|
+
integration_meta = Sentry.integrations[hint[:integration]]
|
43
52
|
return unless @configuration.exception_class_allowed?(exception)
|
44
53
|
|
45
|
-
Event.new(configuration: configuration).tap do |event|
|
54
|
+
Event.new(configuration: configuration, integration_meta: integration_meta).tap do |event|
|
46
55
|
event.add_exception_interface(exception)
|
47
56
|
end
|
48
57
|
end
|
49
58
|
|
50
|
-
def event_from_message(message)
|
51
|
-
|
59
|
+
def event_from_message(message, hint = {})
|
60
|
+
integration_meta = Sentry.integrations[hint[:integration]]
|
61
|
+
Event.new(configuration: configuration, integration_meta: integration_meta, message: message)
|
52
62
|
end
|
53
63
|
|
54
64
|
def event_from_transaction(transaction)
|
@@ -64,9 +74,9 @@ module Sentry
|
|
64
74
|
end
|
65
75
|
|
66
76
|
def send_event(event, hint = nil)
|
67
|
-
|
77
|
+
event_type = event.is_a?(Event) ? event.type : event["type"]
|
78
|
+
event = configuration.before_send.call(event, hint) if configuration.before_send && event_type == "event"
|
68
79
|
|
69
|
-
event = configuration.before_send.call(event, hint) if configuration.before_send
|
70
80
|
if event.nil?
|
71
81
|
configuration.logger.info(LOGGER_PROGNAME) { "Discarded event because before_send returned nil" }
|
72
82
|
return
|
data/lib/sentry/configuration.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require "concurrent/utility/processor_counter"
|
2
|
+
|
1
3
|
require "sentry/utils/exception_cause_chain"
|
2
4
|
require "sentry/dsn"
|
3
5
|
require "sentry/transport/configuration"
|
@@ -15,6 +17,15 @@ module Sentry
|
|
15
17
|
attr_reader :async
|
16
18
|
alias async? async
|
17
19
|
|
20
|
+
# to send events in a non-blocking way, sentry-ruby has its own background worker
|
21
|
+
# by default, the worker holds a thread pool that has [the number of processors] threads
|
22
|
+
# but you can configure it with this configuration option
|
23
|
+
# E.g.: config.background_worker_threads = 5
|
24
|
+
#
|
25
|
+
# if you want to send events synchronously, set the value to 0
|
26
|
+
# E.g.: config.background_worker_threads = 0
|
27
|
+
attr_accessor :background_worker_threads
|
28
|
+
|
18
29
|
# a proc/lambda that takes an array of stack traces
|
19
30
|
# it'll be used to silence (reduce) backtrace of the exception
|
20
31
|
#
|
@@ -146,6 +157,7 @@ module Sentry
|
|
146
157
|
|
147
158
|
def initialize
|
148
159
|
self.async = false
|
160
|
+
self.background_worker_threads = Concurrent.processor_count
|
149
161
|
self.breadcrumbs_logger = []
|
150
162
|
self.context_lines = 3
|
151
163
|
self.environment = environment_from_env
|
data/lib/sentry/event.rb
CHANGED
@@ -18,9 +18,9 @@ module Sentry
|
|
18
18
|
)
|
19
19
|
|
20
20
|
attr_accessor(*ATTRIBUTES)
|
21
|
-
attr_reader :configuration
|
21
|
+
attr_reader :configuration, :request, :exception, :stacktrace
|
22
22
|
|
23
|
-
def initialize(configuration:, message: nil)
|
23
|
+
def initialize(configuration:, integration_meta: nil, message: nil)
|
24
24
|
# this needs to go first because some setters rely on configuration
|
25
25
|
@configuration = configuration
|
26
26
|
|
@@ -28,7 +28,7 @@ module Sentry
|
|
28
28
|
@event_id = SecureRandom.uuid.delete("-")
|
29
29
|
@timestamp = Sentry.utc_now.iso8601
|
30
30
|
@platform = :ruby
|
31
|
-
@sdk = Sentry.sdk_meta
|
31
|
+
@sdk = integration_meta || Sentry.sdk_meta
|
32
32
|
|
33
33
|
@user = {}
|
34
34
|
@extra = {}
|
@@ -75,7 +75,7 @@ module Sentry
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def rack_env=(env)
|
78
|
-
unless
|
78
|
+
unless request || env.empty?
|
79
79
|
@request = Sentry::RequestInterface.new.tap do |int|
|
80
80
|
int.from_rack(env)
|
81
81
|
end
|
@@ -96,9 +96,9 @@ module Sentry
|
|
96
96
|
def to_hash
|
97
97
|
data = serialize_attributes
|
98
98
|
data[:breadcrumbs] = breadcrumbs.to_hash if breadcrumbs
|
99
|
-
data[:stacktrace] =
|
100
|
-
data[:request] =
|
101
|
-
data[:exception] =
|
99
|
+
data[:stacktrace] = stacktrace.to_hash if stacktrace
|
100
|
+
data[:request] = request.to_hash if request
|
101
|
+
data[:exception] = exception.to_hash if exception
|
102
102
|
|
103
103
|
data
|
104
104
|
end
|
data/lib/sentry/hub.rb
CHANGED
@@ -76,12 +76,12 @@ module Sentry
|
|
76
76
|
def capture_exception(exception, **options, &block)
|
77
77
|
return unless current_client
|
78
78
|
|
79
|
-
|
79
|
+
options[:hint] ||= {}
|
80
|
+
options[:hint][:exception] = exception
|
81
|
+
event = current_client.event_from_exception(exception, options[:hint])
|
80
82
|
|
81
83
|
return unless event
|
82
84
|
|
83
|
-
options[:hint] ||= {}
|
84
|
-
options[:hint] = options[:hint].merge(exception: exception)
|
85
85
|
capture_event(event, **options, &block)
|
86
86
|
end
|
87
87
|
|
@@ -89,15 +89,15 @@ module Sentry
|
|
89
89
|
return unless current_client
|
90
90
|
|
91
91
|
options[:hint] ||= {}
|
92
|
-
options[:hint]
|
93
|
-
event = current_client.event_from_message(message)
|
92
|
+
options[:hint][:message] = message
|
93
|
+
event = current_client.event_from_message(message, options[:hint])
|
94
94
|
capture_event(event, **options, &block)
|
95
95
|
end
|
96
96
|
|
97
97
|
def capture_event(event, **options, &block)
|
98
98
|
return unless current_client
|
99
99
|
|
100
|
-
hint = options.delete(:hint)
|
100
|
+
hint = options.delete(:hint) || {}
|
101
101
|
scope = current_scope.dup
|
102
102
|
|
103
103
|
if block
|
@@ -110,7 +110,7 @@ module Sentry
|
|
110
110
|
|
111
111
|
event = current_client.capture_event(event, scope, hint)
|
112
112
|
|
113
|
-
@last_event_id = event
|
113
|
+
@last_event_id = event&.event_id
|
114
114
|
event
|
115
115
|
end
|
116
116
|
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Sentry
|
2
|
+
module Integrable
|
3
|
+
def register_integration(name:, version:)
|
4
|
+
Sentry.register_integration(name, version)
|
5
|
+
@integration_name = name
|
6
|
+
end
|
7
|
+
|
8
|
+
def integration_name
|
9
|
+
@integration_name
|
10
|
+
end
|
11
|
+
|
12
|
+
def capture_exception(exception, **options, &block)
|
13
|
+
options[:hint] ||= {}
|
14
|
+
options[:hint][:integration] = integration_name
|
15
|
+
Sentry.capture_exception(exception, **options, &block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def capture_message(message, **options, &block)
|
19
|
+
options[:hint] ||= {}
|
20
|
+
options[:hint][:integration] = integration_name
|
21
|
+
Sentry.capture_message(message, **options, &block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'rack'
|
2
|
-
|
3
1
|
module Sentry
|
4
2
|
class RequestInterface < Interface
|
5
3
|
REQUEST_ID_HEADERS = %w(action_dispatch.request_id HTTP_X_REQUEST_ID).freeze
|
@@ -18,25 +16,6 @@ module Sentry
|
|
18
16
|
self.cookies = nil
|
19
17
|
end
|
20
18
|
|
21
|
-
def from_rack(env_hash)
|
22
|
-
req = ::Rack::Request.new(env_hash)
|
23
|
-
|
24
|
-
if Sentry.configuration.send_default_pii
|
25
|
-
self.data = read_data_from(req)
|
26
|
-
self.cookies = req.cookies
|
27
|
-
else
|
28
|
-
# need to completely wipe out ip addresses
|
29
|
-
IP_HEADERS.each { |h| env_hash.delete(h) }
|
30
|
-
end
|
31
|
-
|
32
|
-
self.url = req.scheme && req.url.split('?').first
|
33
|
-
self.method = req.request_method
|
34
|
-
self.query_string = req.query_string
|
35
|
-
|
36
|
-
self.headers = format_headers_for_sentry(env_hash)
|
37
|
-
self.env = format_env_for_sentry(env_hash)
|
38
|
-
end
|
39
|
-
|
40
19
|
private
|
41
20
|
|
42
21
|
# See Sentry server default limits at
|
data/lib/sentry/rack.rb
CHANGED
@@ -0,0 +1,62 @@
|
|
1
|
+
module Sentry
|
2
|
+
module Rack
|
3
|
+
class CaptureExceptions
|
4
|
+
def initialize(app)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
return @app.call(env) unless Sentry.initialized?
|
10
|
+
|
11
|
+
# make sure the current thread has a clean hub
|
12
|
+
Sentry.clone_hub_to_current_thread
|
13
|
+
|
14
|
+
Sentry.with_scope do |scope|
|
15
|
+
scope.clear_breadcrumbs
|
16
|
+
scope.set_transaction_name(env["PATH_INFO"]) if env["PATH_INFO"]
|
17
|
+
scope.set_rack_env(env)
|
18
|
+
|
19
|
+
span = Sentry.start_transaction(name: scope.transaction_name, op: transaction_op)
|
20
|
+
scope.set_span(span)
|
21
|
+
|
22
|
+
begin
|
23
|
+
response = @app.call(env)
|
24
|
+
rescue Sentry::Error
|
25
|
+
finish_span(span, 500)
|
26
|
+
raise # Don't capture Sentry errors
|
27
|
+
rescue Exception => e
|
28
|
+
capture_exception(e)
|
29
|
+
finish_span(span, 500)
|
30
|
+
raise
|
31
|
+
end
|
32
|
+
|
33
|
+
exception = collect_exception(env)
|
34
|
+
capture_exception(exception) if exception
|
35
|
+
|
36
|
+
finish_span(span, response[0])
|
37
|
+
|
38
|
+
response
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def collect_exception(env)
|
45
|
+
env['rack.exception'] || env['sinatra.error']
|
46
|
+
end
|
47
|
+
|
48
|
+
def transaction_op
|
49
|
+
"rack.request".freeze
|
50
|
+
end
|
51
|
+
|
52
|
+
def capture_exception(exception)
|
53
|
+
Sentry.capture_exception(exception)
|
54
|
+
end
|
55
|
+
|
56
|
+
def finish_span(span, status_code)
|
57
|
+
span.set_http_status(status_code)
|
58
|
+
span.finish
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Sentry
|
2
|
+
module Rack
|
3
|
+
class DeprecatedMiddleware
|
4
|
+
def initialize(_)
|
5
|
+
raise Sentry::Error.new <<~MSG
|
6
|
+
|
7
|
+
You're seeing this message because #{self.class} has been replaced by Sentry::Rack::CaptureExceptions.
|
8
|
+
Removing this middleware from your app and upgrading sentry-rails to 4.1.0+ should solve the issue.
|
9
|
+
MSG
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Tracing < DeprecatedMiddleware
|
14
|
+
end
|
15
|
+
|
16
|
+
class CaptureException < DeprecatedMiddleware
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Sentry
|
2
|
+
class RequestInterface
|
3
|
+
def from_rack(env_hash)
|
4
|
+
req = ::Rack::Request.new(env_hash)
|
5
|
+
|
6
|
+
if Sentry.configuration.send_default_pii
|
7
|
+
self.data = read_data_from(req)
|
8
|
+
self.cookies = req.cookies
|
9
|
+
else
|
10
|
+
# need to completely wipe out ip addresses
|
11
|
+
IP_HEADERS.each { |h| env_hash.delete(h) }
|
12
|
+
end
|
13
|
+
|
14
|
+
self.url = req.scheme && req.url.split('?').first
|
15
|
+
self.method = req.request_method
|
16
|
+
self.query_string = req.query_string
|
17
|
+
|
18
|
+
self.headers = format_headers_for_sentry(env_hash)
|
19
|
+
self.env = format_env_for_sentry(env_hash)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/sentry/rake.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "rake"
|
2
|
+
require "rake/task"
|
3
|
+
|
4
|
+
module Rake
|
5
|
+
class Application
|
6
|
+
alias orig_display_error_messsage display_error_message
|
7
|
+
def display_error_message(ex)
|
8
|
+
Sentry.capture_exception(ex, hint: { background: false }) do |scope|
|
9
|
+
task_name = top_level_tasks.join(' ')
|
10
|
+
scope.set_transaction_name(task_name)
|
11
|
+
scope.set_tag("rake_task", task_name)
|
12
|
+
end if Sentry.initialized?
|
13
|
+
|
14
|
+
orig_display_error_messsage(ex)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/sentry/scope.rb
CHANGED
@@ -29,7 +29,7 @@ module Sentry
|
|
29
29
|
event.level = level
|
30
30
|
event.transaction = transaction_names.last
|
31
31
|
event.breadcrumbs = breadcrumbs
|
32
|
-
event.rack_env = rack_env
|
32
|
+
event.rack_env = rack_env if rack_env
|
33
33
|
|
34
34
|
unless @event_processors.empty?
|
35
35
|
@event_processors.each do |processor_block|
|
@@ -57,7 +57,7 @@ module Sentry
|
|
57
57
|
copy.user = user.deep_dup
|
58
58
|
copy.transaction_names = transaction_names.deep_dup
|
59
59
|
copy.fingerprint = fingerprint.deep_dup
|
60
|
-
copy.span = span
|
60
|
+
copy.span = span.deep_dup
|
61
61
|
copy
|
62
62
|
end
|
63
63
|
|
data/lib/sentry/span.rb
CHANGED
@@ -35,11 +35,6 @@ module Sentry
|
|
35
35
|
@tags = {}
|
36
36
|
end
|
37
37
|
|
38
|
-
def set_span_recorder
|
39
|
-
@span_recorder = SpanRecorder.new(1000)
|
40
|
-
@span_recorder.add(self)
|
41
|
-
end
|
42
|
-
|
43
38
|
def finish
|
44
39
|
# already finished
|
45
40
|
return if @timestamp
|
@@ -82,14 +77,7 @@ module Sentry
|
|
82
77
|
|
83
78
|
def start_child(**options)
|
84
79
|
options = options.dup.merge(trace_id: @trace_id, parent_span_id: @span_id, sampled: @sampled)
|
85
|
-
|
86
|
-
child_span.span_recorder = @span_recorder
|
87
|
-
|
88
|
-
if @span_recorder && @sampled
|
89
|
-
@span_recorder.add(child_span)
|
90
|
-
end
|
91
|
-
|
92
|
-
child_span
|
80
|
+
Span.new(**options)
|
93
81
|
end
|
94
82
|
|
95
83
|
def with_child_span(**options, &block)
|
@@ -100,6 +88,10 @@ module Sentry
|
|
100
88
|
child_span.finish
|
101
89
|
end
|
102
90
|
|
91
|
+
def deep_dup
|
92
|
+
dup
|
93
|
+
end
|
94
|
+
|
103
95
|
def set_op(op)
|
104
96
|
@op = op
|
105
97
|
end
|
@@ -136,20 +128,5 @@ module Sentry
|
|
136
128
|
def set_tag(key, value)
|
137
129
|
@tags[key] = value
|
138
130
|
end
|
139
|
-
|
140
|
-
class SpanRecorder
|
141
|
-
attr_reader :max_length, :spans
|
142
|
-
|
143
|
-
def initialize(max_length)
|
144
|
-
@max_length = max_length
|
145
|
-
@spans = []
|
146
|
-
end
|
147
|
-
|
148
|
-
def add(span)
|
149
|
-
if @spans.count < @max_length
|
150
|
-
@spans << span
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
131
|
end
|
155
132
|
end
|
data/lib/sentry/transaction.rb
CHANGED
@@ -20,6 +20,11 @@ module Sentry
|
|
20
20
|
set_span_recorder
|
21
21
|
end
|
22
22
|
|
23
|
+
def set_span_recorder
|
24
|
+
@span_recorder = SpanRecorder.new(1000)
|
25
|
+
@span_recorder.add(self)
|
26
|
+
end
|
27
|
+
|
23
28
|
def self.from_sentry_trace(sentry_trace, **options)
|
24
29
|
return unless sentry_trace
|
25
30
|
|
@@ -37,6 +42,30 @@ module Sentry
|
|
37
42
|
hash
|
38
43
|
end
|
39
44
|
|
45
|
+
def start_child(**options)
|
46
|
+
child_span = super
|
47
|
+
child_span.span_recorder = @span_recorder
|
48
|
+
|
49
|
+
if @sampled
|
50
|
+
@span_recorder.add(child_span)
|
51
|
+
end
|
52
|
+
|
53
|
+
child_span
|
54
|
+
end
|
55
|
+
|
56
|
+
def deep_dup
|
57
|
+
copy = super
|
58
|
+
copy.set_span_recorder
|
59
|
+
|
60
|
+
@span_recorder.spans.each do |span|
|
61
|
+
# span_recorder's first span is the current span, which should not be added to the copy's spans
|
62
|
+
next if span == self
|
63
|
+
copy.span_recorder.add(span.dup)
|
64
|
+
end
|
65
|
+
|
66
|
+
copy
|
67
|
+
end
|
68
|
+
|
40
69
|
def set_initial_sample_desicion(sampling_context = {})
|
41
70
|
unless Sentry.configuration.tracing_enabled?
|
42
71
|
@sampled = false
|
@@ -109,5 +138,20 @@ module Sentry
|
|
109
138
|
result += " <#{@name}>" if @name
|
110
139
|
result
|
111
140
|
end
|
141
|
+
|
142
|
+
class SpanRecorder
|
143
|
+
attr_reader :max_length, :spans
|
144
|
+
|
145
|
+
def initialize(max_length)
|
146
|
+
@max_length = max_length
|
147
|
+
@spans = []
|
148
|
+
end
|
149
|
+
|
150
|
+
def add(span)
|
151
|
+
if @spans.count < @max_length
|
152
|
+
@spans << span
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
112
156
|
end
|
113
157
|
end
|
data/lib/sentry/transport.rb
CHANGED
@@ -1,20 +1,17 @@
|
|
1
1
|
require "json"
|
2
2
|
require "base64"
|
3
|
-
require "sentry/transport/state"
|
4
3
|
|
5
4
|
module Sentry
|
6
5
|
class Transport
|
7
6
|
PROTOCOL_VERSION = '5'
|
8
7
|
USER_AGENT = "sentry-ruby/#{Sentry::VERSION}"
|
9
|
-
CONTENT_TYPE = 'application/json'
|
10
8
|
|
11
|
-
attr_accessor :configuration
|
9
|
+
attr_accessor :configuration
|
12
10
|
|
13
11
|
def initialize(configuration)
|
14
12
|
@configuration = configuration
|
15
13
|
@transport_configuration = configuration.transport
|
16
14
|
@dsn = configuration.dsn
|
17
|
-
@state = State.new
|
18
15
|
end
|
19
16
|
|
20
17
|
def send_data(data, options = {})
|
@@ -22,13 +19,17 @@ module Sentry
|
|
22
19
|
end
|
23
20
|
|
24
21
|
def send_event(event)
|
25
|
-
|
22
|
+
unless configuration.sending_allowed?
|
23
|
+
configuration.logger.debug(LOGGER_PROGNAME) { "Event not sent: #{configuration.error_messages}" }
|
24
|
+
return
|
25
|
+
end
|
26
|
+
|
27
|
+
encoded_data = prepare_encoded_event(event)
|
26
28
|
|
27
29
|
return nil unless encoded_data
|
28
30
|
|
29
|
-
send_data(encoded_data
|
31
|
+
send_data(encoded_data)
|
30
32
|
|
31
|
-
state.success
|
32
33
|
event
|
33
34
|
rescue => e
|
34
35
|
failed_for_exception(e, event)
|
@@ -57,7 +58,7 @@ module Sentry
|
|
57
58
|
#{JSON.generate(event_hash)}
|
58
59
|
ENVELOPE
|
59
60
|
|
60
|
-
|
61
|
+
envelope
|
61
62
|
end
|
62
63
|
|
63
64
|
private
|
@@ -66,27 +67,17 @@ module Sentry
|
|
66
67
|
# Convert to hash
|
67
68
|
event_hash = event.to_hash
|
68
69
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
event_id = event_hash[:event_id] || event_hash['event_id']
|
75
|
-
configuration.logger.info(LOGGER_PROGNAME) { "Sending event #{event_id} to Sentry" }
|
70
|
+
event_id = event_hash[:event_id] || event_hash["event_id"]
|
71
|
+
event_type = event_hash[:type] || event_hash["type"]
|
72
|
+
configuration.logger.info(LOGGER_PROGNAME) { "Sending #{event_type} #{event_id} to Sentry" }
|
76
73
|
encode(event_hash)
|
77
74
|
end
|
78
75
|
|
79
76
|
def failed_for_exception(e, event)
|
80
|
-
@state.failure
|
81
77
|
configuration.logger.warn(LOGGER_PROGNAME) { "Unable to record event with remote Sentry server (#{e.class} - #{e.message}):\n#{e.backtrace[0..10].join("\n")}" }
|
82
78
|
log_not_sending(event)
|
83
79
|
end
|
84
80
|
|
85
|
-
def failed_for_previous_failure(event)
|
86
|
-
configuration.logger.warn(LOGGER_PROGNAME) { "Not sending event due to previous failure(s)." }
|
87
|
-
log_not_sending(event)
|
88
|
-
end
|
89
|
-
|
90
81
|
def log_not_sending(event)
|
91
82
|
configuration.logger.warn(LOGGER_PROGNAME) { "Failed to submit event. Unreported Event: #{Event.get_log_message(event.to_hash)}" }
|
92
83
|
end
|
@@ -2,6 +2,7 @@ require 'faraday'
|
|
2
2
|
|
3
3
|
module Sentry
|
4
4
|
class HTTPTransport < Transport
|
5
|
+
CONTENT_TYPE = 'application/json'
|
5
6
|
attr_reader :conn, :adapter
|
6
7
|
|
7
8
|
def initialize(*args)
|
@@ -11,13 +12,9 @@ module Sentry
|
|
11
12
|
@endpoint = @dsn.envelope_endpoint
|
12
13
|
end
|
13
14
|
|
14
|
-
def send_data(data
|
15
|
-
unless configuration.sending_allowed?
|
16
|
-
logger.debug(LOGGER_PROGNAME) { "Event not sent: #{configuration.error_messages}" }
|
17
|
-
end
|
18
|
-
|
15
|
+
def send_data(data)
|
19
16
|
conn.post @endpoint do |req|
|
20
|
-
req.headers['Content-Type'] =
|
17
|
+
req.headers['Content-Type'] = CONTENT_TYPE
|
21
18
|
req.headers['X-Sentry-Auth'] = generate_auth_header
|
22
19
|
req.body = data
|
23
20
|
end
|
data/lib/sentry/version.rb
CHANGED
data/sentry-ruby.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sentry-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sentry Team
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-12-
|
11
|
+
date: 2020-12-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -24,6 +24,26 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: concurrent-ruby
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 1.0.2
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '1.0'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.0.2
|
27
47
|
description: A gem that provides a client interface for the Sentry error logger
|
28
48
|
email: accounts@sentry.io
|
29
49
|
executables: []
|
@@ -45,6 +65,7 @@ files:
|
|
45
65
|
- bin/console
|
46
66
|
- bin/setup
|
47
67
|
- lib/sentry-ruby.rb
|
68
|
+
- lib/sentry/background_worker.rb
|
48
69
|
- lib/sentry/backtrace.rb
|
49
70
|
- lib/sentry/benchmarks/benchmark_transport.rb
|
50
71
|
- lib/sentry/breadcrumb.rb
|
@@ -57,6 +78,7 @@ files:
|
|
57
78
|
- lib/sentry/dsn.rb
|
58
79
|
- lib/sentry/event.rb
|
59
80
|
- lib/sentry/hub.rb
|
81
|
+
- lib/sentry/integrable.rb
|
60
82
|
- lib/sentry/interface.rb
|
61
83
|
- lib/sentry/interfaces/exception.rb
|
62
84
|
- lib/sentry/interfaces/request.rb
|
@@ -65,8 +87,10 @@ files:
|
|
65
87
|
- lib/sentry/linecache.rb
|
66
88
|
- lib/sentry/logger.rb
|
67
89
|
- lib/sentry/rack.rb
|
68
|
-
- lib/sentry/rack/
|
69
|
-
- lib/sentry/rack/
|
90
|
+
- lib/sentry/rack/capture_exceptions.rb
|
91
|
+
- lib/sentry/rack/deprecations.rb
|
92
|
+
- lib/sentry/rack/interface.rb
|
93
|
+
- lib/sentry/rake.rb
|
70
94
|
- lib/sentry/scope.rb
|
71
95
|
- lib/sentry/span.rb
|
72
96
|
- lib/sentry/transaction.rb
|
@@ -75,7 +99,6 @@ files:
|
|
75
99
|
- lib/sentry/transport/configuration.rb
|
76
100
|
- lib/sentry/transport/dummy_transport.rb
|
77
101
|
- lib/sentry/transport/http_transport.rb
|
78
|
-
- lib/sentry/transport/state.rb
|
79
102
|
- lib/sentry/utils/exception_cause_chain.rb
|
80
103
|
- lib/sentry/utils/real_ip.rb
|
81
104
|
- lib/sentry/utils/request_id.rb
|
@@ -1,45 +0,0 @@
|
|
1
|
-
module Sentry
|
2
|
-
module Rack
|
3
|
-
class CaptureException
|
4
|
-
def initialize(app)
|
5
|
-
@app = app
|
6
|
-
end
|
7
|
-
|
8
|
-
def call(env)
|
9
|
-
# this call clones the main (global) hub
|
10
|
-
# and assigns it to the current thread's Sentry#get_current_hub
|
11
|
-
# it's essential for multi-thread servers (e.g. puma)
|
12
|
-
Sentry.clone_hub_to_current_thread unless Sentry.get_current_hub
|
13
|
-
# this call creates an isolated scope for every request
|
14
|
-
# it's essential for multi-process servers (e.g. unicorn)
|
15
|
-
Sentry.with_scope do |scope|
|
16
|
-
# there could be some breadcrumbs already stored in the top-level scope
|
17
|
-
# and for request information, we don't need those breadcrumbs
|
18
|
-
scope.clear_breadcrumbs
|
19
|
-
env['sentry.client'] = Sentry.get_current_client
|
20
|
-
|
21
|
-
scope.set_transaction_name(env["PATH_INFO"]) if env["PATH_INFO"]
|
22
|
-
scope.set_rack_env(env)
|
23
|
-
|
24
|
-
begin
|
25
|
-
response = @app.call(env)
|
26
|
-
rescue Sentry::Error
|
27
|
-
raise # Don't capture Sentry errors
|
28
|
-
rescue Exception => e
|
29
|
-
Sentry.capture_exception(e)
|
30
|
-
raise
|
31
|
-
end
|
32
|
-
|
33
|
-
exception = collect_exception(env)
|
34
|
-
Sentry.capture_exception(exception) if exception
|
35
|
-
|
36
|
-
response
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def collect_exception(env)
|
41
|
-
env['rack.exception'] || env['sinatra.error']
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
data/lib/sentry/rack/tracing.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
module Sentry
|
2
|
-
module Rack
|
3
|
-
class Tracing
|
4
|
-
def initialize(app)
|
5
|
-
@app = app
|
6
|
-
end
|
7
|
-
|
8
|
-
def call(env)
|
9
|
-
Sentry.clone_hub_to_current_thread unless Sentry.get_current_hub
|
10
|
-
|
11
|
-
if Sentry.configuration.traces_sample_rate.to_f == 0.0
|
12
|
-
return @app.call(env)
|
13
|
-
end
|
14
|
-
|
15
|
-
Sentry.with_scope do |scope|
|
16
|
-
scope.clear_breadcrumbs
|
17
|
-
scope.set_transaction_name(env["PATH_INFO"]) if env["PATH_INFO"]
|
18
|
-
span = Sentry.start_transaction(name: scope.transaction_name, op: "rack.request")
|
19
|
-
scope.set_span(span)
|
20
|
-
|
21
|
-
begin
|
22
|
-
response = @app.call(env)
|
23
|
-
rescue
|
24
|
-
finish_span(span, 500)
|
25
|
-
raise
|
26
|
-
end
|
27
|
-
|
28
|
-
finish_span(span, response[0])
|
29
|
-
response
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def finish_span(span, status_code)
|
34
|
-
span.set_http_status(status_code)
|
35
|
-
span.finish
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
module Sentry
|
2
|
-
class Transport
|
3
|
-
class State
|
4
|
-
def initialize
|
5
|
-
reset
|
6
|
-
end
|
7
|
-
|
8
|
-
def should_try?
|
9
|
-
return true if @status == :online
|
10
|
-
|
11
|
-
interval = @retry_after || [@retry_number, 6].min**2
|
12
|
-
return true if Sentry.utc_now - @last_check >= interval
|
13
|
-
|
14
|
-
false
|
15
|
-
end
|
16
|
-
|
17
|
-
def failure(retry_after = nil)
|
18
|
-
@status = :error
|
19
|
-
@retry_number += 1
|
20
|
-
@last_check = Sentry.utc_now
|
21
|
-
@retry_after = retry_after
|
22
|
-
end
|
23
|
-
|
24
|
-
def success
|
25
|
-
reset
|
26
|
-
end
|
27
|
-
|
28
|
-
def reset
|
29
|
-
@status = :online
|
30
|
-
@retry_number = 0
|
31
|
-
@last_check = nil
|
32
|
-
@retry_after = nil
|
33
|
-
end
|
34
|
-
|
35
|
-
def failed?
|
36
|
-
@status == :error
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|