sentry-ruby 6.1.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/README.md +1 -1
- data/lib/sentry/backtrace/line.rb +99 -0
- data/lib/sentry/backtrace.rb +44 -76
- data/lib/sentry/client.rb +11 -1
- data/lib/sentry/utils/encoding_helper.rb +7 -0
- data/lib/sentry/version.rb +1 -1
- metadata +7 -6
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/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
|
|
|
@@ -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/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
|
|
@@ -194,8 +195,17 @@ module Sentry
|
|
|
194
195
|
|
|
195
196
|
attributes = options.reject { |k, _| k == :level || k == :severity || k == :origin }
|
|
196
197
|
origin = options[:origin]
|
|
198
|
+
body = Utils::EncodingHelper.safe_utf_8_string(message)
|
|
197
199
|
|
|
198
|
-
|
|
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)
|
|
199
209
|
end
|
|
200
210
|
|
|
201
211
|
# Initializes an Event object with the given Transaction object.
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
module Sentry
|
|
4
4
|
module Utils
|
|
5
5
|
module EncodingHelper
|
|
6
|
+
EMPTY_STRING = ""
|
|
7
|
+
MALFORMED_STRING = "<malformed-string>"
|
|
8
|
+
|
|
6
9
|
def self.encode_to_utf_8(value)
|
|
7
10
|
if value.encoding != Encoding::UTF_8 && value.respond_to?(:force_encoding)
|
|
8
11
|
value = value.dup.force_encoding(Encoding::UTF_8)
|
|
@@ -17,6 +20,10 @@ module Sentry
|
|
|
17
20
|
|
|
18
21
|
value.dup.force_encoding(Encoding::UTF_8).valid_encoding?
|
|
19
22
|
end
|
|
23
|
+
|
|
24
|
+
def self.safe_utf_8_string(value)
|
|
25
|
+
valid_utf_8?(value) ? value : MALFORMED_STRING
|
|
26
|
+
end
|
|
20
27
|
end
|
|
21
28
|
end
|
|
22
29
|
end
|
data/lib/sentry/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sentry-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 6.1.
|
|
4
|
+
version: 6.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sentry Team
|
|
@@ -67,6 +67,7 @@ files:
|
|
|
67
67
|
- lib/sentry/background_worker.rb
|
|
68
68
|
- lib/sentry/backpressure_monitor.rb
|
|
69
69
|
- lib/sentry/backtrace.rb
|
|
70
|
+
- lib/sentry/backtrace/line.rb
|
|
70
71
|
- lib/sentry/baggage.rb
|
|
71
72
|
- lib/sentry/breadcrumb.rb
|
|
72
73
|
- lib/sentry/breadcrumb/sentry_logger.rb
|
|
@@ -148,15 +149,15 @@ files:
|
|
|
148
149
|
- lib/sentry/version.rb
|
|
149
150
|
- sentry-ruby-core.gemspec
|
|
150
151
|
- sentry-ruby.gemspec
|
|
151
|
-
homepage: https://github.com/getsentry/sentry-ruby/tree/6.1.
|
|
152
|
+
homepage: https://github.com/getsentry/sentry-ruby/tree/6.1.1/sentry-ruby
|
|
152
153
|
licenses:
|
|
153
154
|
- MIT
|
|
154
155
|
metadata:
|
|
155
|
-
homepage_uri: https://github.com/getsentry/sentry-ruby/tree/6.1.
|
|
156
|
-
source_code_uri: https://github.com/getsentry/sentry-ruby/tree/6.1.
|
|
157
|
-
changelog_uri: https://github.com/getsentry/sentry-ruby/blob/6.1.
|
|
156
|
+
homepage_uri: https://github.com/getsentry/sentry-ruby/tree/6.1.1/sentry-ruby
|
|
157
|
+
source_code_uri: https://github.com/getsentry/sentry-ruby/tree/6.1.1/sentry-ruby
|
|
158
|
+
changelog_uri: https://github.com/getsentry/sentry-ruby/blob/6.1.1/CHANGELOG.md
|
|
158
159
|
bug_tracker_uri: https://github.com/getsentry/sentry-ruby/issues
|
|
159
|
-
documentation_uri: http://www.rubydoc.info/gems/sentry-ruby/6.1.
|
|
160
|
+
documentation_uri: http://www.rubydoc.info/gems/sentry-ruby/6.1.1
|
|
160
161
|
rdoc_options: []
|
|
161
162
|
require_paths:
|
|
162
163
|
- lib
|