sentry-ruby-core 4.3.1 → 4.4.2

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: 8a2e4ce39cece4f17353a14a3984cfaf57b9fc1f9288915a36f9c5ae56e719cd
4
- data.tar.gz: 77ebe61492554532ce811320fbae436735c82ac3a0586176ee53b040211d6b81
3
+ metadata.gz: 46eeab9b7fdc33dd16bbcdd3c7623dcffdc2e70d1c9af0016c4584a08bf743dd
4
+ data.tar.gz: 0ebfed842099817048aeb8754f27dfd7e637a66d8b9f64267bd1953cbd1f9645
5
5
  SHA512:
6
- metadata.gz: 34504541c4743476d4360e7b452e8a7a4b9a3bd66d80878a768d839d8fe00e5294c2e385d62d50527ddf957368a660c8276342abf72a82079583c0a33385e29d
7
- data.tar.gz: d050d0b1bf6346553db6cc02e84b144908d877bd1883243526b0366e21eb97e924cf2f23c2c8ad10383785a90e05337615041ac6d9c87c36694d6077e3f6481d
6
+ metadata.gz: 76284658bda5c4856caf4017046d7f1d6481a11d9287ab0b9ac8363248d1606c7b7a274c9018b56db33062682ceac0f090d614b154048d9e17da4b0a11c98de1
7
+ data.tar.gz: 3462df382685823d4cd77ac0278644144b0570c04f15db4b2a58d591de8cb25fe3762f222adaf4bb990934c476bfc49b18dfc072021e96bb3f50943caa3dceca
data/.craft.yml CHANGED
@@ -13,9 +13,6 @@ targets:
13
13
  # we always need to make sure sentry-ruby-core is present when pushing to any target
14
14
  - name: gem
15
15
  onlyIfPresent: /^sentry-ruby-core-\d.*\.gem$/
16
- - name: github
17
- onlyIfPresent: /^sentry-ruby-core-\d.*\.gem$/
18
- tagPrefix: sentry-ruby-v
19
16
  - name: registry
20
17
  onlyIfPresent: /^sentry-ruby-core-\d.*\.gem$/
21
18
  type: sdk
@@ -26,3 +23,6 @@ targets:
26
23
  type: sdk
27
24
  config:
28
25
  canonical: 'gem:sentry-ruby-core'
26
+ - name: github
27
+ onlyIfPresent: /^sentry-ruby-core-\d.*\.gem$/
28
+ tagPrefix: sentry-ruby-v
data/CHANGELOG.md CHANGED
@@ -1,5 +1,87 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.4.2
4
+
5
+ - Fix NoMethodError when SDK's dsn is nil [#1433](https://github.com/getsentry/sentry-ruby/pull/1433)
6
+ - fix: Update protocol version to 7 [#1434](https://github.com/getsentry/sentry-ruby/pull/1434)
7
+ - Fixes [#867](https://github.com/getsentry/sentry-ruby/issues/867)
8
+
9
+ ## 4.4.1
10
+
11
+ - Apply patches when initializing the SDK [#1432](https://github.com/getsentry/sentry-ruby/pull/1432)
12
+
13
+ ## 4.4.0
14
+
15
+ ### Features
16
+
17
+ #### Support category-based rate limiting [#1336](https://github.com/getsentry/sentry-ruby/pull/1336)
18
+
19
+ Sentry rate limits different types of events. And when rate limiting is enabled, it sends back a `429` response to the SDK. Currently, the SDK would then raise an error like this:
20
+
21
+ ```
22
+ Unable to record event with remote Sentry server (Sentry::Error - the server responded with status 429
23
+ body: {"detail":"event rejected due to rate limit"}):
24
+ ```
25
+
26
+ This change improves the SDK's handling on such responses by:
27
+
28
+ - Not treating them as errors, so you don't see the noise anymore.
29
+ - Halting event sending for a while according to the duration provided in the response. And warns you with a message like:
30
+
31
+ ```
32
+ Envelope [event] not sent: Excluded by random sample
33
+ ```
34
+
35
+ #### Record request span from Net::HTTP library [#1381](https://github.com/getsentry/sentry-ruby/pull/1381)
36
+
37
+ Now any outgoing requests will be recorded as a tracing span. Example:
38
+
39
+ <img width="60%" alt="net:http span example" src="https://user-images.githubusercontent.com/5079556/115838944-c1279a80-a44c-11eb-8c67-dfd92bf68bbd.png">
40
+
41
+
42
+ #### Record breadcrumb for Net::HTTP requests [#1394](https://github.com/getsentry/sentry-ruby/pull/1394)
43
+
44
+ With the new `http_logger` breadcrumbs logger:
45
+
46
+ ```ruby
47
+ config.breadcrumbs_logger = [:http_logger]
48
+ ```
49
+
50
+ The SDK now records a new `net.http` breadcrumb whenever the user makes a request with the `Net::HTTP` library.
51
+
52
+ <img width="60%" alt="net http breadcrumb" src="https://user-images.githubusercontent.com/5079556/114298326-5f7c3d80-9ae8-11eb-9108-222384a7f1a2.png">
53
+
54
+ #### Support config.debug configuration option [#1400](https://github.com/getsentry/sentry-ruby/pull/1400)
55
+
56
+ It'll determine whether the SDK should run in the debugging mode. Default is `false`. When set to true, SDK errors will be logged with backtrace.
57
+
58
+ #### Add the third tracing state [#1402](https://github.com/getsentry/sentry-ruby/pull/1402)
59
+ - `rate == 0` - Tracing enabled. Rejects all locally created transactions but respects sentry-trace.
60
+ - `1 > rate > 0` - Tracing enabled. Samples locally created transactions with the rate and respects sentry-trace.
61
+ - `rate < 0` or `rate > 1` - Tracing disabled.
62
+
63
+ ### Refactorings
64
+
65
+ - Let Transaction constructor take an optional hub argument [#1384](https://github.com/getsentry/sentry-ruby/pull/1384)
66
+ - Introduce LoggingHelper [#1385](https://github.com/getsentry/sentry-ruby/pull/1385)
67
+ - Raise exception if a Transaction is initialized without a hub [#1391](https://github.com/getsentry/sentry-ruby/pull/1391)
68
+ - Make hub a required argument for Transaction constructor [#1401](https://github.com/getsentry/sentry-ruby/pull/1401)
69
+
70
+ ### Bug Fixes
71
+
72
+ - Check `Scope#set_context`'s value argument [#1415](https://github.com/getsentry/sentry-ruby/pull/1415)
73
+ - Disable tracing if events are not allowed to be sent [#1421](https://github.com/getsentry/sentry-ruby/pull/1421)
74
+
75
+ ## 4.3.2
76
+
77
+ - Correct type attribute's usages [#1354](https://github.com/getsentry/sentry-ruby/pull/1354)
78
+ - Fix sampling decision precedence [#1335](https://github.com/getsentry/sentry-ruby/pull/1335)
79
+ - Fix set_contexts [#1375](https://github.com/getsentry/sentry-ruby/pull/1375)
80
+ - Use thread variable instead of fiber variable to store the hub [#1380](https://github.com/getsentry/sentry-ruby/pull/1380)
81
+ - Fixes [#1374](https://github.com/getsentry/sentry-ruby/issues/1374)
82
+ - Fix Span/Transaction's nesting issue [#1382](https://github.com/getsentry/sentry-ruby/pull/1382)
83
+ - Fixes [#1372](https://github.com/getsentry/sentry-ruby/issues/1372)
84
+
3
85
  ## 4.3.1
4
86
 
5
87
  - Add Sentry.set_context helper [#1337](https://github.com/getsentry/sentry-ruby/pull/1337)
data/Gemfile CHANGED
@@ -9,7 +9,10 @@ gem "i18n", "<= 1.8.7"
9
9
  gem "rake", "~> 12.0"
10
10
  gem "rspec", "~> 3.0"
11
11
  gem "rspec-retry"
12
+ gem "webmock"
13
+ gem "timecop"
12
14
  gem "codecov", "0.2.12"
15
+ gem "tapping_device"
13
16
 
14
17
  gem "pry"
15
18
  gem "rack" unless ENV["WITHOUT_RACK"] == "1"
data/README.md CHANGED
@@ -10,23 +10,21 @@ _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
-
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).**
15
-
16
- ---
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) |
17
19
 
18
20
 
19
- [![Gem Version](https://img.shields.io/gem/v/sentry-ruby.svg)](https://rubygems.org/gems/sentry-ruby)
20
- ![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-ruby%20Test/badge.svg)
21
- [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master)
22
- [![Gem](https://img.shields.io/gem/dt/sentry-ruby.svg)](https://rubygems.org/gems/sentry-ruby/)
23
- [![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)
24
21
 
25
22
 
26
- [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
23
+ ## Migrate From sentry-raven
27
24
 
28
- The official Ruby-language client and integration layer for the [Sentry](https://github.com/getsentry/sentry) error reporting API.
25
+ **The old `sentry-raven` client has entered maintenance mode and was moved to [here](https://github.com/getsentry/sentry-ruby/tree/master/sentry-raven).**
29
26
 
27
+ 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/).
30
28
 
31
29
  ## Requirements
32
30
 
@@ -34,10 +32,6 @@ We test on Ruby 2.4, 2.5, 2.6, 2.7, and 3.0 at the latest patchlevel/teeny versi
34
32
 
35
33
  If you use self-hosted Sentry, please also make sure its version is above `20.6.0`.
36
34
 
37
- ## Migrate From sentry-raven
38
-
39
- 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/).
40
-
41
35
  ## Getting Started
42
36
 
43
37
  ### Install
@@ -247,10 +241,10 @@ Of course, you can always assign the information on a per-event basis:
247
241
  Sentry.capture_exception(exception, tags: {foo: "bar"})
248
242
  ```
249
243
 
250
- ## More Information
251
-
252
- - [Documentation](https://docs.sentry.io/platforms/ruby/)
253
- - [Bug Tracker](https://github.com/getsentry/sentry-ruby/issues)
254
- - [Forum](https://forum.sentry.io/)
255
- - [Discord](https://discord.gg/ez5KZN7)
244
+ ## Resources
256
245
 
246
+ * [![Ruby docs](https://img.shields.io/badge/documentation-sentry.io-green.svg?label=ruby%20docs)](https://docs.sentry.io/platforms/ruby/)
247
+ * [![Forum](https://img.shields.io/badge/forum-sentry-green.svg)](https://forum.sentry.io/c/sdks)
248
+ * [![Discord Chat](https://img.shields.io/discord/621778831602221064?logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/PXa5Apfe7K)
249
+ * [![Stack Overflow](https://img.shields.io/badge/stack%20overflow-sentry-green.svg)](https://stackoverflow.com/questions/tagged/sentry)
250
+ * [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry)
data/lib/sentry-ruby.rb CHANGED
@@ -6,6 +6,7 @@ require "sentry/version"
6
6
  require "sentry/exceptions"
7
7
  require "sentry/core_ext/object/deep_dup"
8
8
  require "sentry/utils/argument_checking_helper"
9
+ require "sentry/utils/logging_helper"
9
10
  require "sentry/configuration"
10
11
  require "sentry/logger"
11
12
  require "sentry/event"
@@ -62,13 +63,30 @@ module Sentry
62
63
 
63
64
  attr_accessor :background_worker
64
65
 
66
+ @@registered_patches = []
67
+
68
+ def register_patch(&block)
69
+ registered_patches << block
70
+ end
71
+
72
+ def apply_patches(config)
73
+ registered_patches.each do |patch|
74
+ patch.call(config)
75
+ end
76
+ end
77
+
78
+ def registered_patches
79
+ @@registered_patches
80
+ end
81
+
65
82
  def init(&block)
66
83
  config = Configuration.new
67
84
  yield(config) if block_given?
85
+ apply_patches(config)
68
86
  client = Client.new(config)
69
87
  scope = Scope.new(max_breadcrumbs: config.max_breadcrumbs)
70
88
  hub = Hub.new(client, scope)
71
- Thread.current[THREAD_LOCAL] = hub
89
+ Thread.current.thread_variable_set(THREAD_LOCAL, hub)
72
90
  @main_hub = hub
73
91
  @background_worker = Sentry::BackgroundWorker.new(config)
74
92
  end
@@ -92,7 +110,7 @@ module Sentry
92
110
  # ideally, we should do this proactively whenever a new thread is created
93
111
  # but it's impossible for the SDK to keep track every new thread
94
112
  # so we need to use this rather passive way to make sure the app doesn't crash
95
- Thread.current[THREAD_LOCAL] || clone_hub_to_current_thread
113
+ Thread.current.thread_variable_get(THREAD_LOCAL) || clone_hub_to_current_thread
96
114
  end
97
115
 
98
116
  # Returns the current active client.
@@ -107,7 +125,7 @@ module Sentry
107
125
 
108
126
  # Clones the main thread's active hub and stores it to the current thread.
109
127
  def clone_hub_to_current_thread
110
- Thread.current[THREAD_LOCAL] = get_main_hub.clone
128
+ Thread.current.thread_variable_set(THREAD_LOCAL, get_main_hub.clone)
111
129
  end
112
130
 
113
131
  # Takes a block and yields the current active scope.
@@ -188,3 +206,6 @@ module Sentry
188
206
  end
189
207
  end
190
208
  end
209
+
210
+ # patches
211
+ require "sentry/net/http"
@@ -4,21 +4,24 @@ require "concurrent/configuration"
4
4
 
5
5
  module Sentry
6
6
  class BackgroundWorker
7
- attr_reader :max_queue, :number_of_threads
7
+ include LoggingHelper
8
+
9
+ attr_reader :max_queue, :number_of_threads, :logger
8
10
 
9
11
  def initialize(configuration)
10
12
  @max_queue = 30
11
13
  @number_of_threads = configuration.background_worker_threads
14
+ @logger = configuration.logger
12
15
 
13
16
  @executor =
14
17
  if configuration.async
15
- configuration.logger.debug(LOGGER_PROGNAME) { "config.async is set, BackgroundWorker is disabled" }
18
+ log_debug("config.async is set, BackgroundWorker is disabled")
16
19
  Concurrent::ImmediateExecutor.new
17
20
  elsif @number_of_threads == 0
18
- configuration.logger.debug(LOGGER_PROGNAME) { "config.background_worker_threads is set to 0, all events will be sent synchronously" }
21
+ log_debug("config.background_worker_threads is set to 0, all events will be sent synchronously")
19
22
  Concurrent::ImmediateExecutor.new
20
23
  else
21
- configuration.logger.debug(LOGGER_PROGNAME) { "initialized a background worker with #{@number_of_threads} threads" }
24
+ log_debug("initialized a background worker with #{@number_of_threads} threads")
22
25
 
23
26
  Concurrent::ThreadPoolExecutor.new(
24
27
  min_threads: 0,
data/lib/sentry/client.rb CHANGED
@@ -2,6 +2,8 @@ require "sentry/transport"
2
2
 
3
3
  module Sentry
4
4
  class Client
5
+ include LoggingHelper
6
+
5
7
  attr_reader :transport, :configuration, :logger
6
8
 
7
9
  def initialize(configuration)
@@ -36,7 +38,7 @@ module Sentry
36
38
 
37
39
  event
38
40
  rescue => e
39
- logger.error(LOGGER_PROGNAME) { "Event capturing failed: #{e.message}" }
41
+ log_error("Event capturing failed", e, debug: configuration.debug)
40
42
  nil
41
43
  end
42
44
 
@@ -72,11 +74,11 @@ module Sentry
72
74
  def send_event(event, hint = nil)
73
75
  event_type = event.is_a?(Event) ? event.type : event["type"]
74
76
 
75
- if event_type == "event" && configuration.before_send
77
+ if event_type != TransactionEvent::TYPE && configuration.before_send
76
78
  event = configuration.before_send.call(event, hint)
77
79
 
78
80
  if event.nil?
79
- logger.info(LOGGER_PROGNAME) { "Discarded event because before_send returned nil" }
81
+ log_info("Discarded event because before_send returned nil")
80
82
  return
81
83
  end
82
84
  end
@@ -85,8 +87,11 @@ module Sentry
85
87
 
86
88
  event
87
89
  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
+ loggable_event_type = (event_type || "event").capitalize
91
+ log_error("#{loggable_event_type} sending failed", e, debug: configuration.debug)
92
+
93
+ event_info = Event.get_log_message(event.to_hash)
94
+ log_info("Unreported #{loggable_event_type}: #{event_info}")
90
95
  raise
91
96
  end
92
97
 
@@ -110,10 +115,9 @@ module Sentry
110
115
  async_block.call(event_hash)
111
116
  end
112
117
  rescue => e
113
- event_type = event_hash["type"]
114
- logger.error(LOGGER_PROGNAME) { "Async #{event_type} sending failed: #{e.message}" }
118
+ loggable_event_type = event_hash["type"] || "event"
119
+ log_error("Async #{loggable_event_type} sending failed", e, debug: configuration.debug)
115
120
  send_event(event, hint)
116
121
  end
117
-
118
122
  end
119
123
  end
@@ -8,6 +8,7 @@ require "sentry/interfaces/stacktrace_builder"
8
8
 
9
9
  module Sentry
10
10
  class Configuration
11
+ include LoggingHelper
11
12
  # Directories to be recognized as part of your app. e.g. if you
12
13
  # have an `engines` dir at the root of your project, you may want
13
14
  # to set this to something like /(app|config|engines|lib)/
@@ -71,6 +72,10 @@ module Sentry
71
72
  # RACK_ENV by default.
72
73
  attr_reader :environment
73
74
 
75
+ # Whether the SDK should run in the debugging mode. Default is false.
76
+ # If set to true, SDK errors will be logged with backtrace
77
+ attr_accessor :debug
78
+
74
79
  # the dsn value, whether it's set via `config.dsn=` or `ENV["SENTRY_DSN"]`
75
80
  attr_reader :dsn
76
81
 
@@ -167,13 +172,12 @@ module Sentry
167
172
  LOG_PREFIX = "** [Sentry] ".freeze
168
173
  MODULE_SEPARATOR = "::".freeze
169
174
 
170
- AVAILABLE_BREADCRUMBS_LOGGERS = [:sentry_logger, :active_support_logger].freeze
171
-
172
175
  # Post initialization callbacks are called at the end of initialization process
173
176
  # allowing extending the configuration of sentry-ruby by multiple extensions
174
177
  @@post_initialization_callbacks = []
175
178
 
176
179
  def initialize
180
+ self.debug = false
177
181
  self.background_worker_threads = Concurrent.processor_count
178
182
  self.max_breadcrumbs = BreadcrumbBuffer::DEFAULT_SIZE
179
183
  self.breadcrumbs_logger = []
@@ -226,10 +230,6 @@ module Sentry
226
230
  if logger.is_a?(Array)
227
231
  logger
228
232
  else
229
- unless AVAILABLE_BREADCRUMBS_LOGGERS.include?(logger)
230
- raise Sentry::Error, "Unsupported breadcrumbs logger. Supported loggers: #{AVAILABLE_BREADCRUMBS_LOGGERS}"
231
- end
232
-
233
233
  Array(logger)
234
234
  end
235
235
 
@@ -278,10 +278,10 @@ module Sentry
278
278
  def exception_class_allowed?(exc)
279
279
  if exc.is_a?(Sentry::Error)
280
280
  # Try to prevent error reporting loops
281
- logger.debug(LOGGER_PROGNAME) { "Refusing to capture Sentry error: #{exc.inspect}" }
281
+ log_debug("Refusing to capture Sentry error: #{exc.inspect}")
282
282
  false
283
283
  elsif excluded_exception?(exc)
284
- logger.debug(LOGGER_PROGNAME) { "User excluded error: #{exc.inspect}" }
284
+ log_debug("User excluded error: #{exc.inspect}")
285
285
  false
286
286
  else
287
287
  true
@@ -293,7 +293,7 @@ module Sentry
293
293
  end
294
294
 
295
295
  def tracing_enabled?
296
- !!((@traces_sample_rate && @traces_sample_rate > 0.0) || @traces_sampler)
296
+ !!((@traces_sample_rate && @traces_sample_rate >= 0.0 && @traces_sample_rate <= 1.0) || @traces_sampler) && sending_allowed?
297
297
  end
298
298
 
299
299
  def stacktrace_builder
@@ -314,7 +314,7 @@ module Sentry
314
314
  detect_release_from_capistrano ||
315
315
  detect_release_from_heroku
316
316
  rescue => e
317
- logger.error(LOGGER_PROGNAME) { "Error detecting release: #{e.message}" }
317
+ log_error("Error detecting release", e, debug: debug)
318
318
  end
319
319
 
320
320
  def excluded_exception?(incoming_exception)
@@ -349,7 +349,7 @@ module Sentry
349
349
  def detect_release_from_heroku
350
350
  return unless running_on_heroku?
351
351
  return if ENV['CI']
352
- logger.warn(LOGGER_PROGNAME) { HEROKU_DYNO_METADATA_MESSAGE } && return unless ENV['HEROKU_SLUG_COMMIT']
352
+ log_warn(HEROKU_DYNO_METADATA_MESSAGE) && return unless ENV['HEROKU_SLUG_COMMIT']
353
353
 
354
354
  ENV['HEROKU_SLUG_COMMIT']
355
355
  end
data/lib/sentry/event.rb CHANGED
@@ -100,7 +100,6 @@ module Sentry
100
100
  end
101
101
 
102
102
  def type
103
- "event"
104
103
  end
105
104
 
106
105
  def to_hash
data/lib/sentry/hub.rb CHANGED
@@ -21,6 +21,10 @@ module Sentry
21
21
  current_layer&.client
22
22
  end
23
23
 
24
+ def configuration
25
+ current_client.configuration
26
+ end
27
+
24
28
  def current_scope
25
29
  current_layer&.scope
26
30
  end
@@ -69,11 +73,19 @@ module Sentry
69
73
  @stack.pop
70
74
  end
71
75
 
72
- def start_transaction(transaction: nil, configuration: Sentry.configuration, **options)
76
+ def start_transaction(transaction: nil, custom_sampling_context: {}, **options)
73
77
  return unless configuration.tracing_enabled?
74
78
 
75
- transaction ||= Transaction.new(**options)
76
- transaction.set_initial_sample_decision(configuration: current_client.configuration)
79
+ transaction ||= Transaction.new(**options.merge(hub: self))
80
+
81
+ sampling_context = {
82
+ transaction_context: transaction.to_hash,
83
+ parent_sampled: transaction.parent_sampled
84
+ }
85
+
86
+ sampling_context.merge!(custom_sampling_context)
87
+
88
+ transaction.set_initial_sample_decision(sampling_context: sampling_context)
77
89
  transaction
78
90
  end
79
91
 
@@ -0,0 +1,90 @@
1
+ require "net/http"
2
+
3
+ module Sentry
4
+ module Net
5
+ module HTTP
6
+ OP_NAME = "net.http"
7
+
8
+ def request(req, body = nil, &block)
9
+ super.tap do |res|
10
+ record_sentry_breadcrumb(req, res)
11
+ record_sentry_span(req, res)
12
+ end
13
+ end
14
+
15
+ def do_start
16
+ super.tap do
17
+ start_sentry_span
18
+ end
19
+ end
20
+
21
+ def do_finish
22
+ super.tap do
23
+ finish_sentry_span
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def record_sentry_breadcrumb(req, res)
30
+ if Sentry.initialized? && Sentry.configuration.breadcrumbs_logger.include?(:http_logger)
31
+ return if from_sentry_sdk?
32
+
33
+ request_info = extract_request_info(req)
34
+ crumb = Sentry::Breadcrumb.new(
35
+ level: :info,
36
+ category: OP_NAME,
37
+ type: :info,
38
+ data: {
39
+ method: request_info[:method],
40
+ url: request_info[:url],
41
+ status: res.code.to_i
42
+ }
43
+ )
44
+ Sentry.add_breadcrumb(crumb)
45
+ end
46
+ end
47
+
48
+ def record_sentry_span(req, res)
49
+ if Sentry.initialized? && @sentry_span
50
+ request_info = extract_request_info(req)
51
+ @sentry_span.set_description("#{request_info[:method]} #{request_info[:url]}")
52
+ @sentry_span.set_data(:status, res.code.to_i)
53
+ end
54
+ end
55
+
56
+ def start_sentry_span
57
+ if Sentry.initialized? && transaction = Sentry.get_current_scope.get_transaction
58
+ return if from_sentry_sdk?
59
+ return if transaction.sampled == false
60
+
61
+ child_span = transaction.start_child(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f)
62
+ @sentry_span = child_span
63
+ end
64
+ end
65
+
66
+ def finish_sentry_span
67
+ if Sentry.initialized? && @sentry_span
68
+ @sentry_span.set_timestamp(Sentry.utc_now.to_f)
69
+ @sentry_span = nil
70
+ end
71
+ end
72
+
73
+ def from_sentry_sdk?
74
+ dsn = Sentry.configuration.dsn
75
+ dsn && dsn.host == self.address
76
+ end
77
+
78
+ def extract_request_info(req)
79
+ uri = req.uri
80
+ url = "#{uri.scheme}://#{uri.host}#{uri.path}" rescue uri.to_s
81
+ { method: req.method, url: url }
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ Sentry.register_patch do
88
+ patch = Sentry::Net::HTTP
89
+ Net::HTTP.send(:prepend, patch) unless Net::HTTP.ancestors.include?(patch)
90
+ end
data/lib/sentry/scope.rb CHANGED
@@ -126,10 +126,11 @@ module Sentry
126
126
 
127
127
  def set_contexts(contexts_hash)
128
128
  check_argument_type!(contexts_hash, Hash)
129
- @contexts = contexts_hash
129
+ @contexts.merge!(contexts_hash)
130
130
  end
131
131
 
132
132
  def set_context(key, value)
133
+ check_argument_type!(value, Hash)
133
134
  @contexts.merge!(key => value)
134
135
  end
135
136
 
@@ -146,8 +147,7 @@ module Sentry
146
147
  end
147
148
 
148
149
  def get_transaction
149
- # transaction will always be the first in the span_recorder
150
- span.span_recorder.spans.first if span
150
+ span.transaction if span
151
151
  end
152
152
 
153
153
  def get_span
data/lib/sentry/span.rb CHANGED
@@ -19,9 +19,18 @@ module Sentry
19
19
 
20
20
 
21
21
  attr_reader :trace_id, :span_id, :parent_span_id, :sampled, :start_timestamp, :timestamp, :description, :op, :status, :tags, :data
22
- attr_accessor :span_recorder
23
-
24
- def initialize(description: nil, op: nil, status: nil, trace_id: nil, parent_span_id: nil, sampled: nil, start_timestamp: nil, timestamp: nil)
22
+ attr_accessor :span_recorder, :transaction
23
+
24
+ def initialize(
25
+ description: nil,
26
+ op: nil,
27
+ status: nil,
28
+ trace_id: nil,
29
+ parent_span_id: nil,
30
+ sampled: nil,
31
+ start_timestamp: nil,
32
+ timestamp: nil
33
+ )
25
34
  @trace_id = trace_id || SecureRandom.uuid.delete("-")
26
35
  @span_id = SecureRandom.hex(8)
27
36
  @parent_span_id = parent_span_id
@@ -78,7 +87,15 @@ module Sentry
78
87
 
79
88
  def start_child(**options)
80
89
  options = options.dup.merge(trace_id: @trace_id, parent_span_id: @span_id, sampled: @sampled)
81
- Span.new(**options)
90
+ new_span = Span.new(**options)
91
+ new_span.transaction = transaction
92
+ new_span.span_recorder = span_recorder
93
+
94
+ if span_recorder
95
+ span_recorder.add(new_span)
96
+ end
97
+
98
+ new_span
82
99
  end
83
100
 
84
101
  def with_child_span(**options, &block)
@@ -10,37 +10,38 @@ module Sentry
10
10
  UNLABELD_NAME = "<unlabeled transaction>".freeze
11
11
  MESSAGE_PREFIX = "[Tracing]"
12
12
 
13
- attr_reader :name, :parent_sampled
13
+ include LoggingHelper
14
14
 
15
- def initialize(name: nil, parent_sampled: nil, **options)
15
+ attr_reader :name, :parent_sampled, :hub, :configuration, :logger
16
+
17
+ def initialize(name: nil, parent_sampled: nil, hub:, **options)
16
18
  super(**options)
17
19
 
18
20
  @name = name
19
21
  @parent_sampled = parent_sampled
20
- set_span_recorder
21
- end
22
-
23
- def set_span_recorder
24
- @span_recorder = SpanRecorder.new(1000)
25
- @span_recorder.add(self)
22
+ @transaction = self
23
+ @hub = hub
24
+ @configuration = hub.configuration
25
+ @logger = configuration.logger
26
+ init_span_recorder
26
27
  end
27
28
 
28
- def self.from_sentry_trace(sentry_trace, configuration: Sentry.configuration, **options)
29
- return unless configuration.tracing_enabled?
29
+ def self.from_sentry_trace(sentry_trace, hub: Sentry.get_current_hub, **options)
30
+ return unless hub.configuration.tracing_enabled?
30
31
  return unless sentry_trace
31
32
 
32
33
  match = SENTRY_TRACE_REGEXP.match(sentry_trace)
33
34
  return if match.nil?
34
35
  trace_id, parent_span_id, sampled_flag = match[1..3]
35
36
 
36
- sampled =
37
+ parent_sampled =
37
38
  if sampled_flag.nil?
38
39
  nil
39
40
  else
40
41
  sampled_flag != "0"
41
42
  end
42
43
 
43
- new(trace_id: trace_id, parent_span_id: parent_span_id, parent_sampled: sampled, sampled: sampled, **options)
44
+ new(trace_id: trace_id, parent_span_id: parent_span_id, parent_sampled: parent_sampled, hub: hub, **options)
44
45
  end
45
46
 
46
47
  def to_hash
@@ -49,20 +50,9 @@ module Sentry
49
50
  hash
50
51
  end
51
52
 
52
- def start_child(**options)
53
- child_span = super
54
- child_span.span_recorder = @span_recorder
55
-
56
- if @sampled
57
- @span_recorder.add(child_span)
58
- end
59
-
60
- child_span
61
- end
62
-
63
53
  def deep_dup
64
54
  copy = super
65
- copy.set_span_recorder
55
+ copy.init_span_recorder(@span_recorder.max_length)
66
56
 
67
57
  @span_recorder.spans.each do |span|
68
58
  # span_recorder's first span is the current span, which should not be added to the copy's spans
@@ -73,7 +63,7 @@ module Sentry
73
63
  copy
74
64
  end
75
65
 
76
- def set_initial_sample_decision(sampling_context: {}, configuration: Sentry.configuration)
66
+ def set_initial_sample_decision(sampling_context:)
77
67
  unless configuration.tracing_enabled?
78
68
  @sampled = false
79
69
  return
@@ -81,30 +71,28 @@ module Sentry
81
71
 
82
72
  return unless @sampled.nil?
83
73
 
84
- transaction_description = generate_transaction_description
85
-
86
- logger = configuration.logger
87
- sample_rate = configuration.traces_sample_rate
88
74
  traces_sampler = configuration.traces_sampler
89
75
 
90
- if traces_sampler.is_a?(Proc)
91
- sampling_context = sampling_context.merge(
92
- parent_sampled: @parent_sampled,
93
- transaction_context: self.to_hash
94
- )
76
+ sample_rate =
77
+ if traces_sampler.is_a?(Proc)
78
+ traces_sampler.call(sampling_context)
79
+ elsif !sampling_context[:parent_sampled].nil?
80
+ sampling_context[:parent_sampled]
81
+ else
82
+ configuration.traces_sample_rate
83
+ end
95
84
 
96
- sample_rate = traces_sampler.call(sampling_context)
97
- end
85
+ transaction_description = generate_transaction_description
98
86
 
99
87
  unless [true, false].include?(sample_rate) || (sample_rate.is_a?(Numeric) && sample_rate >= 0.0 && sample_rate <= 1.0)
100
88
  @sampled = false
101
- logger.warn("#{MESSAGE_PREFIX} Discarding #{transaction_description} because of invalid sample_rate: #{sample_rate}")
89
+ log_warn("#{MESSAGE_PREFIX} Discarding #{transaction_description} because of invalid sample_rate: #{sample_rate}")
102
90
  return
103
91
  end
104
92
 
105
93
  if sample_rate == 0.0 || sample_rate == false
106
94
  @sampled = false
107
- logger.debug("#{MESSAGE_PREFIX} Discarding #{transaction_description} because traces_sampler returned 0 or false")
95
+ log_debug("#{MESSAGE_PREFIX} Discarding #{transaction_description} because traces_sampler returned 0 or false")
108
96
  return
109
97
  end
110
98
 
@@ -115,15 +103,26 @@ module Sentry
115
103
  end
116
104
 
117
105
  if @sampled
118
- logger.debug("#{MESSAGE_PREFIX} Starting #{transaction_description}")
106
+ log_debug("#{MESSAGE_PREFIX} Starting #{transaction_description}")
119
107
  else
120
- logger.debug(
108
+ log_debug(
121
109
  "#{MESSAGE_PREFIX} Discarding #{transaction_description} because it's not included in the random sample (sampling rate = #{sample_rate})"
122
110
  )
123
111
  end
124
112
  end
125
113
 
126
114
  def finish(hub: nil)
115
+ if hub
116
+ log_warn(
117
+ <<~MSG
118
+ Specifying a different hub in `Transaction#finish` will be deprecated in version 5.0.
119
+ Please use `Hub#start_transaction` with the designated hub.
120
+ MSG
121
+ )
122
+ end
123
+
124
+ hub ||= @hub
125
+
127
126
  super() # Span#finish doesn't take arguments
128
127
 
129
128
  if @name.nil?
@@ -132,11 +131,17 @@ module Sentry
132
131
 
133
132
  return unless @sampled || @parent_sampled
134
133
 
135
- hub ||= Sentry.get_current_hub
136
134
  event = hub.current_client.event_from_transaction(self)
137
135
  hub.capture_event(event)
138
136
  end
139
137
 
138
+ protected
139
+
140
+ def init_span_recorder(limit = 1000)
141
+ @span_recorder = SpanRecorder.new(limit)
142
+ @span_recorder.add(self)
143
+ end
144
+
140
145
  private
141
146
 
142
147
  def generate_transaction_description
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Sentry
4
4
  class TransactionEvent < Event
5
+ TYPE = "transaction"
6
+
5
7
  ATTRIBUTES = %i(
6
8
  event_id level timestamp start_timestamp
7
9
  release environment server_name modules
@@ -17,7 +19,7 @@ module Sentry
17
19
  end
18
20
 
19
21
  def type
20
- "transaction"
22
+ TYPE
21
23
  end
22
24
 
23
25
  def to_hash
@@ -3,15 +3,20 @@ require "base64"
3
3
 
4
4
  module Sentry
5
5
  class Transport
6
- PROTOCOL_VERSION = '5'
6
+ PROTOCOL_VERSION = '7'
7
7
  USER_AGENT = "sentry-ruby/#{Sentry::VERSION}"
8
8
 
9
+ include LoggingHelper
10
+
9
11
  attr_accessor :configuration
12
+ attr_reader :logger, :rate_limits
10
13
 
11
14
  def initialize(configuration)
12
15
  @configuration = configuration
16
+ @logger = configuration.logger
13
17
  @transport_configuration = configuration.transport
14
18
  @dsn = configuration.dsn
19
+ @rate_limits = {}
15
20
  end
16
21
 
17
22
  def send_data(data, options = {})
@@ -19,12 +24,22 @@ module Sentry
19
24
  end
20
25
 
21
26
  def send_event(event)
27
+ event_hash = event.to_hash
28
+ item_type = get_item_type(event_hash)
29
+
22
30
  unless configuration.sending_allowed?
23
- configuration.logger.debug(LOGGER_PROGNAME) { "Event not sent: #{configuration.error_messages}" }
31
+ log_debug("Envelope [#{item_type}] not sent: #{configuration.error_messages}")
32
+
33
+ return
34
+ end
35
+
36
+ if is_rate_limited?(item_type)
37
+ log_info("Envelope [#{item_type}] not sent: rate limiting")
38
+
24
39
  return
25
40
  end
26
41
 
27
- encoded_data = prepare_encoded_event(event)
42
+ encoded_data = encode(event)
28
43
 
29
44
  return nil unless encoded_data
30
45
 
@@ -33,6 +48,35 @@ module Sentry
33
48
  event
34
49
  end
35
50
 
51
+ def is_rate_limited?(item_type)
52
+ # check category-specific limit
53
+ category_delay =
54
+ case item_type
55
+ when "transaction"
56
+ @rate_limits["transaction"]
57
+ else
58
+ @rate_limits["error"]
59
+ end
60
+
61
+ # check universal limit if not category limit
62
+ universal_delay = @rate_limits[nil]
63
+
64
+ delay =
65
+ if category_delay && universal_delay
66
+ if category_delay > universal_delay
67
+ category_delay
68
+ else
69
+ universal_delay
70
+ end
71
+ elsif category_delay
72
+ category_delay
73
+ else
74
+ universal_delay
75
+ end
76
+
77
+ !!delay && delay > Time.now
78
+ end
79
+
36
80
  def generate_auth_header
37
81
  now = Sentry.utc_now.to_i
38
82
  fields = {
@@ -45,29 +89,28 @@ module Sentry
45
89
  'Sentry ' + fields.map { |key, value| "#{key}=#{value}" }.join(', ')
46
90
  end
47
91
 
48
- def encode(event_hash)
49
- event_id = event_hash[:event_id] || event_hash['event_id']
50
- event_type = event_hash[:type] || event_hash['type']
92
+ def encode(event)
93
+ # Convert to hash
94
+ event_hash = event.to_hash
95
+
96
+ event_id = event_hash[:event_id] || event_hash["event_id"]
97
+ item_type = get_item_type(event_hash)
51
98
 
52
99
  envelope = <<~ENVELOPE
53
100
  {"event_id":"#{event_id}","dsn":"#{configuration.dsn.to_s}","sdk":#{Sentry.sdk_meta.to_json},"sent_at":"#{Sentry.utc_now.iso8601}"}
54
- {"type":"#{event_type}","content_type":"application/json"}
101
+ {"type":"#{item_type}","content_type":"application/json"}
55
102
  #{JSON.generate(event_hash)}
56
103
  ENVELOPE
57
104
 
105
+ log_info("Sending envelope [#{item_type}] #{event_id} to Sentry")
106
+
58
107
  envelope
59
108
  end
60
109
 
61
110
  private
62
111
 
63
- def prepare_encoded_event(event)
64
- # Convert to hash
65
- event_hash = event.to_hash
66
-
67
- event_id = event_hash[:event_id] || event_hash["event_id"]
68
- event_type = event_hash[:type] || event_hash["type"]
69
- configuration.logger.info(LOGGER_PROGNAME) { "Sending #{event_type} #{event_id} to Sentry" }
70
- encode(event_hash)
112
+ def get_item_type(event_hash)
113
+ event_hash[:type] || event_hash["type"] || "event"
71
114
  end
72
115
  end
73
116
  end
@@ -7,6 +7,10 @@ module Sentry
7
7
  GZIP_THRESHOLD = 1024 * 30
8
8
  CONTENT_TYPE = 'application/x-sentry-envelope'
9
9
 
10
+ DEFAULT_DELAY = 60
11
+ RETRY_AFTER_HEADER = "retry-after"
12
+ RATE_LIMIT_HEADER = "x-sentry-rate-limits"
13
+
10
14
  attr_reader :conn, :adapter
11
15
 
12
16
  def initialize(*args)
@@ -24,18 +28,26 @@ module Sentry
24
28
  encoding = GZIP_ENCODING
25
29
  end
26
30
 
27
- conn.post @endpoint do |req|
31
+ response = conn.post @endpoint do |req|
28
32
  req.headers['Content-Type'] = CONTENT_TYPE
29
33
  req.headers['Content-Encoding'] = encoding
30
34
  req.headers['X-Sentry-Auth'] = generate_auth_header
31
35
  req.body = data
32
36
  end
37
+
38
+ if has_rate_limited_header?(response.headers)
39
+ handle_rate_limited_response(response.headers)
40
+ end
33
41
  rescue Faraday::Error => e
34
42
  error_info = e.message
35
43
 
36
44
  if e.response
37
- error_info += "\nbody: #{e.response[:body]}"
38
- error_info += " Error in headers is: #{e.response[:headers]['x-sentry-error']}" if e.response[:headers]['x-sentry-error']
45
+ if e.response[:status] == 429
46
+ handle_rate_limited_response(e.response[:headers])
47
+ else
48
+ error_info += "\nbody: #{e.response[:body]}"
49
+ error_info += " Error in headers is: #{e.response[:headers]['x-sentry-error']}" if e.response[:headers]['x-sentry-error']
50
+ end
39
51
  end
40
52
 
41
53
  raise Sentry::ExternalError, error_info
@@ -43,6 +55,64 @@ module Sentry
43
55
 
44
56
  private
45
57
 
58
+ def has_rate_limited_header?(headers)
59
+ headers[RETRY_AFTER_HEADER] || headers[RATE_LIMIT_HEADER]
60
+ end
61
+
62
+ def handle_rate_limited_response(headers)
63
+ rate_limits =
64
+ if rate_limits = headers[RATE_LIMIT_HEADER]
65
+ parse_rate_limit_header(rate_limits)
66
+ elsif retry_after = headers[RETRY_AFTER_HEADER]
67
+ # although Sentry doesn't send a date string back
68
+ # based on HTTP specification, this could be a date string (instead of an integer)
69
+ retry_after = retry_after.to_i
70
+ retry_after = DEFAULT_DELAY if retry_after == 0
71
+
72
+ { nil => Time.now + retry_after }
73
+ else
74
+ { nil => Time.now + DEFAULT_DELAY }
75
+ end
76
+
77
+ rate_limits.each do |category, limit|
78
+ if current_limit = @rate_limits[category]
79
+ if current_limit < limit
80
+ @rate_limits[category] = limit
81
+ end
82
+ else
83
+ @rate_limits[category] = limit
84
+ end
85
+ end
86
+ end
87
+
88
+ def parse_rate_limit_header(rate_limit_header)
89
+ time = Time.now
90
+
91
+ result = {}
92
+
93
+ limits = rate_limit_header.split(",")
94
+ limits.each do |limit|
95
+ next if limit.nil? || limit.empty?
96
+
97
+ begin
98
+ retry_after, categories = limit.strip.split(":").first(2)
99
+ retry_after = time + retry_after.to_i
100
+ categories = categories.split(";")
101
+
102
+ if categories.empty?
103
+ result[nil] = retry_after
104
+ else
105
+ categories.each do |category|
106
+ result[category] = retry_after
107
+ end
108
+ end
109
+ rescue StandardError
110
+ end
111
+ end
112
+
113
+ result
114
+ end
115
+
46
116
  def should_compress?(data)
47
117
  @transport_configuration.encoding == GZIP_ENCODING && data.bytesize >= GZIP_THRESHOLD
48
118
  end
@@ -50,7 +120,7 @@ module Sentry
50
120
  def set_conn
51
121
  server = @dsn.server
52
122
 
53
- configuration.logger.debug(LOGGER_PROGNAME) { "Sentry HTTP Transport connecting to #{server}" }
123
+ log_debug("Sentry HTTP Transport connecting to #{server}")
54
124
 
55
125
  Faraday.new(server, :ssl => ssl_configuration, :proxy => @transport_configuration.proxy) do |builder|
56
126
  @transport_configuration.faraday_builder&.call(builder)
@@ -0,0 +1,24 @@
1
+ module Sentry
2
+ module LoggingHelper
3
+ def log_error(message, exception, debug: false)
4
+ message = "#{message}: #{exception.message}"
5
+ message += "\n#{exception.backtrace.join("\n")}" if debug
6
+
7
+ logger.error(LOGGER_PROGNAME) do
8
+ message
9
+ end
10
+ end
11
+
12
+ def log_info(message)
13
+ logger.info(LOGGER_PROGNAME) { message }
14
+ end
15
+
16
+ def log_debug(message)
17
+ logger.debug(LOGGER_PROGNAME) { message }
18
+ end
19
+
20
+ def log_warn(message)
21
+ logger.warn(LOGGER_PROGNAME) { message }
22
+ end
23
+ end
24
+ end
@@ -1,3 +1,3 @@
1
1
  module Sentry
2
- VERSION = "4.3.1"
2
+ VERSION = "4.4.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sentry-ruby-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.3.1
4
+ version: 4.4.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: 2021-03-24 00:00:00.000000000 Z
11
+ date: 2021-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -83,6 +83,7 @@ files:
83
83
  - lib/sentry/interfaces/threads.rb
84
84
  - lib/sentry/linecache.rb
85
85
  - lib/sentry/logger.rb
86
+ - lib/sentry/net/http.rb
86
87
  - lib/sentry/rack.rb
87
88
  - lib/sentry/rack/capture_exceptions.rb
88
89
  - lib/sentry/rack/deprecations.rb
@@ -97,6 +98,7 @@ files:
97
98
  - lib/sentry/transport/http_transport.rb
98
99
  - lib/sentry/utils/argument_checking_helper.rb
99
100
  - lib/sentry/utils/exception_cause_chain.rb
101
+ - lib/sentry/utils/logging_helper.rb
100
102
  - lib/sentry/utils/real_ip.rb
101
103
  - lib/sentry/utils/request_id.rb
102
104
  - lib/sentry/version.rb
@@ -124,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
126
  - !ruby/object:Gem::Version
125
127
  version: '0'
126
128
  requirements: []
127
- rubygems_version: 3.0.3
129
+ rubygems_version: 3.0.3.1
128
130
  signing_key:
129
131
  specification_version: 4
130
132
  summary: A gem that provides a client interface for the Sentry error logger