sentry-ruby 5.16.1 → 5.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +6 -0
- data/README.md +20 -10
- data/Rakefile +3 -1
- data/bin/console +2 -0
- data/lib/sentry/attachment.rb +40 -0
- data/lib/sentry/background_worker.rb +1 -1
- data/lib/sentry/backpressure_monitor.rb +2 -32
- data/lib/sentry/backtrace.rb +10 -8
- data/lib/sentry/baggage.rb +7 -7
- data/lib/sentry/breadcrumb/sentry_logger.rb +6 -6
- data/lib/sentry/check_in_event.rb +5 -5
- data/lib/sentry/client.rb +61 -11
- data/lib/sentry/configuration.rb +77 -31
- data/lib/sentry/core_ext/object/deep_dup.rb +1 -1
- data/lib/sentry/cron/monitor_check_ins.rb +3 -1
- data/lib/sentry/cron/monitor_config.rb +1 -1
- data/lib/sentry/cron/monitor_schedule.rb +1 -1
- data/lib/sentry/dsn.rb +4 -4
- data/lib/sentry/envelope/item.rb +88 -0
- data/lib/sentry/envelope.rb +2 -68
- data/lib/sentry/error_event.rb +2 -2
- data/lib/sentry/event.rb +20 -18
- data/lib/sentry/faraday.rb +77 -0
- data/lib/sentry/graphql.rb +9 -0
- data/lib/sentry/hub.rb +23 -3
- data/lib/sentry/integrable.rb +4 -0
- data/lib/sentry/interface.rb +1 -0
- data/lib/sentry/interfaces/exception.rb +5 -3
- data/lib/sentry/interfaces/mechanism.rb +20 -0
- data/lib/sentry/interfaces/request.rb +7 -7
- data/lib/sentry/interfaces/single_exception.rb +9 -7
- data/lib/sentry/interfaces/stacktrace.rb +3 -1
- data/lib/sentry/interfaces/stacktrace_builder.rb +23 -2
- data/lib/sentry/logger.rb +1 -1
- data/lib/sentry/metrics/aggregator.rb +248 -0
- data/lib/sentry/metrics/configuration.rb +47 -0
- data/lib/sentry/metrics/counter_metric.rb +25 -0
- data/lib/sentry/metrics/distribution_metric.rb +25 -0
- data/lib/sentry/metrics/gauge_metric.rb +35 -0
- data/lib/sentry/metrics/local_aggregator.rb +53 -0
- data/lib/sentry/metrics/metric.rb +19 -0
- data/lib/sentry/metrics/set_metric.rb +28 -0
- data/lib/sentry/metrics/timing.rb +43 -0
- data/lib/sentry/metrics.rb +56 -0
- data/lib/sentry/net/http.rb +18 -39
- data/lib/sentry/profiler/helpers.rb +46 -0
- data/lib/sentry/profiler.rb +25 -56
- data/lib/sentry/propagation_context.rb +10 -9
- data/lib/sentry/puma.rb +1 -1
- data/lib/sentry/rack/capture_exceptions.rb +16 -4
- data/lib/sentry/rack.rb +2 -2
- data/lib/sentry/rake.rb +4 -2
- data/lib/sentry/redis.rb +2 -1
- data/lib/sentry/release_detector.rb +4 -4
- data/lib/sentry/scope.rb +36 -26
- data/lib/sentry/session.rb +2 -2
- data/lib/sentry/session_flusher.rb +7 -39
- data/lib/sentry/span.rb +46 -5
- data/lib/sentry/test_helper.rb +5 -2
- data/lib/sentry/threaded_periodic_worker.rb +39 -0
- data/lib/sentry/transaction.rb +19 -17
- data/lib/sentry/transaction_event.rb +6 -2
- data/lib/sentry/transport/configuration.rb +0 -1
- data/lib/sentry/transport/http_transport.rb +12 -12
- data/lib/sentry/transport.rb +18 -26
- data/lib/sentry/utils/argument_checking_helper.rb +6 -0
- data/lib/sentry/utils/env_helper.rb +21 -0
- data/lib/sentry/utils/http_tracing.rb +41 -0
- data/lib/sentry/utils/logging_helper.rb +0 -4
- data/lib/sentry/utils/real_ip.rb +2 -2
- data/lib/sentry/utils/request_id.rb +1 -1
- data/lib/sentry/vernier/output.rb +89 -0
- data/lib/sentry/vernier/profiler.rb +125 -0
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +38 -6
- data/sentry-ruby-core.gemspec +3 -1
- data/sentry-ruby.gemspec +15 -6
- metadata +44 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf62f77a0a968d4080fac612bf67f996bee72b51e050e17bf8d40c04c9c895ea
|
4
|
+
data.tar.gz: 348af55b8f56829cbf5fc5569ddc8308d4cd6ae508480de206443349e1221235
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5baaf6d507772d4a3882a99a43b3f4c88ae4ee56ddfd505433dc88b1e1f21430a2b8fa374932ec4b94478e054a9d1baf12789594bcfe9574db94f449b6526fc2
|
7
|
+
data.tar.gz: 8eacb9b0e326b529c743af650920b17e382b379032895d112a83689965a53fe42ae48eb9c070cd86085b1d7d5d9cc7300e0d9199b975edc25ee4aca1f093ecd6
|
data/Gemfile
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source "https://rubygems.org"
|
2
4
|
git_source(:github) { |name| "https://github.com/#{name}.git" }
|
3
5
|
|
@@ -14,6 +16,9 @@ gem "puma"
|
|
14
16
|
|
15
17
|
gem "timecop"
|
16
18
|
gem "stackprof" unless RUBY_PLATFORM == "java"
|
19
|
+
gem "vernier", platforms: :ruby if RUBY_VERSION >= "3.2.1"
|
20
|
+
|
21
|
+
gem "graphql", ">= 2.2.6" if RUBY_VERSION.to_f >= 2.7
|
17
22
|
|
18
23
|
gem "benchmark-ips"
|
19
24
|
gem "benchmark_driver"
|
@@ -22,5 +27,6 @@ gem "benchmark-memory"
|
|
22
27
|
|
23
28
|
gem "yard", github: "lsegal/yard"
|
24
29
|
gem "webrick"
|
30
|
+
gem "faraday"
|
25
31
|
|
26
32
|
eval_gemfile File.expand_path("../Gemfile", __dir__)
|
data/README.md
CHANGED
@@ -13,14 +13,14 @@ _Bad software is everywhere, and we're tired of it. Sentry is on a mission to he
|
|
13
13
|
Sentry SDK for Ruby
|
14
14
|
===========
|
15
15
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
| [](https://rubygems.org/gems/sentry-ruby) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_ruby_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://rubygems.org/gems/sentry-rails) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_rails_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://rubygems.org/gems/sentry-sidekiq) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_sidekiq_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://rubygems.org/gems/sentry-delayed_job) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_delayed_job_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://rubygems.org/gems/sentry-resque) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_resque_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://rubygems.org/gems/sentry-opentelemetry) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_opentelemetry_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://rubygems.org/gems/sentry-ruby) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_ruby_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://www.rubydoc.info/gems/sentry-ruby) |
|
19
|
+
| [](https://rubygems.org/gems/sentry-rails) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_rails_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://www.rubydoc.info/gems/sentry-rails) |
|
20
|
+
| [](https://rubygems.org/gems/sentry-sidekiq) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_sidekiq_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://www.rubydoc.info/gems/sentry-sidekiq) |
|
21
|
+
| [](https://rubygems.org/gems/sentry-delayed_job) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_delayed_job_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://www.rubydoc.info/gems/sentry-delayed_job) |
|
22
|
+
| [](https://rubygems.org/gems/sentry-resque) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_resque_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://www.rubydoc.info/gems/sentry-resque) |
|
23
|
+
| [](https://rubygems.org/gems/sentry-opentelemetry) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_opentelemetry_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://www.rubydoc.info/gems/sentry-opentelemetry) |
|
24
24
|
|
25
25
|
|
26
26
|
|
@@ -90,7 +90,7 @@ To learn more about sampling transactions, please visit the [official documentat
|
|
90
90
|
- [Sidekiq](https://docs.sentry.io/platforms/ruby/guides/sidekiq/)
|
91
91
|
- [DelayedJob](https://docs.sentry.io/platforms/ruby/guides/delayed_job/)
|
92
92
|
- [Resque](https://docs.sentry.io/platforms/ruby/guides/resque/)
|
93
|
-
- [
|
93
|
+
- [OpenTelemetry](https://docs.sentry.io/platforms/ruby/performance/instrumentation/opentelemetry/)
|
94
94
|
|
95
95
|
### Enriching Events
|
96
96
|
|
@@ -103,6 +103,16 @@ To learn more about sampling transactions, please visit the [official documentat
|
|
103
103
|
|
104
104
|
* [](https://docs.sentry.io/platforms/ruby/)
|
105
105
|
* [](https://forum.sentry.io/c/sdks)
|
106
|
-
* [](https://discord.gg/PXa5Apfe7K)
|
106
|
+
* [](https://discord.gg/PXa5Apfe7K)
|
107
107
|
* [](https://stackoverflow.com/questions/tagged/sentry)
|
108
108
|
* [](https://twitter.com/intent/follow?screen_name=getsentry)
|
109
|
+
|
110
|
+
## Contributing to the SDK
|
111
|
+
|
112
|
+
Please make sure to read the [CONTRIBUTING.md](https://github.com/getsentry/sentry-ruby/blob/master/CONTRIBUTING.md) before making a pull request.
|
113
|
+
|
114
|
+
Thanks to everyone who has contributed to this project so far.
|
115
|
+
|
116
|
+
<a href="https://github.com/getsentry/sentry-ruby/graphs/contributors">
|
117
|
+
<img src="https://contributors-img.web.app/image?repo=getsentry/sentry-ruby" />
|
118
|
+
</a>
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sentry
|
4
|
+
class Attachment
|
5
|
+
PathNotFoundError = Class.new(StandardError)
|
6
|
+
|
7
|
+
attr_reader :bytes, :filename, :path, :content_type
|
8
|
+
|
9
|
+
def initialize(bytes: nil, filename: nil, content_type: nil, path: nil)
|
10
|
+
@bytes = bytes
|
11
|
+
@filename = filename || infer_filename(path)
|
12
|
+
@path = path
|
13
|
+
@content_type = content_type
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_envelope_headers
|
17
|
+
{ type: "attachment", filename: filename, content_type: content_type, length: payload.bytesize }
|
18
|
+
end
|
19
|
+
|
20
|
+
def payload
|
21
|
+
@payload ||= if bytes
|
22
|
+
bytes
|
23
|
+
else
|
24
|
+
File.binread(path)
|
25
|
+
end
|
26
|
+
rescue Errno::ENOENT
|
27
|
+
raise PathNotFoundError, "Failed to read attachment file, file not found: #{path}"
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def infer_filename(path)
|
33
|
+
if path
|
34
|
+
File.basename(path)
|
35
|
+
else
|
36
|
+
raise ArgumentError, "filename or path is required"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -31,7 +31,7 @@ module Sentry
|
|
31
31
|
log_debug("config.background_worker_threads is set to 0, all events will be sent synchronously")
|
32
32
|
Concurrent::ImmediateExecutor.new
|
33
33
|
else
|
34
|
-
log_debug("Initializing the background worker with #{@number_of_threads} threads")
|
34
|
+
log_debug("Initializing the Sentry background worker with #{@number_of_threads} threads")
|
35
35
|
|
36
36
|
executor = Concurrent::ThreadPoolExecutor.new(
|
37
37
|
min_threads: 0,
|
@@ -1,19 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Sentry
|
4
|
-
class BackpressureMonitor
|
5
|
-
include LoggingHelper
|
6
|
-
|
4
|
+
class BackpressureMonitor < ThreadedPeriodicWorker
|
7
5
|
DEFAULT_INTERVAL = 10
|
8
6
|
MAX_DOWNSAMPLE_FACTOR = 10
|
9
7
|
|
10
8
|
def initialize(configuration, client, interval: DEFAULT_INTERVAL)
|
11
|
-
|
9
|
+
super(configuration.logger, interval)
|
12
10
|
@client = client
|
13
|
-
@logger = configuration.logger
|
14
|
-
|
15
|
-
@thread = nil
|
16
|
-
@exited = false
|
17
11
|
|
18
12
|
@healthy = true
|
19
13
|
@downsample_factor = 0
|
@@ -47,29 +41,5 @@ module Sentry
|
|
47
41
|
log_debug("[BackpressureMonitor] health check negative, downsampling with a factor of #{@downsample_factor}")
|
48
42
|
end
|
49
43
|
end
|
50
|
-
|
51
|
-
def kill
|
52
|
-
log_debug("[BackpressureMonitor] killing monitor")
|
53
|
-
|
54
|
-
@exited = true
|
55
|
-
@thread&.kill
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
def ensure_thread
|
61
|
-
return if @exited
|
62
|
-
return if @thread&.alive?
|
63
|
-
|
64
|
-
@thread = Thread.new do
|
65
|
-
loop do
|
66
|
-
sleep(@interval)
|
67
|
-
run
|
68
|
-
end
|
69
|
-
end
|
70
|
-
rescue ThreadError
|
71
|
-
log_debug("[BackpressureMonitor] Thread creation failed")
|
72
|
-
@exited = true
|
73
|
-
end
|
74
44
|
end
|
75
45
|
end
|
data/lib/sentry/backtrace.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "rubygems"
|
4
|
+
|
3
5
|
module Sentry
|
4
6
|
# @api private
|
5
7
|
class Backtrace
|
@@ -10,11 +12,11 @@ module Sentry
|
|
10
12
|
RUBY_INPUT_FORMAT = /
|
11
13
|
^ \s* (?: [a-zA-Z]: | uri:classloader: )? ([^:]+ | <.*>):
|
12
14
|
(\d+)
|
13
|
-
(?: :in
|
14
|
-
/x
|
15
|
+
(?: :in\s('|`)([^']+)')?$
|
16
|
+
/x
|
15
17
|
|
16
18
|
# org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
|
17
|
-
JAVA_INPUT_FORMAT = /^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)
|
19
|
+
JAVA_INPUT_FORMAT = /^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)$/
|
18
20
|
|
19
21
|
# The file portion of the line (such as app/models/user.rb)
|
20
22
|
attr_reader :file
|
@@ -33,10 +35,10 @@ module Sentry
|
|
33
35
|
# Parses a single line of a given backtrace
|
34
36
|
# @param [String] unparsed_line The raw line from +caller+ or some backtrace
|
35
37
|
# @return [Line] The parsed backtrace line
|
36
|
-
def self.parse(unparsed_line, in_app_pattern)
|
38
|
+
def self.parse(unparsed_line, in_app_pattern = nil)
|
37
39
|
ruby_match = unparsed_line.match(RUBY_INPUT_FORMAT)
|
38
40
|
if ruby_match
|
39
|
-
_, file, number, method = ruby_match.to_a
|
41
|
+
_, file, number, _, method = ruby_match.to_a
|
40
42
|
file.sub!(/\.class$/, RB_EXTENSION)
|
41
43
|
module_name = nil
|
42
44
|
else
|
@@ -55,6 +57,8 @@ module Sentry
|
|
55
57
|
end
|
56
58
|
|
57
59
|
def in_app
|
60
|
+
return false unless in_app_pattern
|
61
|
+
|
58
62
|
if file =~ in_app_pattern
|
59
63
|
true
|
60
64
|
else
|
@@ -76,8 +80,6 @@ module Sentry
|
|
76
80
|
end
|
77
81
|
end
|
78
82
|
|
79
|
-
APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test|spec)/.freeze
|
80
|
-
|
81
83
|
# holder for an Array of Backtrace::Line instances
|
82
84
|
attr_reader :lines
|
83
85
|
|
@@ -87,7 +89,7 @@ module Sentry
|
|
87
89
|
ruby_lines = backtrace_cleanup_callback.call(ruby_lines) if backtrace_cleanup_callback
|
88
90
|
|
89
91
|
in_app_pattern ||= begin
|
90
|
-
Regexp.new("^(#{project_root}/)?#{app_dirs_pattern
|
92
|
+
Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}")
|
91
93
|
end
|
92
94
|
|
93
95
|
lines = ruby_lines.to_a.map do |unparsed_line|
|
data/lib/sentry/baggage.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "cgi"
|
4
4
|
|
5
5
|
module Sentry
|
6
6
|
# A {https://www.w3.org/TR/baggage W3C Baggage Header} implementation.
|
7
7
|
class Baggage
|
8
|
-
SENTRY_PREFIX =
|
9
|
-
SENTRY_PREFIX_REGEX = /^sentry
|
8
|
+
SENTRY_PREFIX = "sentry-"
|
9
|
+
SENTRY_PREFIX_REGEX = /^sentry-/
|
10
10
|
|
11
11
|
# @return [Hash]
|
12
12
|
attr_reader :items
|
@@ -30,14 +30,14 @@ module Sentry
|
|
30
30
|
items = {}
|
31
31
|
mutable = true
|
32
32
|
|
33
|
-
header.split(
|
33
|
+
header.split(",").each do |item|
|
34
34
|
item = item.strip
|
35
|
-
key, val = item.split(
|
35
|
+
key, val = item.split("=")
|
36
36
|
|
37
37
|
next unless key && val
|
38
38
|
next unless key =~ SENTRY_PREFIX_REGEX
|
39
39
|
|
40
|
-
baggage_key = key.split(
|
40
|
+
baggage_key = key.split("-")[1]
|
41
41
|
next unless baggage_key
|
42
42
|
|
43
43
|
items[CGI.unescape(baggage_key)] = CGI.unescape(val)
|
@@ -64,7 +64,7 @@ module Sentry
|
|
64
64
|
# @return [String]
|
65
65
|
def serialize
|
66
66
|
items = @items.map { |k, v| "#{SENTRY_PREFIX}#{CGI.escape(k)}=#{CGI.escape(v)}" }
|
67
|
-
items.join(
|
67
|
+
items.join(",")
|
68
68
|
end
|
69
69
|
end
|
70
70
|
end
|
@@ -1,16 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "logger"
|
4
4
|
|
5
5
|
module Sentry
|
6
6
|
class Breadcrumb
|
7
7
|
module SentryLogger
|
8
8
|
LEVELS = {
|
9
|
-
::Logger::DEBUG =>
|
10
|
-
::Logger::INFO =>
|
11
|
-
::Logger::WARN =>
|
12
|
-
::Logger::ERROR =>
|
13
|
-
::Logger::FATAL =>
|
9
|
+
::Logger::DEBUG => "debug",
|
10
|
+
::Logger::INFO => "info",
|
11
|
+
::Logger::WARN => "warn",
|
12
|
+
::Logger::ERROR => "error",
|
13
|
+
::Logger::FATAL => "fatal"
|
14
14
|
}.freeze
|
15
15
|
|
16
16
|
def add(*args, &block)
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "securerandom"
|
4
|
+
require "sentry/cron/monitor_config"
|
5
5
|
|
6
6
|
module Sentry
|
7
7
|
class CheckInEvent < Event
|
8
|
-
TYPE =
|
8
|
+
TYPE = "check_in"
|
9
9
|
|
10
10
|
# uuid to identify this check-in.
|
11
11
|
# @return [String]
|
@@ -27,7 +27,7 @@ module Sentry
|
|
27
27
|
# @return [Symbol]
|
28
28
|
attr_accessor :status
|
29
29
|
|
30
|
-
VALID_STATUSES = %i
|
30
|
+
VALID_STATUSES = %i[ok in_progress error]
|
31
31
|
|
32
32
|
def initialize(
|
33
33
|
slug:,
|
@@ -43,7 +43,7 @@ module Sentry
|
|
43
43
|
self.status = status
|
44
44
|
self.duration = duration
|
45
45
|
self.monitor_config = monitor_config
|
46
|
-
self.check_in_id = check_in_id || SecureRandom.uuid.delete(
|
46
|
+
self.check_in_id = check_in_id || SecureRandom.uuid.delete("-")
|
47
47
|
end
|
48
48
|
|
49
49
|
# @return [Hash]
|
data/lib/sentry/client.rb
CHANGED
@@ -30,7 +30,7 @@ module Sentry
|
|
30
30
|
else
|
31
31
|
@transport =
|
32
32
|
case configuration.dsn&.scheme
|
33
|
-
when
|
33
|
+
when "http", "https"
|
34
34
|
HTTPTransport.new(configuration)
|
35
35
|
else
|
36
36
|
DummyTransport.new(configuration)
|
@@ -49,24 +49,35 @@ module Sentry
|
|
49
49
|
return unless configuration.sending_allowed?
|
50
50
|
|
51
51
|
if event.is_a?(ErrorEvent) && !configuration.sample_allowed?
|
52
|
-
transport.record_lost_event(:sample_rate,
|
52
|
+
transport.record_lost_event(:sample_rate, "error")
|
53
53
|
return
|
54
54
|
end
|
55
55
|
|
56
56
|
event_type = event.is_a?(Event) ? event.type : event["type"]
|
57
|
+
data_category = Envelope::Item.data_category(event_type)
|
58
|
+
|
59
|
+
is_transaction = event.is_a?(TransactionEvent)
|
60
|
+
spans_before = is_transaction ? event.spans.size : 0
|
61
|
+
|
57
62
|
event = scope.apply_to_event(event, hint)
|
58
63
|
|
59
64
|
if event.nil?
|
60
65
|
log_debug("Discarded event because one of the event processors returned nil")
|
61
|
-
transport.record_lost_event(:event_processor,
|
66
|
+
transport.record_lost_event(:event_processor, data_category)
|
67
|
+
transport.record_lost_event(:event_processor, "span", num: spans_before + 1) if is_transaction
|
62
68
|
return
|
69
|
+
elsif is_transaction
|
70
|
+
spans_delta = spans_before - event.spans.size
|
71
|
+
transport.record_lost_event(:event_processor, "span", num: spans_delta) if spans_delta > 0
|
63
72
|
end
|
64
73
|
|
65
74
|
if async_block = configuration.async
|
66
75
|
dispatch_async_event(async_block, event, hint)
|
67
76
|
elsif configuration.background_worker_threads != 0 && hint.fetch(:background, true)
|
68
|
-
|
69
|
-
|
77
|
+
unless dispatch_background_event(event, hint)
|
78
|
+
transport.record_lost_event(:queue_overflow, data_category)
|
79
|
+
transport.record_lost_event(:queue_overflow, "span", num: spans_before + 1) if is_transaction
|
80
|
+
end
|
70
81
|
else
|
71
82
|
send_event(event, hint)
|
72
83
|
end
|
@@ -77,6 +88,20 @@ module Sentry
|
|
77
88
|
nil
|
78
89
|
end
|
79
90
|
|
91
|
+
# Capture an envelope directly.
|
92
|
+
# @param envelope [Envelope] the envelope to be captured.
|
93
|
+
# @return [void]
|
94
|
+
def capture_envelope(envelope)
|
95
|
+
Sentry.background_worker.perform { send_envelope(envelope) }
|
96
|
+
end
|
97
|
+
|
98
|
+
# Flush pending events to Sentry.
|
99
|
+
# @return [void]
|
100
|
+
def flush
|
101
|
+
transport.flush if configuration.sending_to_dsn_allowed?
|
102
|
+
spotlight_transport.flush if spotlight_transport
|
103
|
+
end
|
104
|
+
|
80
105
|
# Initializes an Event object with the given exception. Returns `nil` if the exception's class is excluded from reporting.
|
81
106
|
# @param exception [Exception] the exception to be reported.
|
82
107
|
# @param hint [Hash] the hint data that'll be passed to `before_send` callback and the scope's event processors.
|
@@ -88,9 +113,10 @@ module Sentry
|
|
88
113
|
return if !ignore_exclusions && !@configuration.exception_class_allowed?(exception)
|
89
114
|
|
90
115
|
integration_meta = Sentry.integrations[hint[:integration]]
|
116
|
+
mechanism = hint.delete(:mechanism) { Mechanism.new }
|
91
117
|
|
92
118
|
ErrorEvent.new(configuration: configuration, integration_meta: integration_meta).tap do |event|
|
93
|
-
event.add_exception_interface(exception)
|
119
|
+
event.add_exception_interface(exception, mechanism: mechanism)
|
94
120
|
event.add_threads_interface(crashed: true)
|
95
121
|
event.level = :error
|
96
122
|
end
|
@@ -151,13 +177,15 @@ module Sentry
|
|
151
177
|
# @!macro send_event
|
152
178
|
def send_event(event, hint = nil)
|
153
179
|
event_type = event.is_a?(Event) ? event.type : event["type"]
|
180
|
+
data_category = Envelope::Item.data_category(event_type)
|
181
|
+
spans_before = event.is_a?(TransactionEvent) ? event.spans.size : 0
|
154
182
|
|
155
183
|
if event_type != TransactionEvent::TYPE && configuration.before_send
|
156
184
|
event = configuration.before_send.call(event, hint)
|
157
185
|
|
158
186
|
if event.nil?
|
159
187
|
log_debug("Discarded event because before_send returned nil")
|
160
|
-
transport.record_lost_event(:before_send,
|
188
|
+
transport.record_lost_event(:before_send, data_category)
|
161
189
|
return
|
162
190
|
end
|
163
191
|
end
|
@@ -167,18 +195,40 @@ module Sentry
|
|
167
195
|
|
168
196
|
if event.nil?
|
169
197
|
log_debug("Discarded event because before_send_transaction returned nil")
|
170
|
-
transport.record_lost_event(:before_send,
|
198
|
+
transport.record_lost_event(:before_send, "transaction")
|
199
|
+
transport.record_lost_event(:before_send, "span", num: spans_before + 1)
|
171
200
|
return
|
201
|
+
else
|
202
|
+
spans_after = event.is_a?(TransactionEvent) ? event.spans.size : 0
|
203
|
+
spans_delta = spans_before - spans_after
|
204
|
+
transport.record_lost_event(:before_send, "span", num: spans_delta) if spans_delta > 0
|
172
205
|
end
|
173
206
|
end
|
174
207
|
|
175
|
-
transport.send_event(event)
|
176
|
-
spotlight_transport
|
208
|
+
transport.send_event(event) if configuration.sending_to_dsn_allowed?
|
209
|
+
spotlight_transport.send_event(event) if spotlight_transport
|
177
210
|
|
178
211
|
event
|
179
212
|
rescue => e
|
180
213
|
log_error("Event sending failed", e, debug: configuration.debug)
|
181
|
-
transport.record_lost_event(:network_error,
|
214
|
+
transport.record_lost_event(:network_error, data_category)
|
215
|
+
transport.record_lost_event(:network_error, "span", num: spans_before + 1) if event.is_a?(TransactionEvent)
|
216
|
+
raise
|
217
|
+
end
|
218
|
+
|
219
|
+
# Send an envelope directly to Sentry.
|
220
|
+
# @param envelope [Envelope] the envelope to be sent.
|
221
|
+
# @return [void]
|
222
|
+
def send_envelope(envelope)
|
223
|
+
transport.send_envelope(envelope) if configuration.sending_to_dsn_allowed?
|
224
|
+
spotlight_transport.send_envelope(envelope) if spotlight_transport
|
225
|
+
rescue => e
|
226
|
+
log_error("Envelope sending failed", e, debug: configuration.debug)
|
227
|
+
|
228
|
+
envelope.items.map(&:data_category).each do |data_category|
|
229
|
+
transport.record_lost_event(:network_error, data_category)
|
230
|
+
end
|
231
|
+
|
182
232
|
raise
|
183
233
|
end
|
184
234
|
|