sentry-ruby 6.7.0 → 7.1.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/gemfiles/ruby-2.7_rack-2_redis-4.gemfile.lock +9 -9
- data/gemfiles/ruby-2.7_rack-3.1_redis-4.gemfile.lock +9 -9
- data/gemfiles/ruby-2.7_rack-3_redis-4.gemfile.lock +9 -9
- data/gemfiles/ruby-3.0_rack-2_redis-4.gemfile.lock +12 -12
- data/gemfiles/ruby-3.0_rack-3.1_redis-4.gemfile.lock +12 -12
- data/gemfiles/ruby-3.0_rack-3_redis-4.gemfile.lock +12 -12
- data/gemfiles/ruby-3.1_rack-2_redis-4.gemfile.lock +24 -24
- data/gemfiles/ruby-3.1_rack-3.1_redis-4.gemfile.lock +24 -24
- data/gemfiles/ruby-3.1_rack-3_redis-4.gemfile.lock +24 -24
- data/gemfiles/ruby-3.2_rack-0_redis-5.gemfile.lock +24 -24
- data/gemfiles/ruby-3.2_rack-2_redis-4.gemfile.lock +26 -26
- data/gemfiles/ruby-3.2_rack-2_redis-5.gemfile.lock +26 -26
- data/gemfiles/ruby-3.2_rack-3.1_redis-4.gemfile.lock +26 -26
- data/gemfiles/ruby-3.2_rack-3_redis-4.gemfile.lock +26 -26
- data/gemfiles/ruby-3.2_rack-3_redis-5.gemfile.lock +26 -26
- data/gemfiles/ruby-3.3_rack-2_redis-4.gemfile.lock +30 -30
- data/gemfiles/ruby-3.3_rack-3.1_redis-4.gemfile.lock +30 -30
- data/gemfiles/ruby-3.3_rack-3.1_redis-5.3.gemfile.lock +30 -30
- data/gemfiles/ruby-3.3_rack-3_redis-4.gemfile.lock +30 -30
- data/gemfiles/ruby-3.4_rack-2_redis-4.gemfile.lock +30 -30
- data/gemfiles/ruby-3.4_rack-3.1_redis-4.gemfile.lock +30 -30
- data/gemfiles/ruby-3.4_rack-3.1_redis-5.3.gemfile.lock +30 -30
- data/gemfiles/ruby-3.4_rack-3_redis-4.gemfile.lock +30 -30
- data/gemfiles/ruby-4.0_rack-2_redis-4.gemfile.lock +30 -30
- data/gemfiles/ruby-4.0_rack-3.1_redis-4.gemfile.lock +30 -30
- data/gemfiles/ruby-4.0_rack-3_redis-4.gemfile.lock +30 -30
- data/gemfiles/ruby-jruby-9.4.14.0_rack-2_redis-4.gemfile.lock +24 -24
- data/gemfiles/ruby-jruby-9.4.14.0_rack-3.1_redis-4.gemfile.lock +24 -24
- data/gemfiles/ruby-jruby-9.4.14.0_rack-3_redis-4.gemfile.lock +24 -24
- data/lib/sentry/backtrace.rb +10 -1
- data/lib/sentry/client.rb +21 -12
- data/lib/sentry/configuration.rb +35 -13
- data/lib/sentry/data_collection/key_value_collection.rb +136 -0
- data/lib/sentry/data_collection.rb +203 -0
- data/lib/sentry/debug_structured_logger.rb +2 -15
- data/lib/sentry/error_event.rb +6 -1
- data/lib/sentry/event.rb +8 -4
- data/lib/sentry/excon/middleware.rb +3 -8
- data/lib/sentry/faraday.rb +7 -5
- data/lib/sentry/hub.rb +11 -4
- data/lib/sentry/integrable.rb +12 -0
- data/lib/sentry/interfaces/exception.rb +8 -2
- data/lib/sentry/interfaces/request.rb +42 -46
- data/lib/sentry/interfaces/single_exception.rb +2 -2
- data/lib/sentry/log_event_buffer.rb +1 -1
- data/lib/sentry/metric_event.rb +4 -2
- data/lib/sentry/metric_event_buffer.rb +1 -1
- data/lib/sentry/metrics.rb +12 -6
- data/lib/sentry/net/http.rb +3 -4
- data/lib/sentry/redis.rb +1 -1
- data/lib/sentry/scope.rb +7 -3
- data/lib/sentry/session_flusher.rb +7 -0
- data/lib/sentry/std_lib_logger.rb +10 -8
- data/lib/sentry/telemetry_event_buffer.rb +57 -31
- data/lib/sentry/test_helper.rb +6 -4
- data/lib/sentry/threaded_periodic_worker.rb +90 -13
- data/lib/sentry/transaction.rb +7 -1
- data/lib/sentry/utils/callback_helper.rb +27 -0
- data/lib/sentry/utils/http_tracing.rb +42 -26
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +7 -18
- metadata +9 -6
|
@@ -4,41 +4,118 @@ module Sentry
|
|
|
4
4
|
class ThreadedPeriodicWorker
|
|
5
5
|
include LoggingHelper
|
|
6
6
|
|
|
7
|
+
# @!visibility private
|
|
8
|
+
attr_reader :thread, :thread_mutex, :idle_condition
|
|
9
|
+
|
|
7
10
|
def initialize(sdk_logger, interval)
|
|
11
|
+
@process_id = Process.pid
|
|
8
12
|
@thread = nil
|
|
9
13
|
@exited = false
|
|
10
14
|
@interval = interval
|
|
11
15
|
@sdk_logger = sdk_logger
|
|
16
|
+
|
|
17
|
+
@thread_mutex = Mutex.new
|
|
18
|
+
@wake_condition = ConditionVariable.new
|
|
19
|
+
@idle_condition = ConditionVariable.new
|
|
20
|
+
|
|
21
|
+
@woken = false
|
|
22
|
+
@running = false
|
|
12
23
|
end
|
|
13
24
|
|
|
14
25
|
def ensure_thread
|
|
15
|
-
|
|
16
|
-
return true if @thread&.alive?
|
|
26
|
+
reset_if_forked
|
|
17
27
|
|
|
18
|
-
@
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
run
|
|
22
|
-
end
|
|
23
|
-
end
|
|
28
|
+
@thread_mutex.synchronize do
|
|
29
|
+
return false if @exited
|
|
30
|
+
return true if @thread&.alive?
|
|
24
31
|
|
|
25
|
-
|
|
32
|
+
@thread = Thread.new { worker_loop }
|
|
33
|
+
|
|
34
|
+
true
|
|
35
|
+
end
|
|
26
36
|
rescue ThreadError
|
|
37
|
+
@thread_mutex.synchronize { @exited = true }
|
|
27
38
|
log_debug("[#{self.class.name}] thread creation failed")
|
|
28
|
-
@exited = true
|
|
29
39
|
false
|
|
30
40
|
end
|
|
31
41
|
|
|
42
|
+
def wake
|
|
43
|
+
@thread_mutex.synchronize do
|
|
44
|
+
next false if @exited
|
|
45
|
+
|
|
46
|
+
@woken = true
|
|
47
|
+
@wake_condition.signal
|
|
48
|
+
true
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def wait_until_idle(timeout = nil)
|
|
53
|
+
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + timeout if timeout
|
|
54
|
+
|
|
55
|
+
@thread_mutex.synchronize do
|
|
56
|
+
while !@exited && (@running || @woken)
|
|
57
|
+
remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC) if deadline
|
|
58
|
+
return false if remaining && remaining <= 0
|
|
59
|
+
|
|
60
|
+
@idle_condition.wait(@thread_mutex, remaining)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
true
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
32
67
|
def kill
|
|
33
|
-
|
|
68
|
+
thread = @thread_mutex.synchronize do
|
|
69
|
+
@exited = true
|
|
70
|
+
@woken = false
|
|
71
|
+
@idle_condition.broadcast
|
|
72
|
+
@thread
|
|
73
|
+
end
|
|
34
74
|
|
|
35
75
|
# Only a started worker has a thread to kill (and to log about).
|
|
36
76
|
# Guarding here keeps a never-started worker's teardown silent, so
|
|
37
77
|
# killing one during test reset can't emit a stray debug line.
|
|
38
|
-
return unless
|
|
78
|
+
return unless thread
|
|
39
79
|
|
|
40
80
|
log_debug("[#{self.class.name}] thread killed")
|
|
41
|
-
|
|
81
|
+
thread.kill
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def reset_if_forked
|
|
87
|
+
return false if @process_id == Process.pid
|
|
88
|
+
|
|
89
|
+
@process_id = Process.pid
|
|
90
|
+
@thread = nil
|
|
91
|
+
@exited = false
|
|
92
|
+
@woken = false
|
|
93
|
+
@running = false
|
|
94
|
+
@thread_mutex = Mutex.new
|
|
95
|
+
@wake_condition = ConditionVariable.new
|
|
96
|
+
@idle_condition = ConditionVariable.new
|
|
97
|
+
true
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def worker_loop
|
|
101
|
+
loop do
|
|
102
|
+
@thread_mutex.synchronize do
|
|
103
|
+
@wake_condition.wait(@thread_mutex, @interval) unless @woken
|
|
104
|
+
@woken = false
|
|
105
|
+
@running = true
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
begin
|
|
109
|
+
run
|
|
110
|
+
rescue Exception => e
|
|
111
|
+
log_error("[#{self.class.name}] run failed", e)
|
|
112
|
+
ensure
|
|
113
|
+
@thread_mutex.synchronize do
|
|
114
|
+
@running = false
|
|
115
|
+
@idle_condition.broadcast
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
42
119
|
end
|
|
43
120
|
end
|
|
44
121
|
end
|
data/lib/sentry/transaction.rb
CHANGED
|
@@ -14,6 +14,7 @@ module Sentry
|
|
|
14
14
|
SOURCES = %i[custom url route view component task]
|
|
15
15
|
|
|
16
16
|
include LoggingHelper
|
|
17
|
+
include CallbackHelper
|
|
17
18
|
|
|
18
19
|
# The name of the transaction.
|
|
19
20
|
# @return [String]
|
|
@@ -142,7 +143,12 @@ module Sentry
|
|
|
142
143
|
|
|
143
144
|
sample_rate =
|
|
144
145
|
if configuration.traces_sampler.is_a?(Proc)
|
|
145
|
-
|
|
146
|
+
safe_dispatch_callback(
|
|
147
|
+
"traces_sampler",
|
|
148
|
+
configuration.traces_sampler,
|
|
149
|
+
[sampling_context],
|
|
150
|
+
fallback: configuration.traces_sample_rate
|
|
151
|
+
)
|
|
146
152
|
elsif !sampling_context[:parent_sampled].nil?
|
|
147
153
|
sampling_context[:parent_sampled]
|
|
148
154
|
else
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sentry
|
|
4
|
+
# @private
|
|
5
|
+
module CallbackHelper
|
|
6
|
+
# @!visibility private
|
|
7
|
+
def safe_dispatch_callback(callback_name, callback, args, fallback: nil)
|
|
8
|
+
callback.call(*args)
|
|
9
|
+
rescue => e
|
|
10
|
+
log_callback_error(callback_name, e)
|
|
11
|
+
fallback
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def log_callback_error(callback_name, exception)
|
|
17
|
+
return unless Sentry.initialized?
|
|
18
|
+
|
|
19
|
+
message = "Error in #{callback_name} callback: #{exception.message}"
|
|
20
|
+
message += "\n#{exception.backtrace.join("\n")}" if Sentry.configuration.debug && exception.backtrace
|
|
21
|
+
|
|
22
|
+
Sentry.sdk_logger.error(LOGGER_PROGNAME) { message }
|
|
23
|
+
rescue StandardError
|
|
24
|
+
# Callback error reporting must not propagate to the application.
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -1,11 +1,39 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "uri"
|
|
4
|
+
|
|
3
5
|
module Sentry
|
|
4
6
|
module Utils
|
|
5
7
|
module HttpTracing
|
|
8
|
+
def filter_query_params(query)
|
|
9
|
+
return nil unless query
|
|
10
|
+
return nil unless query.is_a?(String) || query.is_a?(Hash)
|
|
11
|
+
|
|
12
|
+
query_hash = if query.is_a?(String)
|
|
13
|
+
URI.decode_www_form(query).each_with_object({}) do |(key, value), params|
|
|
14
|
+
params[key] = params.key?(key) ? Array(params[key]) + [value] : value
|
|
15
|
+
end
|
|
16
|
+
else
|
|
17
|
+
query
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
filtered_query_hash = Sentry.configuration.data_collection.url_query_params.filter(query_hash)
|
|
21
|
+
return nil if filtered_query_hash.empty?
|
|
22
|
+
|
|
23
|
+
HttpTracing.format_query(filtered_query_hash)
|
|
24
|
+
rescue
|
|
25
|
+
nil
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.format_query(query)
|
|
29
|
+
query.flat_map do |key, value|
|
|
30
|
+
Array(value).map { |item| "#{key}=#{item}" }
|
|
31
|
+
end.join("&")
|
|
32
|
+
end
|
|
33
|
+
|
|
6
34
|
def set_span_info(sentry_span, request_info, response_status)
|
|
7
35
|
sentry_span.set_description("#{request_info[:method]} #{request_info[:url]}")
|
|
8
|
-
sentry_span.set_data(Span::DataConventions::URL, request_info
|
|
36
|
+
sentry_span.set_data(Span::DataConventions::URL, url_with_query(request_info))
|
|
9
37
|
sentry_span.set_data(Span::DataConventions::HTTP_METHOD, request_info[:method])
|
|
10
38
|
sentry_span.set_data(Span::DataConventions::HTTP_QUERY, request_info[:query]) if request_info[:query]
|
|
11
39
|
sentry_span.set_data(Span::DataConventions::HTTP_STATUS_CODE, response_status)
|
|
@@ -43,37 +71,25 @@ module Sentry
|
|
|
43
71
|
Sentry.configuration.trace_propagation_targets.any? { |target| url.match?(target) }
|
|
44
72
|
end
|
|
45
73
|
|
|
46
|
-
# Kindly borrowed from Rack::Utils
|
|
47
|
-
def build_nested_query(value, prefix = nil)
|
|
48
|
-
case value
|
|
49
|
-
when Array
|
|
50
|
-
value.map { |v|
|
|
51
|
-
build_nested_query(v, "#{prefix}[]")
|
|
52
|
-
}.join("&")
|
|
53
|
-
when Hash
|
|
54
|
-
value.map { |k, v|
|
|
55
|
-
build_nested_query(v, prefix ? "#{prefix}[#{k}]" : k)
|
|
56
|
-
}.delete_if(&:empty?).join("&")
|
|
57
|
-
when nil
|
|
58
|
-
URI.encode_www_form_component(prefix)
|
|
59
|
-
else
|
|
60
|
-
raise ArgumentError, "value must be a Hash" if prefix.nil?
|
|
61
|
-
"#{URI.encode_www_form_component(prefix)}=#{URI.encode_www_form_component(value)}"
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
74
|
|
|
65
75
|
private
|
|
66
76
|
|
|
77
|
+
def url_with_query(request_info)
|
|
78
|
+
return request_info[:url] unless request_info[:query]
|
|
79
|
+
|
|
80
|
+
"#{request_info[:url]}?#{request_info[:query]}"
|
|
81
|
+
end
|
|
82
|
+
|
|
67
83
|
def get_level(status)
|
|
68
84
|
return :info unless status && status.is_a?(Integer)
|
|
69
85
|
|
|
70
|
-
if status >= 500
|
|
71
|
-
|
|
72
|
-
elsif status >= 400
|
|
73
|
-
|
|
74
|
-
else
|
|
75
|
-
|
|
76
|
-
end
|
|
86
|
+
if status >= 500
|
|
87
|
+
:error
|
|
88
|
+
elsif status >= 400
|
|
89
|
+
:warning
|
|
90
|
+
else
|
|
91
|
+
:info
|
|
92
|
+
end
|
|
77
93
|
end
|
|
78
94
|
end
|
|
79
95
|
end
|
data/lib/sentry/version.rb
CHANGED
data/lib/sentry-ruby.rb
CHANGED
|
@@ -10,6 +10,7 @@ require "sentry/core_ext/object/deep_dup"
|
|
|
10
10
|
require "sentry/utils/argument_checking_helper"
|
|
11
11
|
require "sentry/utils/encoding_helper"
|
|
12
12
|
require "sentry/utils/logging_helper"
|
|
13
|
+
require "sentry/utils/callback_helper"
|
|
13
14
|
require "sentry/utils/sample_rand"
|
|
14
15
|
require "sentry/configuration"
|
|
15
16
|
require "sentry/structured_logger"
|
|
@@ -277,7 +278,7 @@ module Sentry
|
|
|
277
278
|
@background_worker = Sentry::BackgroundWorker.new(config)
|
|
278
279
|
@session_flusher = config.session_tracking? ? Sentry::SessionFlusher.new(config, client) : nil
|
|
279
280
|
@backpressure_monitor = config.enable_backpressure_handling ? Sentry::BackpressureMonitor.new(config, client) : nil
|
|
280
|
-
exception_locals_tp.enable if config.
|
|
281
|
+
exception_locals_tp.enable if config.data_collection.collect_stack_frame_variables?
|
|
281
282
|
at_exit { close }
|
|
282
283
|
end
|
|
283
284
|
|
|
@@ -300,8 +301,10 @@ module Sentry
|
|
|
300
301
|
if client = get_current_client
|
|
301
302
|
client.configuration.run_after_close_callbacks
|
|
302
303
|
client.flush
|
|
304
|
+
client.log_event_buffer.kill
|
|
305
|
+
client.metric_event_buffer.kill
|
|
303
306
|
|
|
304
|
-
if client.configuration.
|
|
307
|
+
if client.configuration.data_collection.collect_stack_frame_variables?
|
|
305
308
|
exception_locals_tp.disable
|
|
306
309
|
end
|
|
307
310
|
end
|
|
@@ -527,7 +530,7 @@ module Sentry
|
|
|
527
530
|
# Sentry.capture_log("User logged in", level: :info, user_id: 123)
|
|
528
531
|
#
|
|
529
532
|
# @see https://develop.sentry.dev/sdk/telemetry/logs/ Sentry SDK Telemetry Logs Protocol
|
|
530
|
-
# @return [LogEvent, nil] The created log event or nil if
|
|
533
|
+
# @return [LogEvent, nil] The created log event or nil if Sentry is not initialized
|
|
531
534
|
def capture_log(message, **options)
|
|
532
535
|
return unless initialized?
|
|
533
536
|
get_current_hub.capture_log_event(message, **options)
|
|
@@ -639,14 +642,6 @@ module Sentry
|
|
|
639
642
|
|
|
640
643
|
# Returns the structured logger instance that implements Sentry's SDK telemetry logs protocol.
|
|
641
644
|
#
|
|
642
|
-
# This logger is only available when logs are enabled in the configuration.
|
|
643
|
-
#
|
|
644
|
-
# @example Enable logs in configuration
|
|
645
|
-
# Sentry.init do |config|
|
|
646
|
-
# config.dsn = "YOUR_DSN"
|
|
647
|
-
# config.enable_logs = true
|
|
648
|
-
# end
|
|
649
|
-
#
|
|
650
645
|
# @example Basic usage
|
|
651
646
|
# Sentry.logger.info("User logged in successfully", user_id: 123)
|
|
652
647
|
# Sentry.logger.error("Failed to process payment",
|
|
@@ -656,19 +651,13 @@ module Sentry
|
|
|
656
651
|
#
|
|
657
652
|
# @see https://develop.sentry.dev/sdk/telemetry/logs/ Sentry SDK Telemetry Logs Protocol
|
|
658
653
|
#
|
|
659
|
-
# @return [StructuredLogger] The structured logger instance
|
|
654
|
+
# @return [StructuredLogger] The structured logger instance
|
|
660
655
|
def logger
|
|
661
656
|
@logger ||= configuration.structured_logging.logger_class.new(configuration)
|
|
662
657
|
end
|
|
663
658
|
|
|
664
659
|
# Returns the metrics API for capturing custom metrics.
|
|
665
660
|
#
|
|
666
|
-
# @example Enable metrics
|
|
667
|
-
# Sentry.init do |config|
|
|
668
|
-
# config.dsn = "YOUR_DSN"
|
|
669
|
-
# config.enable_metrics = true
|
|
670
|
-
# end
|
|
671
|
-
#
|
|
672
661
|
# @example Usage
|
|
673
662
|
# Sentry.metrics.count("button.click", 1, attributes: { button_id: "submit" })
|
|
674
663
|
# Sentry.metrics.distribution("response.time", 120.5, unit: "millisecond")
|
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:
|
|
4
|
+
version: 7.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sentry Team
|
|
@@ -125,6 +125,8 @@ files:
|
|
|
125
125
|
- lib/sentry/cron/monitor_check_ins.rb
|
|
126
126
|
- lib/sentry/cron/monitor_config.rb
|
|
127
127
|
- lib/sentry/cron/monitor_schedule.rb
|
|
128
|
+
- lib/sentry/data_collection.rb
|
|
129
|
+
- lib/sentry/data_collection/key_value_collection.rb
|
|
128
130
|
- lib/sentry/debug_structured_logger.rb
|
|
129
131
|
- lib/sentry/dsn.rb
|
|
130
132
|
- lib/sentry/envelope.rb
|
|
@@ -183,6 +185,7 @@ files:
|
|
|
183
185
|
- lib/sentry/transport/http_transport.rb
|
|
184
186
|
- lib/sentry/transport/spotlight_transport.rb
|
|
185
187
|
- lib/sentry/utils/argument_checking_helper.rb
|
|
188
|
+
- lib/sentry/utils/callback_helper.rb
|
|
186
189
|
- lib/sentry/utils/custom_inspection.rb
|
|
187
190
|
- lib/sentry/utils/encoding_helper.rb
|
|
188
191
|
- lib/sentry/utils/env_helper.rb
|
|
@@ -200,15 +203,15 @@ files:
|
|
|
200
203
|
- lib/sentry/version.rb
|
|
201
204
|
- sentry-ruby-core.gemspec
|
|
202
205
|
- sentry-ruby.gemspec
|
|
203
|
-
homepage: https://github.com/getsentry/sentry-ruby/tree/
|
|
206
|
+
homepage: https://github.com/getsentry/sentry-ruby/tree/7.1.0/sentry-ruby
|
|
204
207
|
licenses:
|
|
205
208
|
- MIT
|
|
206
209
|
metadata:
|
|
207
|
-
homepage_uri: https://github.com/getsentry/sentry-ruby/tree/
|
|
208
|
-
source_code_uri: https://github.com/getsentry/sentry-ruby/tree/
|
|
209
|
-
changelog_uri: https://github.com/getsentry/sentry-ruby/blob/
|
|
210
|
+
homepage_uri: https://github.com/getsentry/sentry-ruby/tree/7.1.0/sentry-ruby
|
|
211
|
+
source_code_uri: https://github.com/getsentry/sentry-ruby/tree/7.1.0/sentry-ruby
|
|
212
|
+
changelog_uri: https://github.com/getsentry/sentry-ruby/blob/7.1.0/CHANGELOG.md
|
|
210
213
|
bug_tracker_uri: https://github.com/getsentry/sentry-ruby/issues
|
|
211
|
-
documentation_uri: http://www.rubydoc.info/gems/sentry-ruby/
|
|
214
|
+
documentation_uri: http://www.rubydoc.info/gems/sentry-ruby/7.1.0
|
|
212
215
|
rdoc_options: []
|
|
213
216
|
require_paths:
|
|
214
217
|
- lib
|