sentry-ruby 6.4.1 → 6.6.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/README.md +3 -0
- data/lib/sentry/backtrace/line.rb +16 -9
- data/lib/sentry/backtrace.rb +6 -4
- data/lib/sentry/baggage.rb +1 -1
- data/lib/sentry/configuration.rb +37 -1
- data/lib/sentry/dsn.rb +13 -1
- data/lib/sentry/exceptions.rb +3 -0
- data/lib/sentry/hub.rb +6 -0
- data/lib/sentry/interfaces/request.rb +13 -4
- data/lib/sentry/interfaces/stacktrace.rb +2 -29
- data/lib/sentry/interfaces/stacktrace_builder.rb +22 -6
- data/lib/sentry/linecache.rb +18 -21
- data/lib/sentry/metric_event.rb +1 -1
- data/lib/sentry/profiler/helpers.rb +1 -21
- data/lib/sentry/profiler.rb +1 -0
- data/lib/sentry/propagation_context.rb +48 -8
- data/lib/sentry/release_detector.rb +6 -1
- data/lib/sentry/scope.rb +1 -0
- data/lib/sentry/test_helper.rb +41 -8
- data/lib/sentry/transaction.rb +2 -1
- data/lib/sentry/transport/dummy_transport.rb +7 -0
- data/lib/sentry/transport/http_transport.rb +6 -0
- data/lib/sentry/transport.rb +6 -1
- data/lib/sentry/utils/filename_cache.rb +47 -0
- data/lib/sentry/utils/http_tracing.rb +7 -1
- data/lib/sentry/vernier/output.rb +2 -1
- data/lib/sentry/vernier/profiler.rb +3 -1
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +1 -0
- 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: 3ac6a6802b328b59cb636ac1d91b5b1ab5710e9c1427c3d910e7bd05f30b618b
|
|
4
|
+
data.tar.gz: a77ee9a574da2de452d962848dbfca19aef525304e1bdbf65b21cb11ec7e9e3b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c1f221cea1a011d2540c666e14823423d12fa37f3ea4ee59f3d68035ad36e33dd62fbc8f23712fee46b8da31e3bbb7c027e664927945b959197c15d10626f4e9
|
|
7
|
+
data.tar.gz: 95f32db537d5fa0a95b3897dcd7fc6d34dff884fe474fc9a43d0567d6a3ef6a84cb181f06c9ef60b0e1e132cb5afa28e65faf427c408c518beeb1305ddf9af1f
|
data/README.md
CHANGED
|
@@ -21,6 +21,7 @@ Sentry SDK for Ruby
|
|
|
21
21
|
| [](https://rubygems.org/gems/sentry-delayed_job) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/tests.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby) | [](https://www.rubydoc.info/gems/sentry-delayed_job) |
|
|
22
22
|
| [](https://rubygems.org/gems/sentry-resque) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/tests.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby) | [](https://www.rubydoc.info/gems/sentry-resque) |
|
|
23
23
|
| [](https://rubygems.org/gems/sentry-opentelemetry) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/tests.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby) | [](https://www.rubydoc.info/gems/sentry-opentelemetry) |
|
|
24
|
+
| [](https://rubygems.org/gems/sentry-yabeda) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/tests.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby) | [](https://www.rubydoc.info/gems/sentry-yabeda) |
|
|
24
25
|
|
|
25
26
|
|
|
26
27
|
|
|
@@ -53,6 +54,7 @@ gem "sentry-sidekiq"
|
|
|
53
54
|
gem "sentry-delayed_job"
|
|
54
55
|
gem "sentry-resque"
|
|
55
56
|
gem "sentry-opentelemetry"
|
|
57
|
+
gem "sentry-yabeda"
|
|
56
58
|
```
|
|
57
59
|
|
|
58
60
|
### Configuration
|
|
@@ -93,6 +95,7 @@ To learn more about sampling transactions, please visit the [official documentat
|
|
|
93
95
|
- [DelayedJob](https://docs.sentry.io/platforms/ruby/guides/delayed_job/)
|
|
94
96
|
- [Resque](https://docs.sentry.io/platforms/ruby/guides/resque/)
|
|
95
97
|
- [OpenTelemetry](https://docs.sentry.io/platforms/ruby/performance/instrumentation/opentelemetry/)
|
|
98
|
+
- [Yabeda](https://docs.sentry.io/platforms/ruby/guides/yabeda/)
|
|
96
99
|
|
|
97
100
|
### Enriching Events
|
|
98
101
|
|
|
@@ -6,6 +6,7 @@ module Sentry
|
|
|
6
6
|
# Handles backtrace parsing line by line
|
|
7
7
|
class Line
|
|
8
8
|
RB_EXTENSION = ".rb"
|
|
9
|
+
CLASS_EXTENSION = ".class"
|
|
9
10
|
# regexp (optional leading X: on windows, or JRuby9000 class-prefix)
|
|
10
11
|
RUBY_INPUT_FORMAT = /
|
|
11
12
|
^ \s* (?: [a-zA-Z]: | uri:classloader: )? ([^:]+ | <.*>):
|
|
@@ -37,12 +38,21 @@ module Sentry
|
|
|
37
38
|
ruby_match = unparsed_line.match(RUBY_INPUT_FORMAT)
|
|
38
39
|
|
|
39
40
|
if ruby_match
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
module_name =
|
|
41
|
+
file = ruby_match[1]
|
|
42
|
+
number = ruby_match[2]
|
|
43
|
+
module_name = ruby_match[4]
|
|
44
|
+
method = ruby_match[5]
|
|
45
|
+
if file.end_with?(CLASS_EXTENSION)
|
|
46
|
+
file.sub!(/\.class$/, RB_EXTENSION)
|
|
47
|
+
end
|
|
43
48
|
else
|
|
44
49
|
java_match = unparsed_line.match(JAVA_INPUT_FORMAT)
|
|
45
|
-
|
|
50
|
+
if java_match
|
|
51
|
+
module_name = java_match[1]
|
|
52
|
+
method = java_match[2]
|
|
53
|
+
file = java_match[3]
|
|
54
|
+
number = java_match[4]
|
|
55
|
+
end
|
|
46
56
|
end
|
|
47
57
|
new(file, number, method, module_name, in_app_pattern)
|
|
48
58
|
end
|
|
@@ -74,12 +84,9 @@ module Sentry
|
|
|
74
84
|
|
|
75
85
|
def in_app
|
|
76
86
|
return false unless in_app_pattern
|
|
87
|
+
return false unless file
|
|
77
88
|
|
|
78
|
-
|
|
79
|
-
true
|
|
80
|
-
else
|
|
81
|
-
false
|
|
82
|
-
end
|
|
89
|
+
file.match?(in_app_pattern)
|
|
83
90
|
end
|
|
84
91
|
|
|
85
92
|
# Reconstructs the line in a readable fashion
|
data/lib/sentry/backtrace.rb
CHANGED
|
@@ -10,14 +10,16 @@ module Sentry
|
|
|
10
10
|
# holder for an Array of Backtrace::Line instances
|
|
11
11
|
attr_reader :lines
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
# @deprecated project_root, in_app_pattern passed from outside
|
|
14
|
+
# @deprecated app_dirs_pattern, in_app_pattern passed from outside
|
|
15
|
+
def self.parse(backtrace, project_root, app_dirs_pattern, in_app_pattern: nil, &backtrace_cleanup_callback)
|
|
14
16
|
ruby_lines = backtrace.is_a?(Array) ? backtrace : backtrace.split(/\n\s*/)
|
|
15
17
|
|
|
16
18
|
ruby_lines = backtrace_cleanup_callback.call(ruby_lines) if backtrace_cleanup_callback
|
|
17
19
|
|
|
18
|
-
in_app_pattern
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
# in_app_pattern is now passed in from StacktraceBuilder, so this regex won't be triggered
|
|
21
|
+
# only here for backwards compat and will be deleted
|
|
22
|
+
in_app_pattern ||= Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}")
|
|
21
23
|
|
|
22
24
|
lines = ruby_lines.to_a.map do |unparsed_line|
|
|
23
25
|
Line.parse(unparsed_line, in_app_pattern)
|
data/lib/sentry/baggage.rb
CHANGED
|
@@ -25,7 +25,7 @@ module Sentry
|
|
|
25
25
|
# The presence of a Sentry item makes the baggage object immutable.
|
|
26
26
|
#
|
|
27
27
|
# @param header [String] The incoming Baggage header string.
|
|
28
|
-
# @return [Baggage
|
|
28
|
+
# @return [Baggage]
|
|
29
29
|
def self.from_incoming_header(header)
|
|
30
30
|
items = {}
|
|
31
31
|
mutable = true
|
data/lib/sentry/configuration.rb
CHANGED
|
@@ -371,6 +371,24 @@ module Sentry
|
|
|
371
371
|
# @return [Proc, nil]
|
|
372
372
|
attr_reader :std_lib_logger_filter
|
|
373
373
|
|
|
374
|
+
# An optional organization ID. The SDK will try to extract it from the DSN in most cases
|
|
375
|
+
# but you can provide it explicitly for self-hosted and Relay setups.
|
|
376
|
+
# This value is used for trace propagation and for features like strict_trace_continuation.
|
|
377
|
+
# @return [String, nil]
|
|
378
|
+
attr_reader :org_id
|
|
379
|
+
|
|
380
|
+
# If set to true, the SDK will only continue a trace if the org_id of the incoming trace found in the
|
|
381
|
+
# baggage header matches the org_id of the current Sentry client and only if BOTH are present.
|
|
382
|
+
#
|
|
383
|
+
# If set to false, consistency of org_id will only be enforced if both are present.
|
|
384
|
+
# If either are missing, the trace will be continued.
|
|
385
|
+
#
|
|
386
|
+
# The client's organization ID is extracted from the DSN or can be set with the org_id option.
|
|
387
|
+
# If the organization IDs do not match, the SDK will start a new trace instead of continuing the incoming one.
|
|
388
|
+
# This is useful to prevent traces of unknown third-party services from being continued in your application.
|
|
389
|
+
# @return [Boolean]
|
|
390
|
+
attr_accessor :strict_trace_continuation
|
|
391
|
+
|
|
374
392
|
# these are not config options
|
|
375
393
|
# @!visibility private
|
|
376
394
|
attr_reader :errors, :gem_specs
|
|
@@ -443,7 +461,8 @@ module Sentry
|
|
|
443
461
|
def callbacks
|
|
444
462
|
@callbacks ||= {
|
|
445
463
|
initialize: { before: [], after: [] },
|
|
446
|
-
configured: { before: [], after: [] }
|
|
464
|
+
configured: { before: [], after: [] },
|
|
465
|
+
closed: { before: [], after: [] }
|
|
447
466
|
}
|
|
448
467
|
end
|
|
449
468
|
|
|
@@ -520,6 +539,8 @@ module Sentry
|
|
|
520
539
|
self.trusted_proxies = []
|
|
521
540
|
self.dsn = ENV["SENTRY_DSN"]
|
|
522
541
|
self.capture_queue_time = true
|
|
542
|
+
self.org_id = nil
|
|
543
|
+
self.strict_trace_continuation = false
|
|
523
544
|
|
|
524
545
|
spotlight_env = ENV["SENTRY_SPOTLIGHT"]
|
|
525
546
|
spotlight_bool = Sentry::Utils::EnvHelper.env_to_bool(spotlight_env, strict: true)
|
|
@@ -673,6 +694,16 @@ module Sentry
|
|
|
673
694
|
@profiler_class = profiler_class
|
|
674
695
|
end
|
|
675
696
|
|
|
697
|
+
def org_id=(value)
|
|
698
|
+
@org_id = value&.to_s
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
# Returns the effective org ID, preferring the explicit config option over the DSN-parsed value.
|
|
702
|
+
# @return [String, nil]
|
|
703
|
+
def effective_org_id
|
|
704
|
+
org_id || dsn&.org_id
|
|
705
|
+
end
|
|
706
|
+
|
|
676
707
|
def sending_allowed?
|
|
677
708
|
spotlight || sending_to_dsn_allowed?
|
|
678
709
|
end
|
|
@@ -768,6 +799,11 @@ module Sentry
|
|
|
768
799
|
@errors.join(", ")
|
|
769
800
|
end
|
|
770
801
|
|
|
802
|
+
# @api private
|
|
803
|
+
def run_after_close_callbacks
|
|
804
|
+
run_callbacks(:after, :closed)
|
|
805
|
+
end
|
|
806
|
+
|
|
771
807
|
private
|
|
772
808
|
|
|
773
809
|
def init_dsn(dsn_string)
|
data/lib/sentry/dsn.rb
CHANGED
|
@@ -11,8 +11,9 @@ module Sentry
|
|
|
11
11
|
REQUIRED_ATTRIBUTES = %w[host path public_key project_id].freeze
|
|
12
12
|
LOCALHOST_NAMES = %w[localhost 127.0.0.1 ::1 [::1]].freeze
|
|
13
13
|
LOCALHOST_PATTERN = /\.local(host|domain)?$/i
|
|
14
|
+
ORG_ID_REGEX = /\Ao(\d+)\./
|
|
14
15
|
|
|
15
|
-
attr_reader :scheme, :secret_key, :port, *REQUIRED_ATTRIBUTES
|
|
16
|
+
attr_reader :scheme, :secret_key, :port, :org_id, *REQUIRED_ATTRIBUTES
|
|
16
17
|
|
|
17
18
|
def initialize(dsn_string)
|
|
18
19
|
@raw_value = dsn_string
|
|
@@ -31,6 +32,8 @@ module Sentry
|
|
|
31
32
|
@host = uri.host
|
|
32
33
|
@port = uri.port if uri.port
|
|
33
34
|
@path = uri_path.join("/")
|
|
35
|
+
|
|
36
|
+
@org_id = extract_org_id_from_host
|
|
34
37
|
end
|
|
35
38
|
|
|
36
39
|
def valid?
|
|
@@ -101,5 +104,14 @@ module Sentry
|
|
|
101
104
|
|
|
102
105
|
"Sentry " + fields.map { |key, value| "#{key}=#{value}" }.join(", ")
|
|
103
106
|
end
|
|
107
|
+
|
|
108
|
+
private
|
|
109
|
+
|
|
110
|
+
def extract_org_id_from_host
|
|
111
|
+
return nil unless @host
|
|
112
|
+
|
|
113
|
+
match = ORG_ID_REGEX.match(@host)
|
|
114
|
+
match ? match[1] : nil
|
|
115
|
+
end
|
|
104
116
|
end
|
|
105
117
|
end
|
data/lib/sentry/exceptions.rb
CHANGED
data/lib/sentry/hub.rb
CHANGED
|
@@ -54,6 +54,12 @@ module Sentry
|
|
|
54
54
|
current_layer&.client
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
+
# All clients bound across the hub's scope stack, base layer first.
|
|
58
|
+
# @return [Array<Client>]
|
|
59
|
+
def clients
|
|
60
|
+
@stack.map(&:client).compact
|
|
61
|
+
end
|
|
62
|
+
|
|
57
63
|
def configuration
|
|
58
64
|
current_client.configuration
|
|
59
65
|
end
|
|
@@ -11,6 +11,9 @@ module Sentry
|
|
|
11
11
|
"HTTP_X_FORWARDED_FOR"
|
|
12
12
|
].freeze
|
|
13
13
|
|
|
14
|
+
# Regex to detect lowercase chars — match? is allocation-free (no MatchData/String)
|
|
15
|
+
LOWERCASE_PATTERN = /[a-z]/.freeze
|
|
16
|
+
|
|
14
17
|
# See Sentry server default limits at
|
|
15
18
|
# https://github.com/getsentry/sentry/blob/master/src/sentry/conf/server.py
|
|
16
19
|
MAX_BODY_LIMIT = 4096 * 4
|
|
@@ -93,7 +96,7 @@ module Sentry
|
|
|
93
96
|
next if key == "HTTP_AUTHORIZATION" && !send_default_pii
|
|
94
97
|
|
|
95
98
|
# Rack stores headers as HTTP_WHAT_EVER, we need What-Ever
|
|
96
|
-
key = key.
|
|
99
|
+
key = key.delete_prefix("HTTP_")
|
|
97
100
|
key = key.split("_").map(&:capitalize).join("-")
|
|
98
101
|
|
|
99
102
|
memo[key] = Utils::EncodingHelper.encode_to_utf_8(value.to_s)
|
|
@@ -108,7 +111,7 @@ module Sentry
|
|
|
108
111
|
end
|
|
109
112
|
|
|
110
113
|
def is_skippable_header?(key)
|
|
111
|
-
key.
|
|
114
|
+
key.match?(LOWERCASE_PATTERN) || # lower-case envs aren't real http headers
|
|
112
115
|
key == "HTTP_COOKIE" || # Cookies don't go here, they go somewhere else
|
|
113
116
|
!(key.start_with?("HTTP_") || CONTENT_HEADERS.include?(key))
|
|
114
117
|
end
|
|
@@ -119,12 +122,18 @@ module Sentry
|
|
|
119
122
|
# if the request has legitimately sent a Version header themselves.
|
|
120
123
|
# See: https://github.com/rack/rack/blob/028438f/lib/rack/handler/cgi.rb#L29
|
|
121
124
|
def is_server_protocol?(key, value, protocol_version)
|
|
122
|
-
|
|
123
|
-
return false if rack_version >= Gem::Version.new("3.0")
|
|
125
|
+
return false if self.class.rack_3_or_above?
|
|
124
126
|
|
|
125
127
|
key == "HTTP_VERSION" && value == protocol_version
|
|
126
128
|
end
|
|
127
129
|
|
|
130
|
+
def self.rack_3_or_above?
|
|
131
|
+
return @rack_3_or_above if defined?(@rack_3_or_above)
|
|
132
|
+
|
|
133
|
+
@rack_3_or_above = defined?(::Rack) &&
|
|
134
|
+
Gem::Version.new(::Rack.release) >= Gem::Version.new("3.0")
|
|
135
|
+
end
|
|
136
|
+
|
|
128
137
|
def filter_and_format_env(env, rack_env_whitelist)
|
|
129
138
|
return env if rack_env_whitelist.empty?
|
|
130
139
|
|
|
@@ -27,38 +27,19 @@ module Sentry
|
|
|
27
27
|
attr_accessor :abs_path, :context_line, :function, :in_app, :filename,
|
|
28
28
|
:lineno, :module, :pre_context, :post_context, :vars
|
|
29
29
|
|
|
30
|
-
def initialize(project_root, line, strip_backtrace_load_path = true)
|
|
31
|
-
@project_root = project_root
|
|
32
|
-
@strip_backtrace_load_path = strip_backtrace_load_path
|
|
33
|
-
|
|
30
|
+
def initialize(project_root, line, strip_backtrace_load_path = true, filename_cache: nil)
|
|
34
31
|
@abs_path = line.file
|
|
35
32
|
@function = line.method if line.method
|
|
36
33
|
@lineno = line.number
|
|
37
34
|
@in_app = line.in_app
|
|
38
35
|
@module = line.module_name if line.module_name
|
|
39
|
-
@filename = compute_filename
|
|
36
|
+
@filename = filename_cache&.compute_filename(@abs_path, @in_app, strip_backtrace_load_path)
|
|
40
37
|
end
|
|
41
38
|
|
|
42
39
|
def to_s
|
|
43
40
|
"#{@filename}:#{@lineno}"
|
|
44
41
|
end
|
|
45
42
|
|
|
46
|
-
def compute_filename
|
|
47
|
-
return if abs_path.nil?
|
|
48
|
-
return abs_path unless @strip_backtrace_load_path
|
|
49
|
-
|
|
50
|
-
prefix =
|
|
51
|
-
if under_project_root? && in_app
|
|
52
|
-
@project_root
|
|
53
|
-
elsif under_project_root?
|
|
54
|
-
longest_load_path || @project_root
|
|
55
|
-
else
|
|
56
|
-
longest_load_path
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
prefix ? abs_path[prefix.to_s.chomp(File::SEPARATOR).length + 1..-1] : abs_path
|
|
60
|
-
end
|
|
61
|
-
|
|
62
43
|
def set_context(linecache, context_lines)
|
|
63
44
|
return unless abs_path
|
|
64
45
|
|
|
@@ -76,14 +57,6 @@ module Sentry
|
|
|
76
57
|
end
|
|
77
58
|
|
|
78
59
|
private
|
|
79
|
-
|
|
80
|
-
def under_project_root?
|
|
81
|
-
@project_root && abs_path.start_with?(@project_root)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def longest_load_path
|
|
85
|
-
$LOAD_PATH.select { |path| abs_path.start_with?(path.to_s) }.max_by(&:size)
|
|
86
|
-
end
|
|
87
60
|
end
|
|
88
61
|
end
|
|
89
62
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "sentry/utils/filename_cache"
|
|
4
|
+
|
|
3
5
|
module Sentry
|
|
4
6
|
class StacktraceBuilder
|
|
5
7
|
# @return [String]
|
|
@@ -20,6 +22,9 @@ module Sentry
|
|
|
20
22
|
# @return [Boolean]
|
|
21
23
|
attr_reader :strip_backtrace_load_path
|
|
22
24
|
|
|
25
|
+
# @return [FilenameCache]
|
|
26
|
+
attr_reader :filename_cache
|
|
27
|
+
|
|
23
28
|
# @param project_root [String]
|
|
24
29
|
# @param app_dirs_pattern [Regexp, nil]
|
|
25
30
|
# @param linecache [LineCache]
|
|
@@ -46,6 +51,8 @@ module Sentry
|
|
|
46
51
|
@context_lines = context_lines
|
|
47
52
|
@backtrace_cleanup_callback = backtrace_cleanup_callback
|
|
48
53
|
@strip_backtrace_load_path = strip_backtrace_load_path
|
|
54
|
+
@in_app_pattern = Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}") if app_dirs_pattern
|
|
55
|
+
@filename_cache = FilenameCache.new(project_root)
|
|
49
56
|
end
|
|
50
57
|
|
|
51
58
|
# Generates a StacktraceInterface with the given backtrace.
|
|
@@ -64,13 +71,21 @@ module Sentry
|
|
|
64
71
|
# @yieldparam frame [StacktraceInterface::Frame]
|
|
65
72
|
# @return [StacktraceInterface]
|
|
66
73
|
def build(backtrace:, &frame_callback)
|
|
67
|
-
parsed_lines = parse_backtrace_lines(backtrace)
|
|
74
|
+
parsed_lines = parse_backtrace_lines(backtrace)
|
|
75
|
+
|
|
76
|
+
# Build frames in reverse order, skipping lines without files
|
|
77
|
+
# Single pass instead of select + reverse + map + compact
|
|
78
|
+
frames = []
|
|
79
|
+
i = parsed_lines.size - 1
|
|
80
|
+
while i >= 0
|
|
81
|
+
line = parsed_lines[i]
|
|
82
|
+
i -= 1
|
|
83
|
+
next unless line.file
|
|
68
84
|
|
|
69
|
-
frames = parsed_lines.reverse.map do |line|
|
|
70
85
|
frame = convert_parsed_line_into_frame(line)
|
|
71
86
|
frame = frame_callback.call(frame) if frame_callback
|
|
72
|
-
frame
|
|
73
|
-
end
|
|
87
|
+
frames << frame if frame
|
|
88
|
+
end
|
|
74
89
|
|
|
75
90
|
StacktraceInterface.new(frames: frames)
|
|
76
91
|
end
|
|
@@ -78,14 +93,15 @@ module Sentry
|
|
|
78
93
|
private
|
|
79
94
|
|
|
80
95
|
def convert_parsed_line_into_frame(line)
|
|
81
|
-
frame = StacktraceInterface::Frame.new(project_root, line, strip_backtrace_load_path)
|
|
96
|
+
frame = StacktraceInterface::Frame.new(project_root, line, strip_backtrace_load_path, filename_cache: @filename_cache)
|
|
82
97
|
frame.set_context(linecache, context_lines) if context_lines
|
|
83
98
|
frame
|
|
84
99
|
end
|
|
85
100
|
|
|
86
101
|
def parse_backtrace_lines(backtrace)
|
|
87
102
|
Backtrace.parse(
|
|
88
|
-
backtrace, project_root, app_dirs_pattern,
|
|
103
|
+
backtrace, project_root, app_dirs_pattern,
|
|
104
|
+
in_app_pattern: @in_app_pattern, &backtrace_cleanup_callback
|
|
89
105
|
).lines
|
|
90
106
|
end
|
|
91
107
|
end
|
data/lib/sentry/linecache.rb
CHANGED
|
@@ -12,36 +12,33 @@ module Sentry
|
|
|
12
12
|
# file. The number of lines retrieved is (2 * context) + 1, the middle
|
|
13
13
|
# line should be the line requested by lineno. See specs for more information.
|
|
14
14
|
def get_file_context(filename, lineno, context)
|
|
15
|
-
|
|
15
|
+
lines = getlines(filename)
|
|
16
|
+
return nil, nil, nil unless lines
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
first_line = lineno - context
|
|
19
|
+
pre = Array.new(context) { |i| line_at(lines, first_line + i) }
|
|
20
|
+
context_line = line_at(lines, lineno)
|
|
21
|
+
post = Array.new(context) { |i| line_at(lines, lineno + 1 + i) }
|
|
22
|
+
|
|
23
|
+
[pre, context_line, post]
|
|
21
24
|
end
|
|
22
25
|
|
|
23
26
|
private
|
|
24
27
|
|
|
25
|
-
def
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
def line_at(lines, n)
|
|
29
|
+
return nil if n < 1
|
|
30
|
+
|
|
31
|
+
lines[n - 1]
|
|
28
32
|
end
|
|
29
33
|
|
|
30
34
|
def getlines(path)
|
|
31
|
-
@cache
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
@cache.fetch(path) do
|
|
36
|
+
@cache[path] = begin
|
|
37
|
+
File.open(path, "r", &:readlines)
|
|
38
|
+
rescue
|
|
39
|
+
nil
|
|
40
|
+
end
|
|
35
41
|
end
|
|
36
42
|
end
|
|
37
|
-
|
|
38
|
-
def getline(path, n)
|
|
39
|
-
return nil if n < 1
|
|
40
|
-
|
|
41
|
-
lines = getlines(path)
|
|
42
|
-
return nil if lines.nil?
|
|
43
|
-
|
|
44
|
-
lines[n - 1]
|
|
45
|
-
end
|
|
46
43
|
end
|
|
47
44
|
end
|
data/lib/sentry/metric_event.rb
CHANGED
|
@@ -9,28 +9,8 @@ module Sentry
|
|
|
9
9
|
abs_path.match?(@in_app_pattern)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
# copied from stacktrace.rb since I don't want to touch existing code
|
|
13
|
-
# TODO-neel-profiler try to fetch this from stackprof once we patch
|
|
14
|
-
# the native extension
|
|
15
12
|
def compute_filename(abs_path, in_app)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
under_project_root = @project_root && abs_path.start_with?(@project_root)
|
|
19
|
-
|
|
20
|
-
prefix =
|
|
21
|
-
if under_project_root && in_app
|
|
22
|
-
@project_root
|
|
23
|
-
else
|
|
24
|
-
longest_load_path = $LOAD_PATH.select { |path| abs_path.start_with?(path.to_s) }.max_by(&:size)
|
|
25
|
-
|
|
26
|
-
if under_project_root
|
|
27
|
-
longest_load_path || @project_root
|
|
28
|
-
else
|
|
29
|
-
longest_load_path
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
prefix ? abs_path[prefix.to_s.chomp(File::SEPARATOR).length + 1..-1] : abs_path
|
|
13
|
+
@filename_cache.compute_filename(abs_path, in_app, true)
|
|
34
14
|
end
|
|
35
15
|
|
|
36
16
|
def split_module(name)
|
data/lib/sentry/profiler.rb
CHANGED
|
@@ -26,6 +26,7 @@ module Sentry
|
|
|
26
26
|
@project_root = configuration.project_root
|
|
27
27
|
@app_dirs_pattern = configuration.app_dirs_pattern
|
|
28
28
|
@in_app_pattern = Regexp.new("^(#{@project_root}/)?#{@app_dirs_pattern}")
|
|
29
|
+
@filename_cache = configuration.stacktrace_builder.filename_cache
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
def start
|
|
@@ -53,6 +53,44 @@ module Sentry
|
|
|
53
53
|
[trace_id, parent_span_id, parent_sampled]
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
+
# Determines whether we should continue an incoming trace based on org_id matching
|
|
57
|
+
# and the strict_trace_continuation configuration option.
|
|
58
|
+
#
|
|
59
|
+
# @param incoming_baggage [Baggage] the baggage from the incoming request
|
|
60
|
+
# @return [Boolean]
|
|
61
|
+
def self.should_continue_trace?(incoming_baggage)
|
|
62
|
+
return true unless Sentry.initialized?
|
|
63
|
+
|
|
64
|
+
configuration = Sentry.configuration
|
|
65
|
+
sdk_org_id = configuration.effective_org_id
|
|
66
|
+
baggage_org_id = incoming_baggage.items["org_id"]
|
|
67
|
+
|
|
68
|
+
# Mismatched org IDs always start a new trace regardless of strict mode
|
|
69
|
+
if sdk_org_id && baggage_org_id && sdk_org_id != baggage_org_id
|
|
70
|
+
Sentry.sdk_logger.debug(LOGGER_PROGNAME) do
|
|
71
|
+
"Starting a new trace because org IDs don't match (incoming baggage org_id: #{baggage_org_id}, SDK org_id: #{sdk_org_id})"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
return false
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
return true unless configuration.strict_trace_continuation
|
|
78
|
+
|
|
79
|
+
# In strict mode, both must be present and match (unless both are missing)
|
|
80
|
+
if sdk_org_id.nil? && baggage_org_id.nil?
|
|
81
|
+
true
|
|
82
|
+
elsif sdk_org_id.nil? || baggage_org_id.nil?
|
|
83
|
+
Sentry.sdk_logger.debug(LOGGER_PROGNAME) do
|
|
84
|
+
"Starting a new trace because strict trace continuation is enabled and one org ID is missing " \
|
|
85
|
+
"(incoming baggage org_id: #{baggage_org_id.inspect}, SDK org_id: #{sdk_org_id.inspect})"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
false
|
|
89
|
+
else
|
|
90
|
+
true
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
56
94
|
def self.extract_sample_rand_from_baggage(baggage, trace_id = nil)
|
|
57
95
|
return unless baggage&.items
|
|
58
96
|
|
|
@@ -96,9 +134,7 @@ module Sentry
|
|
|
96
134
|
sentry_trace_data = self.class.extract_sentry_trace(sentry_trace_header)
|
|
97
135
|
|
|
98
136
|
if sentry_trace_data
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
@baggage =
|
|
137
|
+
incoming_baggage =
|
|
102
138
|
if baggage_header && !baggage_header.empty?
|
|
103
139
|
Baggage.from_incoming_header(baggage_header)
|
|
104
140
|
else
|
|
@@ -108,10 +144,13 @@ module Sentry
|
|
|
108
144
|
Baggage.new({})
|
|
109
145
|
end
|
|
110
146
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
147
|
+
if self.class.should_continue_trace?(incoming_baggage)
|
|
148
|
+
@trace_id, @parent_span_id, @parent_sampled = sentry_trace_data
|
|
149
|
+
@baggage = incoming_baggage
|
|
150
|
+
@sample_rand = self.class.extract_sample_rand_from_baggage(@baggage, @trace_id)
|
|
151
|
+
@baggage.freeze!
|
|
152
|
+
@incoming_trace = true
|
|
153
|
+
end
|
|
115
154
|
end
|
|
116
155
|
end
|
|
117
156
|
end
|
|
@@ -162,7 +201,8 @@ module Sentry
|
|
|
162
201
|
"sample_rand" => Utils::SampleRand.format(@sample_rand),
|
|
163
202
|
"environment" => configuration.environment,
|
|
164
203
|
"release" => configuration.release,
|
|
165
|
-
"public_key" => configuration.dsn&.public_key
|
|
204
|
+
"public_key" => configuration.dsn&.public_key,
|
|
205
|
+
"org_id" => configuration.effective_org_id
|
|
166
206
|
}
|
|
167
207
|
|
|
168
208
|
items.compact!
|
|
@@ -6,6 +6,7 @@ module Sentry
|
|
|
6
6
|
class << self
|
|
7
7
|
def detect_release(project_root:, running_on_heroku:)
|
|
8
8
|
detect_release_from_env ||
|
|
9
|
+
detect_release_from_kamal ||
|
|
9
10
|
detect_release_from_git ||
|
|
10
11
|
detect_release_from_capistrano(project_root) ||
|
|
11
12
|
detect_release_from_heroku(running_on_heroku)
|
|
@@ -13,7 +14,7 @@ module Sentry
|
|
|
13
14
|
|
|
14
15
|
def detect_release_from_heroku(running_on_heroku)
|
|
15
16
|
return unless running_on_heroku
|
|
16
|
-
ENV["HEROKU_SLUG_COMMIT"]
|
|
17
|
+
ENV["HEROKU_BUILD_COMMIT"] || ENV["HEROKU_SLUG_COMMIT"]
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
def detect_release_from_capistrano(project_root)
|
|
@@ -31,6 +32,10 @@ module Sentry
|
|
|
31
32
|
Sentry.sys_command("git rev-parse HEAD") if File.directory?(".git")
|
|
32
33
|
end
|
|
33
34
|
|
|
35
|
+
def detect_release_from_kamal
|
|
36
|
+
ENV["KAMAL_VERSION"]
|
|
37
|
+
end
|
|
38
|
+
|
|
34
39
|
def detect_release_from_env
|
|
35
40
|
ENV["SENTRY_RELEASE"]
|
|
36
41
|
end
|
data/lib/sentry/scope.rb
CHANGED
data/lib/sentry/test_helper.rb
CHANGED
|
@@ -37,13 +37,25 @@ module Sentry
|
|
|
37
37
|
# - auto_session_tracking
|
|
38
38
|
block&.call(dummy_config)
|
|
39
39
|
|
|
40
|
+
# Install the testing clients on the *main* hub rather than the current
|
|
41
|
+
# thread's hub. `Sentry.clone_hub_to_current_thread` (used by
|
|
42
|
+
# Sentry::Rack::CaptureExceptions) always clones the main hub, so if we
|
|
43
|
+
# only mutated the thread-local hub a request-time clone would observe a
|
|
44
|
+
# stale transport.
|
|
45
|
+
main_hub = Sentry.get_main_hub
|
|
46
|
+
|
|
40
47
|
# the base layer's client should already use the dummy config so nothing will be sent by accident
|
|
41
48
|
base_client = Sentry::Client.new(dummy_config)
|
|
42
|
-
|
|
49
|
+
main_hub.bind_client(base_client)
|
|
43
50
|
# create a new layer so mutations made to the testing scope or configuration could be simply popped later
|
|
44
|
-
|
|
51
|
+
main_hub.push_scope
|
|
45
52
|
test_client = Sentry::Client.new(dummy_config.dup)
|
|
46
|
-
|
|
53
|
+
main_hub.bind_client(test_client)
|
|
54
|
+
|
|
55
|
+
# Realign the current thread's hub with the main hub so direct
|
|
56
|
+
# `sentry_events` reads and any hub the Rack middleware clones from the
|
|
57
|
+
# main hub all observe the same DummyTransport.
|
|
58
|
+
Thread.current.thread_variable_set(Sentry::THREAD_LOCAL, main_hub)
|
|
47
59
|
end
|
|
48
60
|
|
|
49
61
|
# Clears all stored events and envelopes.
|
|
@@ -54,11 +66,15 @@ module Sentry
|
|
|
54
66
|
|
|
55
67
|
clear_sentry_events
|
|
56
68
|
|
|
57
|
-
# pop testing layer created by `setup_sentry_test`
|
|
58
|
-
#
|
|
69
|
+
# pop the testing layer created by `setup_sentry_test` off the *main*
|
|
70
|
+
# hub (that is where `setup_sentry_test` pushed it), keeping the base
|
|
71
|
+
# layer to avoid nil-pointer errors. Popping the current thread's hub
|
|
72
|
+
# would leave the test layer dangling on the main hub, which the next
|
|
73
|
+
# request-time clone would inherit.
|
|
59
74
|
# TODO: find a way to notify users if they somehow popped the test layer before calling this method
|
|
60
|
-
|
|
61
|
-
|
|
75
|
+
main_hub = Sentry.get_main_hub
|
|
76
|
+
if main_hub.instance_variable_get(:@stack).size > 1
|
|
77
|
+
main_hub.pop_scope
|
|
62
78
|
end
|
|
63
79
|
Sentry::Scope.global_event_processors.clear
|
|
64
80
|
end
|
|
@@ -66,7 +82,13 @@ module Sentry
|
|
|
66
82
|
def clear_sentry_events
|
|
67
83
|
return unless Sentry.initialized?
|
|
68
84
|
|
|
69
|
-
|
|
85
|
+
# Clear every transport reachable from the current thread's hub and the
|
|
86
|
+
# main hub (including its base layer). A request-time clone shares the
|
|
87
|
+
# main hub's base-layer transport, so clearing only the current
|
|
88
|
+
# transport would let stale events survive into the next test.
|
|
89
|
+
sentry_test_transports.each do |transport|
|
|
90
|
+
transport.clear if transport.respond_to?(:clear)
|
|
91
|
+
end
|
|
70
92
|
|
|
71
93
|
if Sentry.configuration.enable_logs && sentry_logger.respond_to?(:clear)
|
|
72
94
|
sentry_logger.clear
|
|
@@ -83,6 +105,17 @@ module Sentry
|
|
|
83
105
|
Sentry.get_current_client.transport
|
|
84
106
|
end
|
|
85
107
|
|
|
108
|
+
# Every transport reachable from the current thread's hub and the main
|
|
109
|
+
# hub, across all stack layers. Used by `clear_sentry_events` so a stale
|
|
110
|
+
# DummyTransport (e.g. the main hub's base layer that a request-time clone
|
|
111
|
+
# shares) cannot carry leftover events into the next test.
|
|
112
|
+
# @return [Array<Transport>]
|
|
113
|
+
def sentry_test_transports
|
|
114
|
+
[Sentry.get_current_hub, Sentry.get_main_hub].compact.uniq.flat_map do |hub|
|
|
115
|
+
hub.clients.map(&:transport)
|
|
116
|
+
end.compact.uniq
|
|
117
|
+
end
|
|
118
|
+
|
|
86
119
|
# Returns the captured event objects.
|
|
87
120
|
# @return [Array<Event>]
|
|
88
121
|
def sentry_events
|
data/lib/sentry/transaction.rb
CHANGED
|
@@ -295,7 +295,8 @@ module Sentry
|
|
|
295
295
|
"sampled" => sampled&.to_s,
|
|
296
296
|
"environment" => configuration&.environment,
|
|
297
297
|
"release" => configuration&.release,
|
|
298
|
-
"public_key" => configuration&.dsn&.public_key
|
|
298
|
+
"public_key" => configuration&.dsn&.public_key,
|
|
299
|
+
"org_id" => configuration&.effective_org_id
|
|
299
300
|
}
|
|
300
301
|
|
|
301
302
|
items["transaction"] = name unless source_low_quality?
|
|
@@ -18,5 +18,12 @@ module Sentry
|
|
|
18
18
|
def send_envelope(envelope)
|
|
19
19
|
@envelopes << envelope
|
|
20
20
|
end
|
|
21
|
+
|
|
22
|
+
# Empties the captured events and envelopes so `TestHelper.clear_sentry_events`
|
|
23
|
+
# also clears the dummy transport instance
|
|
24
|
+
def clear
|
|
25
|
+
@events.clear
|
|
26
|
+
@envelopes.clear
|
|
27
|
+
end
|
|
21
28
|
end
|
|
22
29
|
end
|
|
@@ -49,6 +49,12 @@ module Sentry
|
|
|
49
49
|
|
|
50
50
|
if response.code.match?(/\A2\d{2}/)
|
|
51
51
|
handle_rate_limited_response(response) if has_rate_limited_header?(response)
|
|
52
|
+
elsif response.code == "413"
|
|
53
|
+
error_message = "HTTP 413: Envelope dropped due to exceeded size limit"
|
|
54
|
+
error_message += " (body: #{response.body})" if response.body && !response.body.empty?
|
|
55
|
+
log_warn(error_message)
|
|
56
|
+
|
|
57
|
+
raise Sentry::SizeExceededError, error_message
|
|
52
58
|
elsif response.code == "429"
|
|
53
59
|
log_debug("the server responded with status 429")
|
|
54
60
|
handle_rate_limited_response(response)
|
data/lib/sentry/transport.rb
CHANGED
|
@@ -19,7 +19,8 @@ module Sentry
|
|
|
19
19
|
:before_send,
|
|
20
20
|
:event_processor,
|
|
21
21
|
:insufficient_data,
|
|
22
|
-
:backpressure
|
|
22
|
+
:backpressure,
|
|
23
|
+
:send_error
|
|
23
24
|
]
|
|
24
25
|
|
|
25
26
|
include LoggingHelper
|
|
@@ -61,6 +62,10 @@ module Sentry
|
|
|
61
62
|
log_debug("[Transport] Sending envelope with items [#{serialized_items.map(&:type).join(', ')}] #{envelope.event_id} to Sentry")
|
|
62
63
|
send_data(data)
|
|
63
64
|
end
|
|
65
|
+
rescue Sentry::SizeExceededError
|
|
66
|
+
serialized_items&.each do |item|
|
|
67
|
+
record_lost_event(:send_error, item.data_category)
|
|
68
|
+
end
|
|
64
69
|
end
|
|
65
70
|
|
|
66
71
|
def serialize_envelope(envelope)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sentry
|
|
4
|
+
class FilenameCache
|
|
5
|
+
attr_reader :cache
|
|
6
|
+
|
|
7
|
+
def initialize(project_root)
|
|
8
|
+
@project_root = project_root
|
|
9
|
+
@load_paths = $LOAD_PATH.map(&:to_s).sort_by(&:size).reverse.freeze
|
|
10
|
+
@cache = {}
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def compute_filename(abs_path, in_app, strip_backtrace_load_path)
|
|
14
|
+
return unless abs_path
|
|
15
|
+
return abs_path unless strip_backtrace_load_path
|
|
16
|
+
|
|
17
|
+
@cache.fetch(abs_path) do
|
|
18
|
+
under_root = @project_root && abs_path.start_with?(@project_root)
|
|
19
|
+
prefix =
|
|
20
|
+
if under_root && in_app
|
|
21
|
+
@project_root
|
|
22
|
+
elsif under_root
|
|
23
|
+
longest_load_path(abs_path) || @project_root
|
|
24
|
+
else
|
|
25
|
+
longest_load_path(abs_path)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
@cache[abs_path] = if prefix
|
|
29
|
+
offset = if prefix.end_with?(File::SEPARATOR)
|
|
30
|
+
prefix.bytesize
|
|
31
|
+
else
|
|
32
|
+
prefix.bytesize + 1
|
|
33
|
+
end
|
|
34
|
+
abs_path.byteslice(offset, abs_path.bytesize - offset)
|
|
35
|
+
else
|
|
36
|
+
abs_path
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def longest_load_path(abs_path)
|
|
44
|
+
@load_paths.find { |path| abs_path.start_with?(path) }
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -12,7 +12,13 @@ module Sentry
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def set_propagation_headers(req)
|
|
15
|
-
Sentry.get_trace_propagation_headers&.each
|
|
15
|
+
Sentry.get_trace_propagation_headers&.each do |k, v|
|
|
16
|
+
if k == BAGGAGE_HEADER_NAME && req[k]
|
|
17
|
+
req[k] = "#{v},#{req[k]}"
|
|
18
|
+
else
|
|
19
|
+
req[k] = v
|
|
20
|
+
end
|
|
21
|
+
end
|
|
16
22
|
end
|
|
17
23
|
|
|
18
24
|
def record_sentry_breadcrumb(request_info, response_status)
|
|
@@ -10,11 +10,12 @@ module Sentry
|
|
|
10
10
|
|
|
11
11
|
attr_reader :profile
|
|
12
12
|
|
|
13
|
-
def initialize(profile, project_root:, in_app_pattern:, app_dirs_pattern:)
|
|
13
|
+
def initialize(profile, project_root:, in_app_pattern:, app_dirs_pattern:, filename_cache:)
|
|
14
14
|
@profile = profile
|
|
15
15
|
@project_root = project_root
|
|
16
16
|
@in_app_pattern = in_app_pattern
|
|
17
17
|
@app_dirs_pattern = app_dirs_pattern
|
|
18
|
+
@filename_cache = filename_cache
|
|
18
19
|
end
|
|
19
20
|
|
|
20
21
|
def to_h
|
|
@@ -24,6 +24,7 @@ module Sentry
|
|
|
24
24
|
@project_root = configuration.project_root
|
|
25
25
|
@app_dirs_pattern = configuration.app_dirs_pattern
|
|
26
26
|
@in_app_pattern = Regexp.new("^(#{@project_root}/)?#{@app_dirs_pattern}")
|
|
27
|
+
@filename_cache = configuration.stacktrace_builder.filename_cache
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
def set_initial_sample_decision(transaction_sampled)
|
|
@@ -125,7 +126,8 @@ module Sentry
|
|
|
125
126
|
result,
|
|
126
127
|
project_root: @project_root,
|
|
127
128
|
app_dirs_pattern: @app_dirs_pattern,
|
|
128
|
-
in_app_pattern: @in_app_pattern
|
|
129
|
+
in_app_pattern: @in_app_pattern,
|
|
130
|
+
filename_cache: @filename_cache
|
|
129
131
|
)
|
|
130
132
|
end
|
|
131
133
|
end
|
data/lib/sentry/version.rb
CHANGED
data/lib/sentry-ruby.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.
|
|
4
|
+
version: 6.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sentry Team
|
|
@@ -157,6 +157,7 @@ files:
|
|
|
157
157
|
- lib/sentry/utils/encoding_helper.rb
|
|
158
158
|
- lib/sentry/utils/env_helper.rb
|
|
159
159
|
- lib/sentry/utils/exception_cause_chain.rb
|
|
160
|
+
- lib/sentry/utils/filename_cache.rb
|
|
160
161
|
- lib/sentry/utils/http_tracing.rb
|
|
161
162
|
- lib/sentry/utils/logging_helper.rb
|
|
162
163
|
- lib/sentry/utils/real_ip.rb
|
|
@@ -169,15 +170,15 @@ files:
|
|
|
169
170
|
- lib/sentry/version.rb
|
|
170
171
|
- sentry-ruby-core.gemspec
|
|
171
172
|
- sentry-ruby.gemspec
|
|
172
|
-
homepage: https://github.com/getsentry/sentry-ruby/tree/6.
|
|
173
|
+
homepage: https://github.com/getsentry/sentry-ruby/tree/6.6.0/sentry-ruby
|
|
173
174
|
licenses:
|
|
174
175
|
- MIT
|
|
175
176
|
metadata:
|
|
176
|
-
homepage_uri: https://github.com/getsentry/sentry-ruby/tree/6.
|
|
177
|
-
source_code_uri: https://github.com/getsentry/sentry-ruby/tree/6.
|
|
178
|
-
changelog_uri: https://github.com/getsentry/sentry-ruby/blob/6.
|
|
177
|
+
homepage_uri: https://github.com/getsentry/sentry-ruby/tree/6.6.0/sentry-ruby
|
|
178
|
+
source_code_uri: https://github.com/getsentry/sentry-ruby/tree/6.6.0/sentry-ruby
|
|
179
|
+
changelog_uri: https://github.com/getsentry/sentry-ruby/blob/6.6.0/CHANGELOG.md
|
|
179
180
|
bug_tracker_uri: https://github.com/getsentry/sentry-ruby/issues
|
|
180
|
-
documentation_uri: http://www.rubydoc.info/gems/sentry-ruby/6.
|
|
181
|
+
documentation_uri: http://www.rubydoc.info/gems/sentry-ruby/6.6.0
|
|
181
182
|
rdoc_options: []
|
|
182
183
|
require_paths:
|
|
183
184
|
- lib
|