sentry-ruby 0.1.3 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b16bf44cdc5e7689122b6727e08f680c7cfb98be5bebba286fdfc8a9e9f2cb81
4
- data.tar.gz: 55a4793366f3e1a1dba8db0bec236d5c7bed5b2f1cb838244faaf629f4a1edb4
3
+ metadata.gz: 517c3e0bc0ab170dbd508034bf74b3a9ba62a1a32f13a992ba84d65f81249e01
4
+ data.tar.gz: 8a86690e05e1695f15e2da33002ecd52b4596ef8dbd2e9c0a7461f94a8868906
5
5
  SHA512:
6
- metadata.gz: 99da84ece5e4ee5c459fa93284edfa2154c4bb0409278bb763ff98c2ceeddb57821f173c8fe3d1cf3a1cfa48d9d168e676f8cc666117604d7b367c5f8f352f4c
7
- data.tar.gz: aed7ff1ecf47362e8f8be166cc173b0b5ef62dacd17dc21d7d10e6c8240193024b934d1b510cbb72ccd39837c24b79421b568577ad3e3921adbb4b050395a976
6
+ metadata.gz: 3cc45e503a6ed19a5cc507ab0791087e432b612581498e84403fd806e0d9538ff02f57c2fbb64294ba9895514218bca05610f637a8708a752e6eaf42fa61bfaa
7
+ data.tar.gz: 9eb027f449b6bdee43316e3b78364d1680d56442b5f34ec82b49059a9f28418a51448e24e45318efb022e526b62e067e410a8e78eb3b67678f1e18ce46866004
@@ -1,5 +1,74 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.1.0
4
+
5
+ - Separate rack integration [#1138](https://github.com/getsentry/sentry-ruby/pull/1138)
6
+ - Fixes [#1136](https://github.com/getsentry/sentry-ruby/pull/1136)
7
+ - Fix event sampling [#1144](https://github.com/getsentry/sentry-ruby/pull/1144)
8
+ - Merge & rename 2 Rack middlewares [#1147](https://github.com/getsentry/sentry-ruby/pull/1147)
9
+ - Fixes [#1153](https://github.com/getsentry/sentry-ruby/pull/1153)
10
+ - Removed `Sentry::Rack::Tracing` middleware and renamed `Sentry::Rack::CaptureException` to `Sentry::Rack::CaptureExceptions`.
11
+ - Deep-copy spans [#1148](https://github.com/getsentry/sentry-ruby/pull/1148)
12
+ - Move span recorder related code from Span to Transaction [#1149](https://github.com/getsentry/sentry-ruby/pull/1149)
13
+ - Check SDK initialization before running integrations [#1151](https://github.com/getsentry/sentry-ruby/pull/1151)
14
+ - Fixes [#1145](https://github.com/getsentry/sentry-ruby/pull/1145)
15
+ - Refactor transport [#1154](https://github.com/getsentry/sentry-ruby/pull/1154)
16
+ - Implement non-blocking event sending [#1155](https://github.com/getsentry/sentry-ruby/pull/1155)
17
+ - Added `background_worker_threads` configuration option.
18
+
19
+ ### Noticeable Changes
20
+
21
+ #### Middleware Changes
22
+
23
+ `Sentry::Rack::Tracing` is now removed. And `Sentry::Rack::CaptureException` has been renamed to `Sentry::Rack::CaptureExceptions`.
24
+
25
+ #### Events Are Sent Asynchronously
26
+
27
+ `sentry-ruby` now sends events asynchronously by default. The functionality works like this:
28
+
29
+ 1. When the SDK is initialized, a `Sentry::BackgroundWorker` will be initialized too.
30
+ 2. When an event is passed to `Client#capture_event`, instead of sending it directly with `Client#send_event`, we'll let the worker do it.
31
+ 3. The worker will have a number of threads. And the one of the idle threads will pick the job and call `Client#send_event`.
32
+ - If all the threads are busy, new jobs will be put into a queue, which has a limit of 30.
33
+ - If the queue size is exceeded, new events will be dropped.
34
+
35
+ However, if you still prefer to use your own async approach, that's totally fine. If you have `config.async` set, the worker won't initialize a thread pool and won't be used either.
36
+
37
+ This functionality also introduces a new `background_worker_threads` config option. It allows you to decide how many threads should the worker hold. By default, the value will be the number of the processors your machine has. For example, if your machine has 4 processors, the value would be 4.
38
+
39
+ Of course, you can always override the value to fit your use cases, like
40
+
41
+ ```ruby
42
+ config.background_worker_threads = 5 # the worker will have 5 threads for sending events
43
+ ```
44
+
45
+ You can also disable this new non-blocking behaviour by giving a `0` value:
46
+
47
+ ```ruby
48
+ config.background_worker_threads = 0 # all events will be sent synchronously
49
+ ```
50
+
51
+ ## 4.0.1
52
+
53
+ - Add rake integration: [1137](https://github.com/getsentry/sentry-ruby/pull/1137)
54
+ - Make Event's interfaces accessible: [1135](https://github.com/getsentry/sentry-ruby/pull/1135)
55
+ - ActiveSupportLogger should only record events that has a started time: [1132](https://github.com/getsentry/sentry-ruby/pull/1132)
56
+
57
+ ## 4.0.0
58
+
59
+ - Only documents update for the official release and no API/feature changes.
60
+
61
+ ## 0.3.0
62
+
63
+ - Major API changes: [1123](https://github.com/getsentry/sentry-ruby/pull/1123)
64
+ - Support event hint: [1122](https://github.com/getsentry/sentry-ruby/pull/1122)
65
+ - Add request-id tag to events: [1120](https://github.com/getsentry/sentry-ruby/pull/1120) (by @tvec)
66
+
67
+ ## 0.2.0
68
+
69
+ - Multiple fixes and refactorings
70
+ - Tracing support
71
+
3
72
  ## 0.1.3
4
73
 
5
74
  Fix require reference
data/Gemfile CHANGED
@@ -8,4 +8,9 @@ gem "rspec", "~> 3.0"
8
8
  gem "codecov"
9
9
 
10
10
  gem "pry"
11
- gem "rack"
11
+ gem "rack" unless ENV["WITHOUT_RACK"] == "1"
12
+
13
+ gem "benchmark-ips"
14
+ gem "benchmark_driver"
15
+ gem "benchmark-ipsa"
16
+ gem "benchmark-memory"
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/clients/ruby/) | [Bug Tracker](https://github.com/getsentry/sentry-ruby/issues) | [Forum](https://forum.sentry.io/) | IRC: irc.freenode.net, #sentry
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
- use Sentry::Rack::CaptureException
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
- run theapp
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
- #### async
142
+ #### Blocking v.s. Non-blocking
108
143
 
109
- When an error or message occurs, the notification is immediately sent to Sentry. Sentry can be configured to send asynchronously:
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/clients/ruby/)
254
+ * [Documentation](https://docs.sentry.io/platforms/ruby/)
176
255
  * [Bug Tracker](https://github.com/getsentry/sentry-ruby/issues)
177
256
  * [Forum](https://forum.sentry.io/)
178
257
  - [Discord](https://discord.gg/ez5KZN7)
258
+
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rspec/core/rake_task"
3
3
 
4
- RSpec::Core::RakeTask.new(:spec)
4
+ RSpec::Core::RakeTask.new(:spec).tap do |task|
5
+ task.rspec_opts = "--order rand"
6
+ end
5
7
 
6
8
  task :default => :spec
@@ -1,10 +1,26 @@
1
+ require "forwardable"
2
+ require "time"
3
+
1
4
  require "sentry/version"
2
5
  require "sentry/core_ext/object/deep_dup"
3
6
  require "sentry/configuration"
4
7
  require "sentry/logger"
5
8
  require "sentry/event"
9
+ require "sentry/transaction_event"
10
+ require "sentry/span"
11
+ require "sentry/transaction"
6
12
  require "sentry/hub"
7
- require "sentry/rack"
13
+ require "sentry/background_worker"
14
+
15
+ def safely_require(lib)
16
+ begin
17
+ require lib
18
+ rescue LoadError
19
+ end
20
+ end
21
+
22
+ safely_require "sentry/rake"
23
+ safely_require "sentry/rack"
8
24
 
9
25
  module Sentry
10
26
  class Error < StandardError
@@ -20,7 +36,17 @@ module Sentry
20
36
  META
21
37
  end
22
38
 
39
+ def self.utc_now
40
+ Time.now.utc
41
+ end
42
+
23
43
  class << self
44
+ extend Forwardable
45
+
46
+ def_delegators :get_current_scope, :set_tags, :set_extras, :set_user
47
+
48
+ attr_accessor :background_worker
49
+
24
50
  def init(&block)
25
51
  config = Configuration.new
26
52
  yield(config)
@@ -29,6 +55,11 @@ module Sentry
29
55
  hub = Hub.new(client, scope)
30
56
  Thread.current[THREAD_LOCAL] = hub
31
57
  @main_hub = hub
58
+ @background_worker = Sentry::BackgroundWorker.new(config)
59
+ end
60
+
61
+ def initialized?
62
+ !!@main_hub
32
63
  end
33
64
 
34
65
  def get_main_hub
@@ -39,8 +70,8 @@ module Sentry
39
70
  configuration.logger
40
71
  end
41
72
 
42
- def breadcrumbs
43
- get_current_scope.breadcrumbs
73
+ def add_breadcrumb(breadcrumb, &block)
74
+ get_current_scope.breadcrumbs.record(breadcrumb, &block)
44
75
  end
45
76
 
46
77
  def configuration
@@ -92,6 +123,10 @@ module Sentry
92
123
  get_current_hub.capture_message(message, **options, &block)
93
124
  end
94
125
 
126
+ def start_transaction(**options)
127
+ get_current_hub.start_transaction(**options)
128
+ end
129
+
95
130
  def last_event_id
96
131
  get_current_hub.last_event_id
97
132
  end
@@ -0,0 +1,37 @@
1
+ require "concurrent/executor/thread_pool_executor"
2
+ require "concurrent/executor/immediate_executor"
3
+
4
+ module Sentry
5
+ class BackgroundWorker
6
+ attr_reader :max_queue, :number_of_threads
7
+
8
+ def initialize(configuration)
9
+ @max_queue = 30
10
+ @number_of_threads = configuration.background_worker_threads
11
+
12
+ @executor =
13
+ if configuration.async?
14
+ configuration.logger.debug(LOGGER_PROGNAME) { "config.async is set, BackgroundWorker is disabled" }
15
+ Concurrent::ImmediateExecutor.new
16
+ elsif @number_of_threads == 0
17
+ configuration.logger.debug(LOGGER_PROGNAME) { "config.background_worker_threads is set to 0, all events will be sent synchronously" }
18
+ Concurrent::ImmediateExecutor.new
19
+ else
20
+ configuration.logger.debug(LOGGER_PROGNAME) { "initialized a background worker with #{@number_of_threads} threads" }
21
+
22
+ Concurrent::ThreadPoolExecutor.new(
23
+ min_threads: 0,
24
+ max_threads: @number_of_threads,
25
+ max_queue: @max_queue,
26
+ fallback_policy: :discard
27
+ )
28
+ end
29
+ end
30
+
31
+ def perform(&block)
32
+ @executor.post do
33
+ block.call
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,14 @@
1
+ module Sentry
2
+ class BenchmarkTransport < Transport
3
+ attr_accessor :events
4
+
5
+ def initialize(*)
6
+ super
7
+ @events = []
8
+ end
9
+
10
+ def send_event(event)
11
+ @events << encode(event.to_hash)
12
+ end
13
+ end
14
+ end
@@ -2,13 +2,13 @@ module Sentry
2
2
  class Breadcrumb
3
3
  attr_accessor :category, :data, :message, :level, :timestamp, :type
4
4
 
5
- def initialize
6
- @category = nil
7
- @data = {}
8
- @level = nil
9
- @message = nil
10
- @timestamp = Time.now.to_i
11
- @type = nil
5
+ def initialize(category: nil, data: nil, message: nil, timestamp: nil, level: nil, type: nil)
6
+ @category = category
7
+ @data = data || {}
8
+ @level = level
9
+ @message = message
10
+ @timestamp = timestamp || Sentry.utc_now.to_i
11
+ @type = type
12
12
  end
13
13
 
14
14
  def to_hash
@@ -58,17 +58,15 @@ module Sentry
58
58
  last_crumb = current_breadcrumbs.peek
59
59
  # try to avoid dupes from logger broadcasts
60
60
  if last_crumb.nil? || last_crumb.message != message
61
- current_breadcrumbs.record do |crumb|
62
- crumb.level = Sentry::Breadcrumb::SentryLogger::LEVELS.fetch(severity, nil)
63
- crumb.category = category
64
- crumb.message = message
65
- crumb.type =
66
- if severity >= 3
67
- "error"
68
- else
69
- crumb.level
70
- end
71
- end
61
+ level = Sentry::Breadcrumb::SentryLogger::LEVELS.fetch(severity, nil)
62
+ crumb = Sentry::Breadcrumb.new(
63
+ level: level,
64
+ category: category,
65
+ message: message,
66
+ type: severity >= 3 ? "error" : level
67
+ )
68
+
69
+ Sentry.add_breadcrumb(crumb)
72
70
  end
73
71
  end
74
72
 
@@ -80,21 +78,7 @@ module Sentry
80
78
  end
81
79
 
82
80
  def current_breadcrumbs
83
- Sentry.breadcrumbs
84
- end
85
- end
86
- module OldBreadcrumbsSentryLogger
87
- def self.included(base)
88
- base.class_eval do
89
- include Sentry::Breadcrumbs::SentryLogger
90
- alias_method :add_without_sentry, :add
91
- alias_method :add, :add_with_sentry
92
- end
93
- end
94
-
95
- def add_with_sentry(*args)
96
- add_breadcrumb(*args)
97
- add_without_sentry(*args)
81
+ Sentry.get_current_scope.breadcrumbs
98
82
  end
99
83
  end
100
84
  end