sentry-ruby-core 4.4.0 → 5.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -0
  3. data/CHANGELOG.md +12 -0
  4. data/Gemfile +9 -5
  5. data/LICENSE.txt +1 -1
  6. data/README.md +29 -175
  7. data/bin/console +5 -1
  8. data/lib/sentry/background_worker.rb +33 -3
  9. data/lib/sentry/backtrace.rb +1 -3
  10. data/lib/sentry/breadcrumb/sentry_logger.rb +3 -1
  11. data/lib/sentry/breadcrumb.rb +28 -2
  12. data/lib/sentry/breadcrumb_buffer.rb +16 -0
  13. data/lib/sentry/client.rb +66 -7
  14. data/lib/sentry/configuration.rb +156 -112
  15. data/lib/sentry/core_ext/object/deep_dup.rb +4 -0
  16. data/lib/sentry/core_ext/object/duplicable.rb +2 -0
  17. data/lib/sentry/dsn.rb +6 -1
  18. data/lib/sentry/envelope.rb +49 -0
  19. data/lib/sentry/event.rb +65 -23
  20. data/lib/sentry/exceptions.rb +2 -0
  21. data/lib/sentry/hub.rb +37 -6
  22. data/lib/sentry/integrable.rb +2 -0
  23. data/lib/sentry/interface.rb +3 -10
  24. data/lib/sentry/interfaces/exception.rb +13 -3
  25. data/lib/sentry/interfaces/request.rb +52 -21
  26. data/lib/sentry/interfaces/single_exception.rb +31 -0
  27. data/lib/sentry/interfaces/stacktrace.rb +14 -0
  28. data/lib/sentry/interfaces/stacktrace_builder.rb +39 -10
  29. data/lib/sentry/interfaces/threads.rb +12 -2
  30. data/lib/sentry/linecache.rb +3 -0
  31. data/lib/sentry/net/http.rb +79 -51
  32. data/lib/sentry/rack/capture_exceptions.rb +2 -0
  33. data/lib/sentry/rack.rb +2 -1
  34. data/lib/sentry/rake.rb +33 -9
  35. data/lib/sentry/redis.rb +88 -0
  36. data/lib/sentry/release_detector.rb +39 -0
  37. data/lib/sentry/scope.rb +76 -6
  38. data/lib/sentry/span.rb +84 -8
  39. data/lib/sentry/transaction.rb +50 -13
  40. data/lib/sentry/transaction_event.rb +19 -6
  41. data/lib/sentry/transport/configuration.rb +4 -2
  42. data/lib/sentry/transport/dummy_transport.rb +2 -0
  43. data/lib/sentry/transport/http_transport.rb +55 -42
  44. data/lib/sentry/transport.rb +101 -32
  45. data/lib/sentry/utils/argument_checking_helper.rb +2 -0
  46. data/lib/sentry/utils/custom_inspection.rb +14 -0
  47. data/lib/sentry/utils/exception_cause_chain.rb +10 -10
  48. data/lib/sentry/utils/logging_helper.rb +6 -4
  49. data/lib/sentry/utils/real_ip.rb +9 -1
  50. data/lib/sentry/utils/request_id.rb +2 -0
  51. data/lib/sentry/version.rb +3 -1
  52. data/lib/sentry-ruby.rb +247 -47
  53. data/sentry-ruby-core.gemspec +2 -3
  54. data/sentry-ruby.gemspec +2 -3
  55. metadata +10 -22
  56. data/.craft.yml +0 -29
  57. data/lib/sentry/benchmarks/benchmark_transport.rb +0 -14
  58. data/lib/sentry/rack/deprecations.rb +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a6ec50e2aac42f99230cb5a3f78970b057535aae4d31b1dd94e18b0fdf8995be
4
- data.tar.gz: 162dc5844575766403454816354ec4b93ac0c05950c44251963fdcbea685f8e4
3
+ metadata.gz: bfc28e6f57d57de669447d555889196617f72ce09624b343cd284375021f60f5
4
+ data.tar.gz: 5a6af91521df30a18ac1d021b2e59cd9e871653f1325cf6d65346e6c1dc91d7e
5
5
  SHA512:
6
- metadata.gz: bed995802c6f5b4c628071283aacd5f9804ec1a963202fb2cf63170bc5c3bf75a16dcebc64520aa5b209bbef6042765456df9ff012512b66ba95261553732d1b
7
- data.tar.gz: da726d263583d1db7f5c163cfb5c4e947e3cd4145e512229f37ca8e2a416c62b2284a1a465d26af1155be12ccaf053e93ec74968aff415cca544ff71140e8038
6
+ metadata.gz: fbe80e4c07f972d3babbf8c26c31cd97da84e91d77e86628a6931f35d7e66c83fb48461838d1a3e402361ee78dd9a3b6dfe849833f08a4573328d0eb4b5e66e1
7
+ data.tar.gz: 0f081f57f89207ece5279bd77fa89d311c3d516231421ccf60f4b9c232065a606d80eacc53ab460f12e087aa7b2fadfc4cdd4636863cb58261cc4e58a605ad2c
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --exclude lib/sentry/utils/
2
+ --exclude lib/sentry/core_ext
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
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
+
5
+ ## 4.4.2
6
+
7
+ - Fix NoMethodError when SDK's dsn is nil [#1433](https://github.com/getsentry/sentry-ruby/pull/1433)
8
+ - fix: Update protocol version to 7 [#1434](https://github.com/getsentry/sentry-ruby/pull/1434)
9
+ - Fixes [#867](https://github.com/getsentry/sentry-ruby/issues/867)
10
+
11
+ ## 4.4.1
12
+
13
+ - Apply patches when initializing the SDK [#1432](https://github.com/getsentry/sentry-ruby/pull/1432)
14
+
3
15
  ## 4.4.0
4
16
 
5
17
  ### Features
data/Gemfile CHANGED
@@ -3,21 +3,25 @@ source "https://rubygems.org"
3
3
  gem "sentry-ruby-core", path: "./"
4
4
  gem "sentry-ruby", path: "./"
5
5
 
6
- # TODO: Remove this if https://github.com/jruby/jruby/issues/6547 is addressed
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"
12
+ gem "fakeredis"
13
13
  gem "timecop"
14
- gem "codecov", "0.2.12"
15
- gem "tapping_device"
14
+ gem 'simplecov'
15
+ gem "simplecov-cobertura", "~> 1.4"
16
+ gem "rexml"
16
17
 
18
+ gem "object_tracer"
19
+ gem "debug", github: "ruby/debug", platform: :ruby if RUBY_VERSION.to_f >= 2.6
17
20
  gem "pry"
18
- gem "rack" unless ENV["WITHOUT_RACK"] == "1"
19
21
 
20
22
  gem "benchmark-ips"
21
23
  gem "benchmark_driver"
22
24
  gem "benchmark-ipsa"
23
25
  gem "benchmark-memory"
26
+
27
+ gem "yard", "~> 0.9.27"
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2020 st0012
3
+ Copyright (c) 2020 Sentry
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
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 | semver stability |
14
- | --- | ----- | -------- | --------- | ---------------- |
15
- | [![Gem Version](https://img.shields.io/gem/v/sentry-ruby?label=sentry-ruby)](https://github.com/getsentry/sentry-ruby/blob/master/sentry-ruby/CHANGELOG.md) | ![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-ruby%20Test/badge.svg) | [![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/) | [![SemVer stability](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) |
16
- | [![Gem Version](https://img.shields.io/gem/v/sentry-rails?label=sentry-rails)](https://github.com/getsentry/sentry-ruby/blob/master/sentry-rails/CHANGELOG.md) | ![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-rails%20Test/badge.svg) | [![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/) | [![SemVer stability](https://api.dependabot.com/badges/compatibility_score?dependency-name=sentry-rails&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=sentry-rails&package-manager=bundler&version-scheme=semver) |
17
- | [![Gem Version](https://img.shields.io/gem/v/sentry-sidekiq?label=sentry-sidekiq)](https://github.com/getsentry/sentry-ruby/blob/master/sentry-sidekiq/CHANGELOG.md) | ![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-sidekiq%20Test/badge.svg) | [![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/) | [![SemVer stability](https://api.dependabot.com/badges/compatibility_score?dependency-name=sentry-sidekiq&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=sentry-sidekiq&package-manager=bundler&version-scheme=semver) |
18
- | [![Gem Version](https://img.shields.io/gem/v/sentry-delayed_job?label=sentry-delayed_job)](https://github.com/getsentry/sentry-ruby/blob/master/sentry-delayed_job/CHANGELOG.md) | ![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-delayed_job%20Test/badge.svg) | [![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/) | [![SemVer stability](https://api.dependabot.com/badges/compatibility_score?dependency-name=sentry-delayed_job&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=sentry-delayed_job&package-manager=bundler&version-scheme=semver) |
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
- # and mores to come in the future!
50
+ gem "sentry-resque"
50
51
  ```
51
52
 
52
- ### Sentry only runs when Sentry DSN is set
53
+ ### Configuration
53
54
 
54
- Sentry will capture and send exceptions to the Sentry server whenever its DSN is set. This makes environment-based configuration easy - if you don't want to send errors in a certain environment, just don't set the DSN in that environment!
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 = 'http://public@example.com/project-id'
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
- # or control sampling dynamically
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
- Or build up a temporary scope for local information:
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
- Sentry.with_scope do |scope|
230
- scope.set_tags(tag_1: "bar", tag_2: "baz")
81
+ ### [Migration Guide](https://docs.sentry.io/platforms/ruby/migration/)
231
82
 
232
- Sentry.capture_message("message") # this event will have 2 tags: tag_1 => "bar" and tag_2 => "baz"
233
- end
83
+ ### Integrations
234
84
 
235
- Sentry.capture_message("another message") # this event will have 1 tag: tag_1 => "foo"
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
- Of course, you can always assign the information on a per-event basis:
91
+ ### Enriching Events
239
92
 
240
- ```ruby
241
- Sentry.capture_exception(exception, tags: {foo: "bar"})
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/ruby"
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, :logger
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
- block.call
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
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- ## Inspired by Rails' and Airbrake's backtrace parsers.
4
-
5
3
  module Sentry
6
- # Front end to parsing the backtrace for each notice
4
+ # @api private
7
5
  class Backtrace
8
6
  # Handles backtrace parsing line by line
9
7
  class Line
@@ -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
 
@@ -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
- attr_accessor :category, :data, :message, :level, :timestamp, :type
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