sentry-ruby 5.26.0 → 6.1.1
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 +2 -4
- data/README.md +1 -1
- data/lib/sentry/background_worker.rb +1 -4
- data/lib/sentry/backtrace/line.rb +99 -0
- data/lib/sentry/backtrace.rb +44 -76
- data/lib/sentry/breadcrumb.rb +1 -1
- data/lib/sentry/breadcrumb_buffer.rb +2 -2
- data/lib/sentry/check_in_event.rb +2 -2
- data/lib/sentry/client.rb +39 -89
- data/lib/sentry/configuration.rb +125 -78
- data/lib/sentry/cron/monitor_check_ins.rb +3 -3
- data/lib/sentry/cron/monitor_config.rb +2 -2
- data/lib/sentry/cron/monitor_schedule.rb +2 -2
- data/lib/sentry/debug_structured_logger.rb +94 -0
- data/lib/sentry/dsn.rb +32 -0
- data/lib/sentry/envelope/item.rb +1 -2
- data/lib/sentry/error_event.rb +3 -3
- data/lib/sentry/event.rb +4 -10
- data/lib/sentry/graphql.rb +1 -1
- data/lib/sentry/hub.rb +6 -5
- data/lib/sentry/interface.rb +1 -1
- data/lib/sentry/interfaces/exception.rb +2 -2
- data/lib/sentry/interfaces/request.rb +2 -0
- data/lib/sentry/interfaces/single_exception.rb +3 -3
- data/lib/sentry/interfaces/stacktrace.rb +3 -3
- data/lib/sentry/interfaces/stacktrace_builder.rb +0 -8
- data/lib/sentry/interfaces/threads.rb +2 -2
- data/lib/sentry/log_event.rb +19 -6
- data/lib/sentry/profiler.rb +4 -5
- data/lib/sentry/propagation_context.rb +55 -18
- data/lib/sentry/rspec.rb +1 -1
- data/lib/sentry/span.rb +2 -17
- data/lib/sentry/std_lib_logger.rb +6 -1
- data/lib/sentry/test_helper.rb +23 -0
- data/lib/sentry/transaction.rb +72 -95
- data/lib/sentry/transaction_event.rb +4 -9
- data/lib/sentry/transport/debug_transport.rb +70 -0
- data/lib/sentry/transport/dummy_transport.rb +1 -0
- data/lib/sentry/transport/http_transport.rb +9 -5
- data/lib/sentry/transport.rb +3 -5
- data/lib/sentry/utils/encoding_helper.rb +7 -0
- data/lib/sentry/utils/logging_helper.rb +8 -6
- data/lib/sentry/utils/sample_rand.rb +97 -0
- data/lib/sentry/vernier/profiler.rb +4 -3
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +6 -30
- data/sentry-ruby-core.gemspec +1 -1
- data/sentry-ruby.gemspec +1 -1
- metadata +12 -18
- data/lib/sentry/metrics/aggregator.rb +0 -248
- data/lib/sentry/metrics/configuration.rb +0 -47
- data/lib/sentry/metrics/counter_metric.rb +0 -25
- data/lib/sentry/metrics/distribution_metric.rb +0 -25
- data/lib/sentry/metrics/gauge_metric.rb +0 -35
- data/lib/sentry/metrics/local_aggregator.rb +0 -53
- data/lib/sentry/metrics/metric.rb +0 -19
- data/lib/sentry/metrics/set_metric.rb +0 -28
- data/lib/sentry/metrics/timing.rb +0 -51
- data/lib/sentry/metrics.rb +0 -56
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0c7e991a71c48c638739ac8ce5800da3796ea8847cf2957eee2a44b6b04233fc
|
|
4
|
+
data.tar.gz: 4a1981f39e3dac807e4c14fb50372467a46bf3f01331d0c6d61c3b27cc46e26c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 39f12421ae5bc3fbbd0899f595cd7a614fdf613f68f2bf1b265640dd8d874dc387c68a959b6c16fdc6255000886fa1cdbd88279835d0c9a0ea5566b40cc03e16
|
|
7
|
+
data.tar.gz: 6020209a29b8ba823c5da7035e8a634e5355d839f77fc4d4232d3633aeadf3d88f46aba492456ec281984cbd12ec0d2948b8a8c0baca880a89799840e1ed97b3
|
data/Gemfile
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
source "https://rubygems.org"
|
|
4
4
|
git_source(:github) { |name| "https://github.com/#{name}.git" }
|
|
5
5
|
|
|
6
|
-
eval_gemfile "../Gemfile"
|
|
6
|
+
eval_gemfile "../Gemfile.dev"
|
|
7
7
|
|
|
8
8
|
gem "sentry-ruby", path: "./"
|
|
9
9
|
|
|
@@ -11,8 +11,6 @@ rack_version = ENV["RACK_VERSION"]
|
|
|
11
11
|
rack_version = "3.0.0" if rack_version.nil?
|
|
12
12
|
gem "rack", "~> #{Gem::Version.new(rack_version)}" unless rack_version == "0"
|
|
13
13
|
|
|
14
|
-
gem "ostruct" if RUBY_VERSION >= "3.4"
|
|
15
|
-
|
|
16
14
|
redis_rb_version = ENV.fetch("REDIS_RB_VERSION", "5.0")
|
|
17
15
|
gem "redis", "~> #{redis_rb_version}"
|
|
18
16
|
|
|
@@ -22,7 +20,7 @@ gem "timecop"
|
|
|
22
20
|
gem "stackprof" unless RUBY_PLATFORM == "java"
|
|
23
21
|
gem "vernier", platforms: :ruby if RUBY_VERSION >= "3.2.1"
|
|
24
22
|
|
|
25
|
-
gem "graphql", ">= 2.2.6"
|
|
23
|
+
gem "graphql", ">= 2.2.6"
|
|
26
24
|
|
|
27
25
|
gem "benchmark-ips"
|
|
28
26
|
gem "benchmark_driver"
|
data/README.md
CHANGED
|
@@ -107,7 +107,7 @@ To learn more about sampling transactions, please visit the [official documentat
|
|
|
107
107
|
* [](https://forum.sentry.io/c/sdks)
|
|
108
108
|
* [](https://discord.gg/PXa5Apfe7K)
|
|
109
109
|
* [](https://stackoverflow.com/questions/tagged/sentry)
|
|
110
|
-
* [](https://x.com/intent/follow?screen_name=sentry)
|
|
111
111
|
|
|
112
112
|
## Contributing to the SDK
|
|
113
113
|
|
|
@@ -23,10 +23,7 @@ module Sentry
|
|
|
23
23
|
@shutdown_callback = nil
|
|
24
24
|
|
|
25
25
|
@executor =
|
|
26
|
-
if
|
|
27
|
-
log_debug("config.async is set, BackgroundWorker is disabled")
|
|
28
|
-
Concurrent::ImmediateExecutor.new
|
|
29
|
-
elsif @number_of_threads == 0
|
|
26
|
+
if @number_of_threads == 0
|
|
30
27
|
log_debug("config.background_worker_threads is set to 0, all events will be sent synchronously")
|
|
31
28
|
Concurrent::ImmediateExecutor.new
|
|
32
29
|
else
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sentry
|
|
4
|
+
# @api private
|
|
5
|
+
class Backtrace
|
|
6
|
+
# Handles backtrace parsing line by line
|
|
7
|
+
class Line
|
|
8
|
+
RB_EXTENSION = ".rb"
|
|
9
|
+
# regexp (optional leading X: on windows, or JRuby9000 class-prefix)
|
|
10
|
+
RUBY_INPUT_FORMAT = /
|
|
11
|
+
^ \s* (?: [a-zA-Z]: | uri:classloader: )? ([^:]+ | <.*>):
|
|
12
|
+
(\d+)
|
|
13
|
+
(?: :in\s('|`)(?:([\w:]+)\#)?([^']+)')?$
|
|
14
|
+
/x
|
|
15
|
+
|
|
16
|
+
# org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
|
|
17
|
+
JAVA_INPUT_FORMAT = /^([\w$.]+)\.([\w$]+)\(([\w$.]+):(\d+)\)$/
|
|
18
|
+
|
|
19
|
+
# The file portion of the line (such as app/models/user.rb)
|
|
20
|
+
attr_reader :file
|
|
21
|
+
|
|
22
|
+
# The line number portion of the line
|
|
23
|
+
attr_reader :number
|
|
24
|
+
|
|
25
|
+
# The method of the line (such as index)
|
|
26
|
+
attr_reader :method
|
|
27
|
+
|
|
28
|
+
# The module name (JRuby)
|
|
29
|
+
attr_reader :module_name
|
|
30
|
+
|
|
31
|
+
attr_reader :in_app_pattern
|
|
32
|
+
|
|
33
|
+
# Parses a single line of a given backtrace
|
|
34
|
+
# @param [String] unparsed_line The raw line from +caller+ or some backtrace
|
|
35
|
+
# @return [Line] The parsed backtrace line
|
|
36
|
+
def self.parse(unparsed_line, in_app_pattern = nil)
|
|
37
|
+
ruby_match = unparsed_line.match(RUBY_INPUT_FORMAT)
|
|
38
|
+
|
|
39
|
+
if ruby_match
|
|
40
|
+
_, file, number, _, module_name, method = ruby_match.to_a
|
|
41
|
+
file.sub!(/\.class$/, RB_EXTENSION)
|
|
42
|
+
module_name = module_name
|
|
43
|
+
else
|
|
44
|
+
java_match = unparsed_line.match(JAVA_INPUT_FORMAT)
|
|
45
|
+
_, module_name, method, file, number = java_match.to_a
|
|
46
|
+
end
|
|
47
|
+
new(file, number, method, module_name, in_app_pattern)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Creates a Line from a Thread::Backtrace::Location object
|
|
51
|
+
# This is more efficient than converting to string and parsing with regex
|
|
52
|
+
# @param [Thread::Backtrace::Location] location The location object
|
|
53
|
+
# @param [Regexp, nil] in_app_pattern Optional pattern to determine if the line is in-app
|
|
54
|
+
# @return [Line] The backtrace line
|
|
55
|
+
def self.from_source_location(location, in_app_pattern = nil)
|
|
56
|
+
file = location.absolute_path
|
|
57
|
+
number = location.lineno
|
|
58
|
+
method = location.base_label
|
|
59
|
+
|
|
60
|
+
label = location.label
|
|
61
|
+
index = label.index("#") || label.index(".")
|
|
62
|
+
module_name = label[0, index] if index
|
|
63
|
+
|
|
64
|
+
new(file, number, method, module_name, in_app_pattern)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def initialize(file, number, method, module_name, in_app_pattern)
|
|
68
|
+
@file = file
|
|
69
|
+
@module_name = module_name
|
|
70
|
+
@number = number.to_i
|
|
71
|
+
@method = method
|
|
72
|
+
@in_app_pattern = in_app_pattern
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def in_app
|
|
76
|
+
return false unless in_app_pattern
|
|
77
|
+
|
|
78
|
+
if file =~ in_app_pattern
|
|
79
|
+
true
|
|
80
|
+
else
|
|
81
|
+
false
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Reconstructs the line in a readable fashion
|
|
86
|
+
def to_s
|
|
87
|
+
"#{file}:#{number}:in `#{method}'"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def ==(other)
|
|
91
|
+
to_s == other.to_s
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def inspect
|
|
95
|
+
"<Line:#{self}>"
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
data/lib/sentry/backtrace.rb
CHANGED
|
@@ -1,86 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "rubygems"
|
|
4
|
+
require "concurrent/map"
|
|
5
|
+
require "sentry/backtrace/line"
|
|
4
6
|
|
|
5
7
|
module Sentry
|
|
6
8
|
# @api private
|
|
7
9
|
class Backtrace
|
|
8
|
-
# Handles backtrace parsing line by line
|
|
9
|
-
class Line
|
|
10
|
-
RB_EXTENSION = ".rb"
|
|
11
|
-
# regexp (optional leading X: on windows, or JRuby9000 class-prefix)
|
|
12
|
-
RUBY_INPUT_FORMAT = /
|
|
13
|
-
^ \s* (?: [a-zA-Z]: | uri:classloader: )? ([^:]+ | <.*>):
|
|
14
|
-
(\d+)
|
|
15
|
-
(?: :in\s('|`)(?:([\w:]+)\#)?([^']+)')?$
|
|
16
|
-
/x
|
|
17
|
-
|
|
18
|
-
# org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
|
|
19
|
-
JAVA_INPUT_FORMAT = /^([\w$.]+)\.([\w$]+)\(([\w$.]+):(\d+)\)$/
|
|
20
|
-
|
|
21
|
-
# The file portion of the line (such as app/models/user.rb)
|
|
22
|
-
attr_reader :file
|
|
23
|
-
|
|
24
|
-
# The line number portion of the line
|
|
25
|
-
attr_reader :number
|
|
26
|
-
|
|
27
|
-
# The method of the line (such as index)
|
|
28
|
-
attr_reader :method
|
|
29
|
-
|
|
30
|
-
# The module name (JRuby)
|
|
31
|
-
attr_reader :module_name
|
|
32
|
-
|
|
33
|
-
attr_reader :in_app_pattern
|
|
34
|
-
|
|
35
|
-
# Parses a single line of a given backtrace
|
|
36
|
-
# @param [String] unparsed_line The raw line from +caller+ or some backtrace
|
|
37
|
-
# @return [Line] The parsed backtrace line
|
|
38
|
-
def self.parse(unparsed_line, in_app_pattern = nil)
|
|
39
|
-
ruby_match = unparsed_line.match(RUBY_INPUT_FORMAT)
|
|
40
|
-
|
|
41
|
-
if ruby_match
|
|
42
|
-
_, file, number, _, module_name, method = ruby_match.to_a
|
|
43
|
-
file.sub!(/\.class$/, RB_EXTENSION)
|
|
44
|
-
module_name = module_name
|
|
45
|
-
else
|
|
46
|
-
java_match = unparsed_line.match(JAVA_INPUT_FORMAT)
|
|
47
|
-
_, module_name, method, file, number = java_match.to_a
|
|
48
|
-
end
|
|
49
|
-
new(file, number, method, module_name, in_app_pattern)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def initialize(file, number, method, module_name, in_app_pattern)
|
|
53
|
-
@file = file
|
|
54
|
-
@module_name = module_name
|
|
55
|
-
@number = number.to_i
|
|
56
|
-
@method = method
|
|
57
|
-
@in_app_pattern = in_app_pattern
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def in_app
|
|
61
|
-
return false unless in_app_pattern
|
|
62
|
-
|
|
63
|
-
if file =~ in_app_pattern
|
|
64
|
-
true
|
|
65
|
-
else
|
|
66
|
-
false
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
# Reconstructs the line in a readable fashion
|
|
71
|
-
def to_s
|
|
72
|
-
"#{file}:#{number}:in `#{method}'"
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def ==(other)
|
|
76
|
-
to_s == other.to_s
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def inspect
|
|
80
|
-
"<Line:#{self}>"
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
|
|
84
10
|
# holder for an Array of Backtrace::Line instances
|
|
85
11
|
attr_reader :lines
|
|
86
12
|
|
|
@@ -100,6 +26,48 @@ module Sentry
|
|
|
100
26
|
new(lines)
|
|
101
27
|
end
|
|
102
28
|
|
|
29
|
+
# Thread.each_caller_location is an API added in Ruby 3.2 that doesn't always collect
|
|
30
|
+
# the entire stack like Kernel#caller or #caller_locations do.
|
|
31
|
+
#
|
|
32
|
+
# @see https://github.com/rails/rails/pull/49095 for more context.
|
|
33
|
+
if Thread.respond_to?(:each_caller_location)
|
|
34
|
+
def self.source_location(&backtrace_cleaner)
|
|
35
|
+
Thread.each_caller_location do |location|
|
|
36
|
+
frame_key = [location.absolute_path, location.lineno]
|
|
37
|
+
cached_value = line_cache[frame_key]
|
|
38
|
+
|
|
39
|
+
next if cached_value == :skip
|
|
40
|
+
|
|
41
|
+
if cached_value
|
|
42
|
+
return cached_value
|
|
43
|
+
else
|
|
44
|
+
if cleaned_frame = backtrace_cleaner.(location)
|
|
45
|
+
line = Line.from_source_location(location)
|
|
46
|
+
line_cache[frame_key] = line
|
|
47
|
+
|
|
48
|
+
return line
|
|
49
|
+
else
|
|
50
|
+
line_cache[frame_key] = :skip
|
|
51
|
+
|
|
52
|
+
next
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.line_cache
|
|
59
|
+
@line_cache ||= Concurrent::Map.new
|
|
60
|
+
end
|
|
61
|
+
else
|
|
62
|
+
# Since Sentry is mostly used in production, we don't want to fallback
|
|
63
|
+
# to the slower implementation and adds potentially big overhead to the
|
|
64
|
+
# application.
|
|
65
|
+
def self.source_location(*)
|
|
66
|
+
nil
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
|
|
103
71
|
def initialize(lines)
|
|
104
72
|
@lines = lines
|
|
105
73
|
end
|
data/lib/sentry/breadcrumb.rb
CHANGED
|
@@ -48,13 +48,13 @@ module Sentry
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
# @return [Hash]
|
|
51
|
-
def
|
|
51
|
+
def to_h
|
|
52
52
|
data = super
|
|
53
53
|
data[:check_in_id] = check_in_id
|
|
54
54
|
data[:monitor_slug] = monitor_slug
|
|
55
55
|
data[:status] = status
|
|
56
56
|
data[:duration] = duration if duration
|
|
57
|
-
data[:monitor_config] = monitor_config.
|
|
57
|
+
data[:monitor_config] = monitor_config.to_h if monitor_config
|
|
58
58
|
data
|
|
59
59
|
end
|
|
60
60
|
end
|
data/lib/sentry/client.rb
CHANGED
|
@@ -4,6 +4,7 @@ require "sentry/transport"
|
|
|
4
4
|
require "sentry/log_event"
|
|
5
5
|
require "sentry/log_event_buffer"
|
|
6
6
|
require "sentry/utils/uuid"
|
|
7
|
+
require "sentry/utils/encoding_helper"
|
|
7
8
|
|
|
8
9
|
module Sentry
|
|
9
10
|
class Client
|
|
@@ -60,8 +61,7 @@ module Sentry
|
|
|
60
61
|
return
|
|
61
62
|
end
|
|
62
63
|
|
|
63
|
-
|
|
64
|
-
data_category = Envelope::Item.data_category(event_type)
|
|
64
|
+
data_category = Envelope::Item.data_category(event.type)
|
|
65
65
|
|
|
66
66
|
is_transaction = event.is_a?(TransactionEvent)
|
|
67
67
|
spans_before = is_transaction ? event.spans.size : 0
|
|
@@ -78,9 +78,7 @@ module Sentry
|
|
|
78
78
|
transport.record_lost_event(:event_processor, "span", num: spans_delta) if spans_delta > 0
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
-
if
|
|
82
|
-
dispatch_async_event(async_block, event, hint)
|
|
83
|
-
elsif configuration.background_worker_threads != 0 && hint.fetch(:background, true)
|
|
81
|
+
if configuration.background_worker_threads != 0 && hint.fetch(:background, true)
|
|
84
82
|
unless dispatch_background_event(event, hint)
|
|
85
83
|
transport.record_lost_event(:queue_overflow, data_category)
|
|
86
84
|
transport.record_lost_event(:queue_overflow, "span", num: spans_before + 1) if is_transaction
|
|
@@ -195,9 +193,19 @@ module Sentry
|
|
|
195
193
|
def event_from_log(message, level:, **options)
|
|
196
194
|
return unless configuration.sending_allowed?
|
|
197
195
|
|
|
198
|
-
attributes = options.reject { |k, _| k == :level || k == :severity }
|
|
196
|
+
attributes = options.reject { |k, _| k == :level || k == :severity || k == :origin }
|
|
197
|
+
origin = options[:origin]
|
|
198
|
+
body = Utils::EncodingHelper.safe_utf_8_string(message)
|
|
199
199
|
|
|
200
|
-
|
|
200
|
+
sanitized_attributes = attributes.transform_values do |value|
|
|
201
|
+
if value.is_a?(String)
|
|
202
|
+
Utils::EncodingHelper.safe_utf_8_string(value)
|
|
203
|
+
else
|
|
204
|
+
value
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
LogEvent.new(level: level, body: body, attributes: sanitized_attributes, origin: origin)
|
|
201
209
|
end
|
|
202
210
|
|
|
203
211
|
# Initializes an Event object with the given Transaction object.
|
|
@@ -209,22 +217,13 @@ module Sentry
|
|
|
209
217
|
|
|
210
218
|
# @!macro send_event
|
|
211
219
|
def send_event(event, hint = nil)
|
|
212
|
-
|
|
213
|
-
data_category = Envelope::Item.data_category(event_type)
|
|
220
|
+
data_category = Envelope::Item.data_category(event.type)
|
|
214
221
|
spans_before = event.is_a?(TransactionEvent) ? event.spans.size : 0
|
|
215
222
|
|
|
216
|
-
if
|
|
223
|
+
if event.is_a?(ErrorEvent) && configuration.before_send
|
|
217
224
|
event = configuration.before_send.call(event, hint)
|
|
218
225
|
|
|
219
|
-
|
|
220
|
-
when ErrorEvent, CheckInEvent
|
|
221
|
-
# do nothing
|
|
222
|
-
when Hash
|
|
223
|
-
log_debug(<<~MSG)
|
|
224
|
-
Returning a Hash from before_send is deprecated and will be removed in the next major version.
|
|
225
|
-
Please return a Sentry::ErrorEvent object instead.
|
|
226
|
-
MSG
|
|
227
|
-
else
|
|
226
|
+
if !event.is_a?(ErrorEvent)
|
|
228
227
|
# Avoid serializing the event object in this case because we aren't sure what it is and what it contains
|
|
229
228
|
log_debug(<<~MSG)
|
|
230
229
|
Discarded event because before_send didn't return a Sentry::ErrorEvent object but an instance of #{event.class}
|
|
@@ -234,21 +233,10 @@ module Sentry
|
|
|
234
233
|
end
|
|
235
234
|
end
|
|
236
235
|
|
|
237
|
-
if
|
|
236
|
+
if event.is_a?(TransactionEvent) && configuration.before_send_transaction
|
|
238
237
|
event = configuration.before_send_transaction.call(event, hint)
|
|
239
238
|
|
|
240
|
-
if event.is_a?(TransactionEvent)
|
|
241
|
-
spans_after = event.is_a?(TransactionEvent) ? event.spans.size : 0
|
|
242
|
-
spans_delta = spans_before - spans_after
|
|
243
|
-
transport.record_lost_event(:before_send, "span", num: spans_delta) if spans_delta > 0
|
|
244
|
-
|
|
245
|
-
if event.is_a?(Hash)
|
|
246
|
-
log_debug(<<~MSG)
|
|
247
|
-
Returning a Hash from before_send_transaction is deprecated and will be removed in the next major version.
|
|
248
|
-
Please return a Sentry::TransactionEvent object instead.
|
|
249
|
-
MSG
|
|
250
|
-
end
|
|
251
|
-
else
|
|
239
|
+
if !event.is_a?(TransactionEvent)
|
|
252
240
|
# Avoid serializing the event object in this case because we aren't sure what it is and what it contains
|
|
253
241
|
log_debug(<<~MSG)
|
|
254
242
|
Discarded event because before_send_transaction didn't return a Sentry::TransactionEvent object but an instance of #{event.class}
|
|
@@ -257,6 +245,23 @@ module Sentry
|
|
|
257
245
|
transport.record_lost_event(:before_send, "span", num: spans_before + 1)
|
|
258
246
|
return
|
|
259
247
|
end
|
|
248
|
+
|
|
249
|
+
spans_after = event.is_a?(TransactionEvent) ? event.spans.size : 0
|
|
250
|
+
spans_delta = spans_before - spans_after
|
|
251
|
+
transport.record_lost_event(:before_send, "span", num: spans_delta) if spans_delta > 0
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
if event.is_a?(CheckInEvent) && configuration.before_send_check_in
|
|
255
|
+
event = configuration.before_send_check_in.call(event, hint)
|
|
256
|
+
|
|
257
|
+
if !event.is_a?(CheckInEvent)
|
|
258
|
+
# Avoid serializing the event object in this case because we aren't sure what it is and what it contains
|
|
259
|
+
log_debug(<<~MSG)
|
|
260
|
+
Discarded event because before_send_check_in didn't return a Sentry::CheckInEvent object but an instance of #{event.class}
|
|
261
|
+
MSG
|
|
262
|
+
transport.record_lost_event(:before_send, data_category)
|
|
263
|
+
return
|
|
264
|
+
end
|
|
260
265
|
end
|
|
261
266
|
|
|
262
267
|
transport.send_event(event) if configuration.sending_to_dsn_allowed?
|
|
@@ -290,7 +295,7 @@ module Sentry
|
|
|
290
295
|
processed_log_event = configuration.before_send_log.call(log_event)
|
|
291
296
|
|
|
292
297
|
if processed_log_event
|
|
293
|
-
envelope_items << processed_log_event.
|
|
298
|
+
envelope_items << processed_log_event.to_h
|
|
294
299
|
else
|
|
295
300
|
discarded_count += 1
|
|
296
301
|
end
|
|
@@ -298,7 +303,7 @@ module Sentry
|
|
|
298
303
|
|
|
299
304
|
envelope_items
|
|
300
305
|
else
|
|
301
|
-
envelope_items = log_events.map(&:
|
|
306
|
+
envelope_items = log_events.map(&:to_h)
|
|
302
307
|
end
|
|
303
308
|
|
|
304
309
|
envelope.add_item(
|
|
@@ -333,38 +338,6 @@ module Sentry
|
|
|
333
338
|
raise
|
|
334
339
|
end
|
|
335
340
|
|
|
336
|
-
# @deprecated use Sentry.get_traceparent instead.
|
|
337
|
-
#
|
|
338
|
-
# Generates a Sentry trace for distribted tracing from the given Span.
|
|
339
|
-
# Returns `nil` if `config.propagate_traces` is `false`.
|
|
340
|
-
# @param span [Span] the span to generate trace from.
|
|
341
|
-
# @return [String, nil]
|
|
342
|
-
def generate_sentry_trace(span)
|
|
343
|
-
return unless configuration.propagate_traces
|
|
344
|
-
|
|
345
|
-
trace = span.to_sentry_trace
|
|
346
|
-
log_debug("[Tracing] Adding #{SENTRY_TRACE_HEADER_NAME} header to outgoing request: #{trace}")
|
|
347
|
-
trace
|
|
348
|
-
end
|
|
349
|
-
|
|
350
|
-
# @deprecated Use Sentry.get_baggage instead.
|
|
351
|
-
#
|
|
352
|
-
# Generates a W3C Baggage header for distributed tracing from the given Span.
|
|
353
|
-
# Returns `nil` if `config.propagate_traces` is `false`.
|
|
354
|
-
# @param span [Span] the span to generate trace from.
|
|
355
|
-
# @return [String, nil]
|
|
356
|
-
def generate_baggage(span)
|
|
357
|
-
return unless configuration.propagate_traces
|
|
358
|
-
|
|
359
|
-
baggage = span.to_baggage
|
|
360
|
-
|
|
361
|
-
if baggage && !baggage.empty?
|
|
362
|
-
log_debug("[Tracing] Adding #{BAGGAGE_HEADER_NAME} header to outgoing request: #{baggage}")
|
|
363
|
-
end
|
|
364
|
-
|
|
365
|
-
baggage
|
|
366
|
-
end
|
|
367
|
-
|
|
368
341
|
private
|
|
369
342
|
|
|
370
343
|
def dispatch_background_event(event, hint)
|
|
@@ -372,28 +345,5 @@ module Sentry
|
|
|
372
345
|
send_event(event, hint)
|
|
373
346
|
end
|
|
374
347
|
end
|
|
375
|
-
|
|
376
|
-
def dispatch_async_event(async_block, event, hint)
|
|
377
|
-
# We have to convert to a JSON-like hash, because background job
|
|
378
|
-
# processors (esp ActiveJob) may not like weird types in the event hash
|
|
379
|
-
|
|
380
|
-
event_hash =
|
|
381
|
-
begin
|
|
382
|
-
event.to_json_compatible
|
|
383
|
-
rescue => e
|
|
384
|
-
log_error("Converting #{event.type} (#{event.event_id}) to JSON compatible hash failed", e, debug: configuration.debug)
|
|
385
|
-
return
|
|
386
|
-
end
|
|
387
|
-
|
|
388
|
-
if async_block.arity == 2
|
|
389
|
-
hint = JSON.parse(JSON.generate(hint))
|
|
390
|
-
async_block.call(event_hash, hint)
|
|
391
|
-
else
|
|
392
|
-
async_block.call(event_hash)
|
|
393
|
-
end
|
|
394
|
-
rescue => e
|
|
395
|
-
log_error("Async #{event_hash["type"]} sending failed", e, debug: configuration.debug)
|
|
396
|
-
send_event(event, hint)
|
|
397
|
-
end
|
|
398
348
|
end
|
|
399
349
|
end
|