sentry-ruby-core 4.1.5 → 4.3.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: c7862b3ddbb49c77b2c47c1a9509cce1efa4c193d459d0b3bd07bebd6aa9b62e
4
- data.tar.gz: faca1cc6efce70d3f64e1266c2e32fc2d67352544f8bfc2b2a278bcbefca1a61
3
+ metadata.gz: 66ef212c06425a29b56b64935c1fb662633fa80fb9f58b9680b1d95220ee8b5d
4
+ data.tar.gz: 18e211d0c93d18717795b23290c2cb7da503b0dcd1690c1c8b51861c3a37ef98
5
5
  SHA512:
6
- metadata.gz: 76dbfe0e360744126dcfdfce35d1563fb14387bafb1196c315fd1ef5e9d57c09d4d627f5a5386610a031a4909fab28a659bdfcd66e96d00a2e56c8737c130358
7
- data.tar.gz: e4c26db4e8bcaa1c6a32c4acadc9d385356b3617b8d5e76ffeda773b9deb4da291a77eafef27aa7bb98539cca187f27d174a7d0cc16c1ef8204c380e46fd54fc
6
+ metadata.gz: e334875a26a04e45a78c37e7bb0014604cd2b400b89eb01faa3ae21adc1f9072e46227ce880c1406148e32d6a125504dc08ffab5e1ac61c0b3befbd31e5352ea
7
+ data.tar.gz: 4c01fb8d489a3d143a738180f3f68ba62d3882267ecf17b82c3cf0e509ab36a8b458699d022d5d55699baacaccd2acc3bfede0d332ae5b50776128ac5c164a2a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,90 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.3.0
4
+
5
+ ### Features
6
+
7
+ - Allow configuring BreadcrumbBuffer's size limit [#1310](https://github.com/getsentry/sentry-ruby/pull/1310)
8
+
9
+ ```ruby
10
+ # the SDK will only store 10 breadcrumbs (default is 100)
11
+ config.max_breadcrumbs = 10
12
+ ```
13
+
14
+ - Compress event payload by default [#1314](https://github.com/getsentry/sentry-ruby/pull/1314)
15
+
16
+ ### Refatorings
17
+
18
+ - Refactor interface construction [#1296](https://github.com/getsentry/sentry-ruby/pull/1296)
19
+ - Refactor tracing implementation [#1309](https://github.com/getsentry/sentry-ruby/pull/1309)
20
+
21
+ ### Bug Fixes
22
+ - Improve SDK's error handling [#1298](https://github.com/getsentry/sentry-ruby/pull/1298)
23
+ - Fixes [#1246](https://github.com/getsentry/sentry-ruby/issues/1246) and [#1289](https://github.com/getsentry/sentry-ruby/issues/1289)
24
+ - Please read [#1290](https://github.com/getsentry/sentry-ruby/issues/1290) to see the full specification
25
+ - Treat query string as pii too [#1302](https://github.com/getsentry/sentry-ruby/pull/1302)
26
+ - Fixes [#1301](https://github.com/getsentry/sentry-ruby/issues/1301)
27
+ - Ignore sentry-trace when tracing is not enabled [#1308](https://github.com/getsentry/sentry-ruby/pull/1308)
28
+ - Fixes [#1307](https://github.com/getsentry/sentry-ruby/issues/1307)
29
+ - Return nil from logger methods instead of breadcrumb buffer [#1299](https://github.com/getsentry/sentry-ruby/pull/1299)
30
+ - Exceptions with nil message shouldn't cause issues [#1327](https://github.com/getsentry/sentry-ruby/pull/1327)
31
+ - Fixes [#1323](https://github.com/getsentry/sentry-ruby/issues/1323)
32
+ - Fix sampling decision with sentry-trace and add more tests [#1326](https://github.com/getsentry/sentry-ruby/pull/1326)
33
+
34
+ ## 4.2.2
35
+
36
+ - Add thread_id to Exception interface [#1291](https://github.com/getsentry/sentry-ruby/pull/1291)
37
+ - always convert trusted proxies to string [#1288](https://github.com/getsentry/sentry-ruby/pull/1288)
38
+ - fixes [#1274](https://github.com/getsentry/sentry-ruby/issues/1274)
39
+
40
+ ## 4.2.1
41
+
42
+ ### Bug Fixes
43
+
44
+ - Ignore invalid values for sentry-trace header that don't match the required format [#1265](https://github.com/getsentry/sentry-ruby/pull/1265)
45
+ - Transaction created by `.from_sentry_trace` should inherit sampling decision [#1269](https://github.com/getsentry/sentry-ruby/pull/1269)
46
+ - Transaction's sample rate should accept any numeric value [#1278](https://github.com/getsentry/sentry-ruby/pull/1278)
47
+
48
+ ## 4.2.0
49
+
50
+ ### Features
51
+
52
+ - Add configuration option for trusted proxies [#1126](https://github.com/getsentry/sentry-ruby/pull/1126)
53
+
54
+ ```ruby
55
+ config.trusted_proxies = ["2.2.2.2"] # this ip address will be skipped when computing users' ip addresses
56
+ ```
57
+
58
+ - Add ThreadsInterface [#1178](https://github.com/getsentry/sentry-ruby/pull/1178)
59
+
60
+ <img width="1029" alt="an exception event that has the new threads interface" src="https://user-images.githubusercontent.com/5079556/103459223-98b64c00-4d48-11eb-9ebb-ee58f15e647e.png">
61
+
62
+ - Support `config.before_breadcrumb` [#1253](https://github.com/getsentry/sentry-ruby/pull/1253)
63
+
64
+ ```ruby
65
+ # this will be called before every breadcrumb is added to the breadcrumb buffer
66
+ # you can use it to
67
+ # - remove the data you don't want to send
68
+ # - add additional info to the data
69
+ config.before_breadcrumb = lambda do |breadcrumb, hint|
70
+ breadcrumb.message = "foo"
71
+ breadcrumb
72
+ end
73
+ ```
74
+
75
+ - Add ability to have many post initialization callbacks [#1261](https://github.com/getsentry/sentry-ruby/pull/1261)
76
+
77
+ ### Bug Fixes
78
+
79
+ - Inspect exception cause by default & don't exclude ActiveJob::DeserializationError [#1180](https://github.com/getsentry/sentry-ruby/pull/1180)
80
+ - Fixes [#1071](https://github.com/getsentry/sentry-ruby/issues/1071)
81
+
82
+ ## 4.1.6
83
+
84
+ - Don't detect project root for Rails apps [#1243](https://github.com/getsentry/sentry-ruby/pull/1243)
85
+ - Separate individual breadcrumb's data serialization [#1250](https://github.com/getsentry/sentry-ruby/pull/1250)
86
+ - Capture sentry-trace with the correct http header key [#1260](https://github.com/getsentry/sentry-ruby/pull/1260)
87
+
3
88
  ## 4.1.5
4
89
 
5
90
  - Serialize event hint before passing it to the async block [#1231](https://github.com/getsentry/sentry-ruby/pull/1231)
@@ -134,4 +219,3 @@ Fix require reference
134
219
  ## 0.1.0
135
220
 
136
221
  First version
137
-
data/Gemfile CHANGED
@@ -3,6 +3,9 @@ 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"
8
+
6
9
  gem "rake", "~> 12.0"
7
10
  gem "rspec", "~> 3.0"
8
11
  gem "codecov", "0.2.12"
data/Makefile ADDED
@@ -0,0 +1,4 @@
1
+ build:
2
+ bundle install
3
+ gem build sentry-ruby-core.gemspec
4
+ gem build sentry-ruby.gemspec
data/README.md CHANGED
@@ -2,10 +2,14 @@
2
2
  <a href="https://sentry.io" target="_blank" align="center">
3
3
  <img src="https://sentry-brand.storage.googleapis.com/sentry-logo-black.png" width="280">
4
4
  </a>
5
- <br>
5
+ <br />
6
6
  </p>
7
7
 
8
- # sentry-ruby, the Ruby Client for Sentry
8
+ _Bad software is everywhere, and we're tired of it. Sentry is on a mission to help developers write better software faster, so we can get back to enjoying technology. If you want to join us [<kbd>**Check out our open positions**</kbd>](https://sentry.io/careers/)_
9
+
10
+ Sentry SDK for Ruby
11
+ ===========
12
+
9
13
 
10
14
  **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
15
 
@@ -26,7 +30,7 @@ The official Ruby-language client and integration layer for the [Sentry](https:/
26
30
 
27
31
  ## Requirements
28
32
 
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.
33
+ We test on Ruby 2.4, 2.5, 2.6, 2.7, and 3.0 at the latest patchlevel/teeny version. We also support JRuby 9.0.
30
34
 
31
35
  If you use self-hosted Sentry, please also make sure its version is above `20.6.0`.
32
36
 
@@ -47,6 +51,7 @@ and depends on the integrations you want to have, you might also want to install
47
51
  ```ruby
48
52
  gem "sentry-rails"
49
53
  gem "sentry-sidekiq"
54
+ gem "sentry-delayed_job"
50
55
  # and mores to come in the future!
51
56
  ```
52
57
 
@@ -136,6 +141,7 @@ We also provide integrations with popular frameworks/libraries with the related
136
141
 
137
142
  - [sentry-rails](https://github.com/getsentry/sentry-ruby/tree/master/sentry-rails)
138
143
  - [sentry-sidekiq](https://github.com/getsentry/sentry-ruby/tree/master/sentry-sidekiq)
144
+ - [sentry-delayed_job](https://github.com/getsentry/sentry-ruby/tree/master/sentry-delayed_job)
139
145
 
140
146
  ### More configuration
141
147
 
@@ -143,32 +149,7 @@ You're all set - but there's a few more settings you may want to know about too!
143
149
 
144
150
  #### Blocking v.s. Non-blocking
145
151
 
146
- **Before version 4.1.0**, `sentry-ruby` sends every event immediately. But it can be configured to send asynchronously:
147
-
148
- ```ruby
149
- config.async = lambda { |event, hint|
150
- Thread.new { Sentry.send_event(event, hint) }
151
- }
152
- ```
153
-
154
- Using a thread to send events will be adequate for truly parallel Ruby platforms such as JRuby, though the benefit on MRI/CRuby will be limited. If the async callback raises an exception, Sentry will attempt to send synchronously.
155
-
156
- Note that the naive example implementation has a major drawback - it can create an infinite number of threads. We recommend creating a background job, using your background job processor, that will send Sentry notifications in the background.
157
-
158
- ```ruby
159
- config.async = lambda { |event, hint| SentryJob.perform_later(event, hint) }
160
-
161
- class SentryJob < ActiveJob::Base
162
- queue_as :default
163
-
164
- def perform(event, hint)
165
- Sentry.send_event(event, hint)
166
- end
167
- end
168
- ```
169
-
170
-
171
- **After version 4.1.0**, `sentry-ruby` sends events asynchronously by default. The functionality works like this:
152
+ `sentry-ruby` sends events asynchronously by default. The functionality works like this:
172
153
 
173
154
  1. When the SDK is initialized, a `Sentry::BackgroundWorker` will be initialized too.
174
155
  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.
@@ -202,6 +183,21 @@ If you want to send a particular event immediately, you can use event hints to d
202
183
  Sentry.capture_message("send me now!", hint: { background: false })
203
184
  ```
204
185
 
186
+ ##### `config.async`
187
+
188
+ You can also use `config.async` to send events with you own worker:
189
+
190
+ ```ruby
191
+ config.async = lambda { |event, hint| SentryJob.perform_later(event, hint) }
192
+ ```
193
+
194
+ And if you use `sentry-rails`, you can directly use the job we defined for you:
195
+
196
+ ```ruby
197
+ config.async = lambda { |event, hint| Sentry::SendEventJob.perform_later(event, hint) }
198
+ ```
199
+
200
+
205
201
  #### Contexts
206
202
 
207
203
  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:
data/lib/sentry-ruby.rb CHANGED
@@ -3,6 +3,7 @@ require "forwardable"
3
3
  require "time"
4
4
 
5
5
  require "sentry/version"
6
+ require "sentry/exceptions"
6
7
  require "sentry/core_ext/object/deep_dup"
7
8
  require "sentry/utils/argument_checking_helper"
8
9
  require "sentry/configuration"
@@ -26,9 +27,6 @@ require "sentry/background_worker"
26
27
  end
27
28
 
28
29
  module Sentry
29
- class Error < StandardError
30
- end
31
-
32
30
  META = { "name" => "sentry.ruby", "version" => Sentry::VERSION }.freeze
33
31
 
34
32
  LOGGER_PROGNAME = "sentry".freeze
@@ -68,7 +66,7 @@ module Sentry
68
66
  config = Configuration.new
69
67
  yield(config) if block_given?
70
68
  client = Client.new(config)
71
- scope = Scope.new
69
+ scope = Scope.new(max_breadcrumbs: config.max_breadcrumbs)
72
70
  hub = Hub.new(client, scope)
73
71
  Thread.current[THREAD_LOCAL] = hub
74
72
  @main_hub = hub
@@ -1,5 +1,6 @@
1
1
  require "concurrent/executor/thread_pool_executor"
2
2
  require "concurrent/executor/immediate_executor"
3
+ require "concurrent/configuration"
3
4
 
4
5
  module Sentry
5
6
  class BackgroundWorker
@@ -1,5 +1,7 @@
1
1
  module Sentry
2
2
  class Breadcrumb
3
+ DATA_SERIALIZATION_ERROR_MESSAGE = "[data were removed due to serialization issues]"
4
+
3
5
  attr_accessor :category, :data, :message, :level, :timestamp, :type
4
6
 
5
7
  def initialize(category: nil, data: nil, message: nil, timestamp: nil, level: nil, type: nil)
@@ -13,13 +15,30 @@ module Sentry
13
15
 
14
16
  def to_hash
15
17
  {
16
- :category => @category,
17
- :data => @data,
18
- :level => @level,
19
- :message => @message,
20
- :timestamp => @timestamp,
21
- :type => @type
18
+ category: @category,
19
+ data: serialized_data,
20
+ level: @level,
21
+ message: @message,
22
+ timestamp: @timestamp,
23
+ type: @type
22
24
  }
23
25
  end
26
+
27
+ private
28
+
29
+ def serialized_data
30
+ begin
31
+ ::JSON.parse(::JSON.generate(@data))
32
+ rescue Exception => e
33
+ Sentry.logger.debug(LOGGER_PROGNAME) do
34
+ <<~MSG
35
+ can't serialize breadcrumb data because of error: #{e}
36
+ data: #{@data}
37
+ MSG
38
+ end
39
+
40
+ DATA_SERIALIZATION_ERROR_MESSAGE
41
+ end
42
+ end
24
43
  end
25
44
  end
@@ -14,6 +14,7 @@ module Sentry
14
14
  def add(*args, &block)
15
15
  super
16
16
  add_breadcrumb(*args, &block)
17
+ nil
17
18
  end
18
19
 
19
20
  def add_breadcrumb(severity, message = nil, progname = nil)
@@ -2,12 +2,13 @@ require "sentry/breadcrumb"
2
2
 
3
3
  module Sentry
4
4
  class BreadcrumbBuffer
5
+ DEFAULT_SIZE = 100
5
6
  include Enumerable
6
7
 
7
8
  attr_accessor :buffer
8
9
 
9
- def initialize(size = 100)
10
- @buffer = Array.new(size)
10
+ def initialize(size = nil)
11
+ @buffer = Array.new(size || DEFAULT_SIZE)
11
12
  end
12
13
 
13
14
  def record(crumb)
@@ -34,7 +35,7 @@ module Sentry
34
35
 
35
36
  def to_hash
36
37
  {
37
- :values => members.map(&:to_hash)
38
+ values: members.map(&:to_hash)
38
39
  }
39
40
  end
40
41
 
data/lib/sentry/client.rb CHANGED
@@ -2,10 +2,11 @@ require "sentry/transport"
2
2
 
3
3
  module Sentry
4
4
  class Client
5
- attr_reader :transport, :configuration
5
+ attr_reader :transport, :configuration, :logger
6
6
 
7
7
  def initialize(configuration)
8
8
  @configuration = configuration
9
+ @logger = configuration.logger
9
10
 
10
11
  if transport_class = configuration.transport.transport_class
11
12
  @transport = transport_class.new(configuration)
@@ -26,32 +27,17 @@ module Sentry
26
27
  scope.apply_to_event(event, hint)
27
28
 
28
29
  if async_block = configuration.async
29
- begin
30
- # We have to convert to a JSON-like hash, because background job
31
- # processors (esp ActiveJob) may not like weird types in the event hash
32
- event_hash = event.to_json_compatible
33
-
34
- if async_block.arity == 2
35
- hint = JSON.parse(JSON.generate(hint))
36
- async_block.call(event_hash, hint)
37
- else
38
- async_block.call(event_hash)
39
- end
40
- rescue => e
41
- configuration.logger.error(LOGGER_PROGNAME) { "async event sending failed: #{e.message}" }
42
- send_event(event, hint)
43
- end
30
+ dispatch_async_event(async_block, event, hint)
31
+ elsif hint.fetch(:background, true)
32
+ dispatch_background_event(event, hint)
44
33
  else
45
- if hint.fetch(:background, true)
46
- Sentry.background_worker.perform do
47
- send_event(event, hint)
48
- end
49
- else
50
- send_event(event, hint)
51
- end
34
+ send_event(event, hint)
52
35
  end
53
36
 
54
37
  event
38
+ rescue => e
39
+ logger.error(LOGGER_PROGNAME) { "Event capturing failed: #{e.message}" }
40
+ nil
55
41
  end
56
42
 
57
43
  def event_from_exception(exception, hint = {})
@@ -60,12 +46,15 @@ module Sentry
60
46
 
61
47
  Event.new(configuration: configuration, integration_meta: integration_meta).tap do |event|
62
48
  event.add_exception_interface(exception)
49
+ event.add_threads_interface(crashed: true)
63
50
  end
64
51
  end
65
52
 
66
53
  def event_from_message(message, hint = {})
67
54
  integration_meta = Sentry.integrations[hint[:integration]]
68
- Event.new(configuration: configuration, integration_meta: integration_meta, message: message)
55
+ event = Event.new(configuration: configuration, integration_meta: integration_meta, message: message)
56
+ event.add_threads_interface(backtrace: caller)
57
+ event
69
58
  end
70
59
 
71
60
  def event_from_transaction(transaction)
@@ -82,16 +71,49 @@ module Sentry
82
71
 
83
72
  def send_event(event, hint = nil)
84
73
  event_type = event.is_a?(Event) ? event.type : event["type"]
85
- event = configuration.before_send.call(event, hint) if configuration.before_send && event_type == "event"
86
74
 
87
- if event.nil?
88
- configuration.logger.info(LOGGER_PROGNAME) { "Discarded event because before_send returned nil" }
89
- return
75
+ if event_type == "event" && configuration.before_send
76
+ event = configuration.before_send.call(event, hint)
77
+
78
+ if event.nil?
79
+ logger.info(LOGGER_PROGNAME) { "Discarded event because before_send returned nil" }
80
+ return
81
+ end
90
82
  end
91
83
 
92
84
  transport.send_event(event)
93
85
 
94
86
  event
87
+ rescue => e
88
+ logger.error(LOGGER_PROGNAME) { "#{event_type.capitalize} sending failed: #{e.message}" }
89
+ logger.error(LOGGER_PROGNAME) { "Unreported #{event_type.capitalize}: #{Event.get_log_message(event.to_hash)}" }
90
+ raise
91
+ end
92
+
93
+ private
94
+
95
+ def dispatch_background_event(event, hint)
96
+ Sentry.background_worker.perform do
97
+ send_event(event, hint)
98
+ end
95
99
  end
100
+
101
+ def dispatch_async_event(async_block, event, hint)
102
+ # We have to convert to a JSON-like hash, because background job
103
+ # processors (esp ActiveJob) may not like weird types in the event hash
104
+ event_hash = event.to_json_compatible
105
+
106
+ if async_block.arity == 2
107
+ hint = JSON.parse(JSON.generate(hint))
108
+ async_block.call(event_hash, hint)
109
+ else
110
+ async_block.call(event_hash)
111
+ end
112
+ rescue => e
113
+ event_type = event_hash["type"]
114
+ logger.error(LOGGER_PROGNAME) { "Async #{event_type} sending failed: #{e.message}" }
115
+ send_event(event, hint)
116
+ end
117
+
96
118
  end
97
119
  end