sentry-ruby 4.1.4 → 4.2.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 +10 -2
- metadata +21 -57
- data/.craft.yml +0 -19
- data/.gitignore +0 -11
- data/.rspec +0 -3
- data/.travis.yml +0 -6
- data/CHANGELOG.md +0 -120
- data/CODE_OF_CONDUCT.md +0 -74
- data/Gemfile +0 -16
- data/Rakefile +0 -8
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/lib/sentry-ruby.rb +0 -190
- data/lib/sentry/background_worker.rb +0 -37
- data/lib/sentry/backtrace.rb +0 -126
- data/lib/sentry/benchmarks/benchmark_transport.rb +0 -14
- data/lib/sentry/breadcrumb.rb +0 -25
- data/lib/sentry/breadcrumb/sentry_logger.rb +0 -87
- data/lib/sentry/breadcrumb_buffer.rb +0 -47
- data/lib/sentry/client.rb +0 -96
- data/lib/sentry/configuration.rb +0 -396
- data/lib/sentry/core_ext/object/deep_dup.rb +0 -57
- data/lib/sentry/core_ext/object/duplicable.rb +0 -153
- data/lib/sentry/dsn.rb +0 -48
- data/lib/sentry/event.rb +0 -171
- data/lib/sentry/hub.rb +0 -143
- data/lib/sentry/integrable.rb +0 -24
- data/lib/sentry/interface.rb +0 -22
- data/lib/sentry/interfaces/exception.rb +0 -11
- data/lib/sentry/interfaces/request.rb +0 -113
- data/lib/sentry/interfaces/single_exception.rb +0 -14
- data/lib/sentry/interfaces/stacktrace.rb +0 -90
- data/lib/sentry/linecache.rb +0 -44
- data/lib/sentry/logger.rb +0 -20
- data/lib/sentry/rack.rb +0 -4
- data/lib/sentry/rack/capture_exceptions.rb +0 -68
- data/lib/sentry/rack/deprecations.rb +0 -19
- data/lib/sentry/rake.rb +0 -17
- data/lib/sentry/scope.rb +0 -210
- data/lib/sentry/span.rb +0 -133
- data/lib/sentry/transaction.rb +0 -157
- data/lib/sentry/transaction_event.rb +0 -29
- data/lib/sentry/transport.rb +0 -88
- data/lib/sentry/transport/configuration.rb +0 -21
- data/lib/sentry/transport/dummy_transport.rb +0 -14
- data/lib/sentry/transport/http_transport.rb +0 -62
- data/lib/sentry/utils/argument_checking_helper.rb +0 -11
- data/lib/sentry/utils/exception_cause_chain.rb +0 -20
- data/lib/sentry/utils/real_ip.rb +0 -70
- data/lib/sentry/utils/request_id.rb +0 -16
- data/lib/sentry/version.rb +0 -3
- data/sentry-ruby.gemspec +0 -27
data/lib/sentry-ruby.rb
DELETED
@@ -1,190 +0,0 @@
|
|
1
|
-
require "forwardable"
|
2
|
-
require "time"
|
3
|
-
|
4
|
-
require "sentry/version"
|
5
|
-
require "sentry/core_ext/object/deep_dup"
|
6
|
-
require "sentry/utils/argument_checking_helper"
|
7
|
-
require "sentry/configuration"
|
8
|
-
require "sentry/logger"
|
9
|
-
require "sentry/event"
|
10
|
-
require "sentry/transaction_event"
|
11
|
-
require "sentry/span"
|
12
|
-
require "sentry/transaction"
|
13
|
-
require "sentry/hub"
|
14
|
-
require "sentry/background_worker"
|
15
|
-
|
16
|
-
def safely_require(lib)
|
17
|
-
begin
|
18
|
-
require lib
|
19
|
-
rescue LoadError
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
safely_require "sentry/rake"
|
24
|
-
safely_require "sentry/rack"
|
25
|
-
|
26
|
-
module Sentry
|
27
|
-
class Error < StandardError
|
28
|
-
end
|
29
|
-
|
30
|
-
META = { "name" => "sentry.ruby", "version" => Sentry::VERSION }.freeze
|
31
|
-
|
32
|
-
LOGGER_PROGNAME = "sentry".freeze
|
33
|
-
|
34
|
-
THREAD_LOCAL = :sentry_hub
|
35
|
-
|
36
|
-
def self.sdk_meta
|
37
|
-
META
|
38
|
-
end
|
39
|
-
|
40
|
-
def self.utc_now
|
41
|
-
Time.now.utc
|
42
|
-
end
|
43
|
-
|
44
|
-
class << self
|
45
|
-
# Returns a hash that contains all the integrations that have been registered to the main SDK.
|
46
|
-
def integrations
|
47
|
-
@integrations ||= {}
|
48
|
-
end
|
49
|
-
|
50
|
-
# Registers the SDK integration with its name and version.
|
51
|
-
def register_integration(name, version)
|
52
|
-
meta = { name: "sentry.ruby.#{name}", version: version }.freeze
|
53
|
-
integrations[name.to_s] = meta
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
class << self
|
58
|
-
extend Forwardable
|
59
|
-
|
60
|
-
def_delegators :get_current_client, :configuration, :send_event
|
61
|
-
def_delegators :get_current_scope, :set_tags, :set_extras, :set_user
|
62
|
-
|
63
|
-
attr_accessor :background_worker
|
64
|
-
|
65
|
-
def init(&block)
|
66
|
-
config = Configuration.new
|
67
|
-
yield(config)
|
68
|
-
client = Client.new(config)
|
69
|
-
scope = Scope.new
|
70
|
-
hub = Hub.new(client, scope)
|
71
|
-
Thread.current[THREAD_LOCAL] = hub
|
72
|
-
@main_hub = hub
|
73
|
-
@background_worker = Sentry::BackgroundWorker.new(config)
|
74
|
-
end
|
75
|
-
|
76
|
-
# Returns the main thread's active hub.
|
77
|
-
def get_main_hub
|
78
|
-
@main_hub
|
79
|
-
end
|
80
|
-
|
81
|
-
# Takes an instance of Sentry::Breadcrumb and stores it to the current active scope.
|
82
|
-
def add_breadcrumb(breadcrumb)
|
83
|
-
get_current_scope.breadcrumbs.record(breadcrumb)
|
84
|
-
end
|
85
|
-
|
86
|
-
# Returns the current active hub.
|
87
|
-
# If the current thread doesn't have an active hub, it will clone the main thread's active hub,
|
88
|
-
# stores it in the current thread, and then returns it.
|
89
|
-
def get_current_hub
|
90
|
-
# we need to assign a hub to the current thread if it doesn't have one yet
|
91
|
-
#
|
92
|
-
# ideally, we should do this proactively whenever a new thread is created
|
93
|
-
# but it's impossible for the SDK to keep track every new thread
|
94
|
-
# so we need to use this rather passive way to make sure the app doesn't crash
|
95
|
-
Thread.current[THREAD_LOCAL] || clone_hub_to_current_thread
|
96
|
-
end
|
97
|
-
|
98
|
-
# Returns the current active client.
|
99
|
-
def get_current_client
|
100
|
-
get_current_hub&.current_client
|
101
|
-
end
|
102
|
-
|
103
|
-
# Returns the current active scope.
|
104
|
-
def get_current_scope
|
105
|
-
get_current_hub&.current_scope
|
106
|
-
end
|
107
|
-
|
108
|
-
# Clones the main thread's active hub and stores it to the current thread.
|
109
|
-
def clone_hub_to_current_thread
|
110
|
-
Thread.current[THREAD_LOCAL] = get_main_hub.clone
|
111
|
-
end
|
112
|
-
|
113
|
-
# Takes a block and yields the current active scope.
|
114
|
-
#
|
115
|
-
# ```ruby
|
116
|
-
# Sentry.configure_scope do |scope|
|
117
|
-
# scope.set_tags(foo: "bar")
|
118
|
-
# end
|
119
|
-
#
|
120
|
-
# Sentry.capture_message("test message") # this event will have tags { foo: "bar" }
|
121
|
-
# ```
|
122
|
-
#
|
123
|
-
def configure_scope(&block)
|
124
|
-
get_current_hub&.configure_scope(&block)
|
125
|
-
end
|
126
|
-
|
127
|
-
# Takes a block and yields a temporary scope.
|
128
|
-
# The temporary scope will inherit all the attributes from the current active scope and replace it to be the active
|
129
|
-
# scope inside the block. For example:
|
130
|
-
#
|
131
|
-
# ```ruby
|
132
|
-
# Sentry.configure_scope do |scope|
|
133
|
-
# scope.set_tags(foo: "bar")
|
134
|
-
# end
|
135
|
-
#
|
136
|
-
# Sentry.capture_message("test message") # this event will have tags { foo: "bar" }
|
137
|
-
#
|
138
|
-
# Sentry.with_scope do |temp_scope|
|
139
|
-
# temp_scope.set_tags(foo: "baz")
|
140
|
-
# Sentry.capture_message("test message 2") # this event will have tags { foo: "baz" }
|
141
|
-
# end
|
142
|
-
#
|
143
|
-
# Sentry.capture_message("test message 3") # this event will have tags { foo: "bar" }
|
144
|
-
# ```
|
145
|
-
#
|
146
|
-
def with_scope(&block)
|
147
|
-
get_current_hub&.with_scope(&block)
|
148
|
-
end
|
149
|
-
|
150
|
-
# Takes an exception and reports it to Sentry via the currently active hub.
|
151
|
-
def capture_exception(exception, **options, &block)
|
152
|
-
get_current_hub&.capture_exception(exception, **options, &block)
|
153
|
-
end
|
154
|
-
|
155
|
-
# Takes a message string and reports it to Sentry via the currently active hub.
|
156
|
-
def capture_message(message, **options, &block)
|
157
|
-
get_current_hub&.capture_message(message, **options, &block)
|
158
|
-
end
|
159
|
-
|
160
|
-
# Takes an instance of Sentry::Event and dispatches it to the currently active hub.
|
161
|
-
def capture_event(event)
|
162
|
-
get_current_hub&.capture_event(event)
|
163
|
-
end
|
164
|
-
|
165
|
-
# Takes or initializes a new Sentry::Transaction and makes a sampling decision for it.
|
166
|
-
def start_transaction(**options)
|
167
|
-
get_current_hub&.start_transaction(**options)
|
168
|
-
end
|
169
|
-
|
170
|
-
# Returns the id of the lastly reported Sentry::Event.
|
171
|
-
def last_event_id
|
172
|
-
get_current_hub&.last_event_id
|
173
|
-
end
|
174
|
-
|
175
|
-
def sys_command(command)
|
176
|
-
result = `#{command} 2>&1` rescue nil
|
177
|
-
return if result.nil? || result.empty? || ($CHILD_STATUS && $CHILD_STATUS.exitstatus != 0)
|
178
|
-
|
179
|
-
result.strip
|
180
|
-
end
|
181
|
-
|
182
|
-
def initialized?
|
183
|
-
!!@main_hub
|
184
|
-
end
|
185
|
-
|
186
|
-
def logger
|
187
|
-
configuration.logger
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
require "concurrent/executor/thread_pool_executor"
|
2
|
-
require "concurrent/executor/immediate_executor"
|
3
|
-
|
4
|
-
module Sentry
|
5
|
-
class BackgroundWorker
|
6
|
-
attr_reader :max_queue, :number_of_threads
|
7
|
-
|
8
|
-
def initialize(configuration)
|
9
|
-
@max_queue = 30
|
10
|
-
@number_of_threads = configuration.background_worker_threads
|
11
|
-
|
12
|
-
@executor =
|
13
|
-
if configuration.async
|
14
|
-
configuration.logger.debug(LOGGER_PROGNAME) { "config.async is set, BackgroundWorker is disabled" }
|
15
|
-
Concurrent::ImmediateExecutor.new
|
16
|
-
elsif @number_of_threads == 0
|
17
|
-
configuration.logger.debug(LOGGER_PROGNAME) { "config.background_worker_threads is set to 0, all events will be sent synchronously" }
|
18
|
-
Concurrent::ImmediateExecutor.new
|
19
|
-
else
|
20
|
-
configuration.logger.debug(LOGGER_PROGNAME) { "initialized a background worker with #{@number_of_threads} threads" }
|
21
|
-
|
22
|
-
Concurrent::ThreadPoolExecutor.new(
|
23
|
-
min_threads: 0,
|
24
|
-
max_threads: @number_of_threads,
|
25
|
-
max_queue: @max_queue,
|
26
|
-
fallback_policy: :discard
|
27
|
-
)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def perform(&block)
|
32
|
-
@executor.post do
|
33
|
-
block.call
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
data/lib/sentry/backtrace.rb
DELETED
@@ -1,126 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
## Inspired by Rails' and Airbrake's backtrace parsers.
|
4
|
-
|
5
|
-
module Sentry
|
6
|
-
# Front end to parsing the backtrace for each notice
|
7
|
-
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 `([^']+)')?$
|
16
|
-
/x.freeze
|
17
|
-
|
18
|
-
# org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
|
19
|
-
JAVA_INPUT_FORMAT = /^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)$/.freeze
|
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)
|
39
|
-
ruby_match = unparsed_line.match(RUBY_INPUT_FORMAT)
|
40
|
-
if ruby_match
|
41
|
-
_, file, number, method = ruby_match.to_a
|
42
|
-
file.sub!(/\.class$/, RB_EXTENSION)
|
43
|
-
module_name = nil
|
44
|
-
else
|
45
|
-
java_match = unparsed_line.match(JAVA_INPUT_FORMAT)
|
46
|
-
_, module_name, method, file, number = java_match.to_a
|
47
|
-
end
|
48
|
-
new(file, number, method, module_name, in_app_pattern)
|
49
|
-
end
|
50
|
-
|
51
|
-
def initialize(file, number, method, module_name, in_app_pattern)
|
52
|
-
@file = file
|
53
|
-
@module_name = module_name
|
54
|
-
@number = number.to_i
|
55
|
-
@method = method
|
56
|
-
@in_app_pattern = in_app_pattern
|
57
|
-
end
|
58
|
-
|
59
|
-
def in_app
|
60
|
-
if file =~ in_app_pattern
|
61
|
-
true
|
62
|
-
else
|
63
|
-
false
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
# Reconstructs the line in a readable fashion
|
68
|
-
def to_s
|
69
|
-
"#{file}:#{number}:in `#{method}'"
|
70
|
-
end
|
71
|
-
|
72
|
-
def ==(other)
|
73
|
-
to_s == other.to_s
|
74
|
-
end
|
75
|
-
|
76
|
-
def inspect
|
77
|
-
"<Line:#{self}>"
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test)/.freeze
|
82
|
-
|
83
|
-
# holder for an Array of Backtrace::Line instances
|
84
|
-
attr_reader :lines
|
85
|
-
|
86
|
-
def self.parse(backtrace, project_root, app_dirs_pattern, &backtrace_cleanup_callback)
|
87
|
-
ruby_lines = backtrace.is_a?(Array) ? backtrace : backtrace.split(/\n\s*/)
|
88
|
-
|
89
|
-
ruby_lines = backtrace_cleanup_callback.call(ruby_lines) if backtrace_cleanup_callback
|
90
|
-
|
91
|
-
in_app_pattern ||= begin
|
92
|
-
Regexp.new("^(#{project_root}/)?#{app_dirs_pattern || APP_DIRS_PATTERN}")
|
93
|
-
end
|
94
|
-
|
95
|
-
lines = ruby_lines.to_a.map do |unparsed_line|
|
96
|
-
Line.parse(unparsed_line, in_app_pattern)
|
97
|
-
end
|
98
|
-
|
99
|
-
new(lines)
|
100
|
-
end
|
101
|
-
|
102
|
-
def initialize(lines)
|
103
|
-
@lines = lines
|
104
|
-
end
|
105
|
-
|
106
|
-
def inspect
|
107
|
-
"<Backtrace: " + lines.map(&:inspect).join(", ") + ">"
|
108
|
-
end
|
109
|
-
|
110
|
-
def to_s
|
111
|
-
content = []
|
112
|
-
lines.each do |line|
|
113
|
-
content << line
|
114
|
-
end
|
115
|
-
content.join("\n")
|
116
|
-
end
|
117
|
-
|
118
|
-
def ==(other)
|
119
|
-
if other.respond_to?(:lines)
|
120
|
-
lines == other.lines
|
121
|
-
else
|
122
|
-
false
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
data/lib/sentry/breadcrumb.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
module Sentry
|
2
|
-
class Breadcrumb
|
3
|
-
attr_accessor :category, :data, :message, :level, :timestamp, :type
|
4
|
-
|
5
|
-
def initialize(category: nil, data: nil, message: nil, timestamp: nil, level: nil, type: nil)
|
6
|
-
@category = category
|
7
|
-
@data = data || {}
|
8
|
-
@level = level
|
9
|
-
@message = message
|
10
|
-
@timestamp = timestamp || Sentry.utc_now.to_i
|
11
|
-
@type = type
|
12
|
-
end
|
13
|
-
|
14
|
-
def to_hash
|
15
|
-
{
|
16
|
-
:category => @category,
|
17
|
-
:data => @data,
|
18
|
-
:level => @level,
|
19
|
-
:message => @message,
|
20
|
-
:timestamp => @timestamp,
|
21
|
-
:type => @type
|
22
|
-
}
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,87 +0,0 @@
|
|
1
|
-
require 'logger'
|
2
|
-
|
3
|
-
module Sentry
|
4
|
-
class Breadcrumb
|
5
|
-
module SentryLogger
|
6
|
-
LEVELS = {
|
7
|
-
::Logger::DEBUG => 'debug',
|
8
|
-
::Logger::INFO => 'info',
|
9
|
-
::Logger::WARN => 'warn',
|
10
|
-
::Logger::ERROR => 'error',
|
11
|
-
::Logger::FATAL => 'fatal'
|
12
|
-
}.freeze
|
13
|
-
|
14
|
-
def add(*args, &block)
|
15
|
-
super
|
16
|
-
add_breadcrumb(*args, &block)
|
17
|
-
end
|
18
|
-
|
19
|
-
def add_breadcrumb(severity, message = nil, progname = nil)
|
20
|
-
# because the breadcrumbs now belongs to different Hub's Scope in different threads
|
21
|
-
# we need to make sure the current thread's Hub has been set before adding breadcrumbs
|
22
|
-
return unless Sentry.get_current_hub
|
23
|
-
|
24
|
-
category = "logger"
|
25
|
-
|
26
|
-
# this is because the nature of Ruby Logger class:
|
27
|
-
#
|
28
|
-
# when given 1 argument, the argument will become both message and progname
|
29
|
-
#
|
30
|
-
# ```
|
31
|
-
# logger.info("foo")
|
32
|
-
# # message == progname == "foo"
|
33
|
-
# ```
|
34
|
-
#
|
35
|
-
# and to specify progname with a different message,
|
36
|
-
# we need to pass the progname as the argument and pass the message as a proc
|
37
|
-
#
|
38
|
-
# ```
|
39
|
-
# logger.info("progname") { "the message" }
|
40
|
-
# ```
|
41
|
-
#
|
42
|
-
# so the condition below is to replicate the similar behavior
|
43
|
-
if message.nil?
|
44
|
-
if block_given?
|
45
|
-
message = yield
|
46
|
-
category = progname
|
47
|
-
else
|
48
|
-
message = progname
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
return if ignored_logger?(progname) || message.empty?
|
53
|
-
|
54
|
-
# some loggers will add leading/trailing space as they (incorrectly, mind you)
|
55
|
-
# think of logging as a shortcut to std{out,err}
|
56
|
-
message = message.to_s.strip
|
57
|
-
|
58
|
-
last_crumb = current_breadcrumbs.peek
|
59
|
-
# try to avoid dupes from logger broadcasts
|
60
|
-
if last_crumb.nil? || last_crumb.message != message
|
61
|
-
level = Sentry::Breadcrumb::SentryLogger::LEVELS.fetch(severity, nil)
|
62
|
-
crumb = Sentry::Breadcrumb.new(
|
63
|
-
level: level,
|
64
|
-
category: category,
|
65
|
-
message: message,
|
66
|
-
type: severity >= 3 ? "error" : level
|
67
|
-
)
|
68
|
-
|
69
|
-
Sentry.add_breadcrumb(crumb)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
private
|
74
|
-
|
75
|
-
def ignored_logger?(progname)
|
76
|
-
progname == LOGGER_PROGNAME ||
|
77
|
-
Sentry.configuration.exclude_loggers.include?(progname)
|
78
|
-
end
|
79
|
-
|
80
|
-
def current_breadcrumbs
|
81
|
-
Sentry.get_current_scope.breadcrumbs
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
::Logger.send(:prepend, Sentry::Breadcrumb::SentryLogger)
|