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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a166b422dd9fc77ede5fcc2d11f6f5556db89bb0e545ad44c06354cb1574d976
4
- data.tar.gz: 067fb812d95c439bd060c65795cf3cc3e66b4f22cf5b681108f92ea4f6e35b69
3
+ metadata.gz: 0c7e991a71c48c638739ac8ce5800da3796ea8847cf2957eee2a44b6b04233fc
4
+ data.tar.gz: 4a1981f39e3dac807e4c14fb50372467a46bf3f01331d0c6d61c3b27cc46e26c
5
5
  SHA512:
6
- metadata.gz: 04bf6ca584de8a34cbc3e860b8e54082e5f5dd9c31626be8cd7f4698b718ac94c4d104982351de858f52ac640e9ac41b9d5ea2aee54552f1dc23e949d5ef33c3
7
- data.tar.gz: 80d82500a25f462656f4f4abcfcda630b0e7f8afe07c2530feede5032ea1b5f5587da1b5eca43d11c5699e683b90db69a89815a31e490c765bb8b8d5a893985f
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
  * [![Forum](https://img.shields.io/badge/forum-sentry-green.svg)](https://forum.sentry.io/c/sdks)
108
108
  * [![Discord Chat](https://img.shields.io/discord/621778831602221064?logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/PXa5Apfe7K)
109
109
  * [![Stack Overflow](https://img.shields.io/badge/stack%20overflow-sentry-green.svg)](https://stackoverflow.com/questions/tagged/sentry)
110
- * [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry)
110
+ * [![X Follow](https://img.shields.io/twitter/follow/sentry?label=sentry&style=social)](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
@@ -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
- LogEvent.new(level: level, body: message, attributes: attributes, origin: origin)
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sentry
4
- VERSION = "6.1.0"
4
+ VERSION = "6.1.1"
5
5
  end
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.0
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.0/sentry-ruby
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.0/sentry-ruby
156
- source_code_uri: https://github.com/getsentry/sentry-ruby/tree/6.1.0/sentry-ruby
157
- changelog_uri: https://github.com/getsentry/sentry-ruby/blob/6.1.0/CHANGELOG.md
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.0
160
+ documentation_uri: http://www.rubydoc.info/gems/sentry-ruby/6.1.1
160
161
  rdoc_options: []
161
162
  require_paths:
162
163
  - lib