sentry-ruby 0.3.0 → 4.3.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 +102 -24
- metadata +41 -54
- data/.craft.yml +0 -19
- data/.gitignore +0 -11
- data/.rspec +0 -3
- data/.travis.yml +0 -6
- data/CHANGELOG.md +0 -31
- 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/backtrace.rb +0 -128
- data/lib/sentry/benchmarks/benchmark_transport.rb +0 -14
- data/lib/sentry/breadcrumb/sentry_logger.rb +0 -87
- data/lib/sentry/breadcrumb.rb +0 -25
- data/lib/sentry/breadcrumb_buffer.rb +0 -47
- data/lib/sentry/client.rb +0 -80
- data/lib/sentry/configuration.rb +0 -387
- 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 -177
- data/lib/sentry/hub.rb +0 -137
- data/lib/sentry/interface.rb +0 -22
- data/lib/sentry/interfaces/exception.rb +0 -11
- data/lib/sentry/interfaces/request.rb +0 -95
- data/lib/sentry/interfaces/single_exception.rb +0 -14
- data/lib/sentry/interfaces/stacktrace.rb +0 -57
- data/lib/sentry/linecache.rb +0 -44
- data/lib/sentry/logger.rb +0 -20
- data/lib/sentry/rack/capture_exception.rb +0 -45
- data/lib/sentry/rack/tracing.rb +0 -39
- data/lib/sentry/rack.rb +0 -5
- data/lib/sentry/scope.rb +0 -214
- data/lib/sentry/span.rb +0 -155
- data/lib/sentry/transaction.rb +0 -113
- data/lib/sentry/transaction_event.rb +0 -29
- 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 -65
- data/lib/sentry/transport/state.rb +0 -40
- data/lib/sentry/transport.rb +0 -97
- 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/lib/sentry-ruby.rb +0 -123
- data/sentry-ruby.gemspec +0 -26
data/lib/sentry/backtrace.rb
DELETED
@@ -1,128 +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
|
-
attr_reader :configuration
|
86
|
-
|
87
|
-
def self.parse(backtrace, configuration:)
|
88
|
-
ruby_lines = backtrace.is_a?(Array) ? backtrace : backtrace.split(/\n\s*/)
|
89
|
-
|
90
|
-
ruby_lines = configuration.backtrace_cleanup_callback.call(ruby_lines) if configuration&.backtrace_cleanup_callback
|
91
|
-
|
92
|
-
in_app_pattern ||= begin
|
93
|
-
project_root = configuration.project_root&.to_s
|
94
|
-
Regexp.new("^(#{project_root}/)?#{configuration.app_dirs_pattern || APP_DIRS_PATTERN}")
|
95
|
-
end
|
96
|
-
|
97
|
-
lines = ruby_lines.to_a.map do |unparsed_line|
|
98
|
-
Line.parse(unparsed_line, in_app_pattern)
|
99
|
-
end
|
100
|
-
|
101
|
-
new(lines)
|
102
|
-
end
|
103
|
-
|
104
|
-
def initialize(lines)
|
105
|
-
@lines = lines
|
106
|
-
end
|
107
|
-
|
108
|
-
def inspect
|
109
|
-
"<Backtrace: " + lines.map(&:inspect).join(", ") + ">"
|
110
|
-
end
|
111
|
-
|
112
|
-
def to_s
|
113
|
-
content = []
|
114
|
-
lines.each do |line|
|
115
|
-
content << line
|
116
|
-
end
|
117
|
-
content.join("\n")
|
118
|
-
end
|
119
|
-
|
120
|
-
def ==(other)
|
121
|
-
if other.respond_to?(:lines)
|
122
|
-
lines == other.lines
|
123
|
-
else
|
124
|
-
false
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
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)
|
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,47 +0,0 @@
|
|
1
|
-
require "sentry/breadcrumb"
|
2
|
-
|
3
|
-
module Sentry
|
4
|
-
class BreadcrumbBuffer
|
5
|
-
include Enumerable
|
6
|
-
|
7
|
-
attr_accessor :buffer
|
8
|
-
|
9
|
-
def initialize(size = 100)
|
10
|
-
@buffer = Array.new(size)
|
11
|
-
end
|
12
|
-
|
13
|
-
def record(crumb)
|
14
|
-
yield(crumb) if block_given?
|
15
|
-
@buffer.slice!(0)
|
16
|
-
@buffer << crumb
|
17
|
-
end
|
18
|
-
|
19
|
-
def members
|
20
|
-
@buffer.compact
|
21
|
-
end
|
22
|
-
|
23
|
-
def peek
|
24
|
-
members.last
|
25
|
-
end
|
26
|
-
|
27
|
-
def each(&block)
|
28
|
-
members.each(&block)
|
29
|
-
end
|
30
|
-
|
31
|
-
def empty?
|
32
|
-
members.none?
|
33
|
-
end
|
34
|
-
|
35
|
-
def to_hash
|
36
|
-
{
|
37
|
-
:values => members.map(&:to_hash)
|
38
|
-
}
|
39
|
-
end
|
40
|
-
|
41
|
-
def dup
|
42
|
-
copy = super
|
43
|
-
copy.buffer = buffer.deep_dup
|
44
|
-
copy
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
data/lib/sentry/client.rb
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
require "sentry/transport"
|
2
|
-
|
3
|
-
module Sentry
|
4
|
-
class Client
|
5
|
-
attr_reader :transport, :configuration
|
6
|
-
|
7
|
-
def initialize(configuration)
|
8
|
-
@configuration = configuration
|
9
|
-
|
10
|
-
if transport_class = configuration.transport.transport_class
|
11
|
-
@transport = transport_class.new(configuration)
|
12
|
-
else
|
13
|
-
@transport =
|
14
|
-
case configuration.dsn&.scheme
|
15
|
-
when 'http', 'https'
|
16
|
-
HTTPTransport.new(configuration)
|
17
|
-
else
|
18
|
-
DummyTransport.new(configuration)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def capture_event(event, scope, hint = nil)
|
24
|
-
scope.apply_to_event(event, hint)
|
25
|
-
|
26
|
-
if configuration.async?
|
27
|
-
begin
|
28
|
-
# We have to convert to a JSON-like hash, because background job
|
29
|
-
# processors (esp ActiveJob) may not like weird types in the event hash
|
30
|
-
configuration.async.call(event.to_json_compatible)
|
31
|
-
rescue => e
|
32
|
-
configuration.logger.error(LOGGER_PROGNAME) { "async event sending failed: #{e.message}" }
|
33
|
-
send_event(event, hint)
|
34
|
-
end
|
35
|
-
else
|
36
|
-
send_event(event, hint)
|
37
|
-
end
|
38
|
-
|
39
|
-
event
|
40
|
-
end
|
41
|
-
|
42
|
-
def event_from_exception(exception)
|
43
|
-
return unless @configuration.exception_class_allowed?(exception)
|
44
|
-
|
45
|
-
Event.new(configuration: configuration).tap do |event|
|
46
|
-
event.add_exception_interface(exception)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def event_from_message(message)
|
51
|
-
Event.new(configuration: configuration, message: message)
|
52
|
-
end
|
53
|
-
|
54
|
-
def event_from_transaction(transaction)
|
55
|
-
TransactionEvent.new(configuration: configuration).tap do |event|
|
56
|
-
event.transaction = transaction.name
|
57
|
-
event.contexts.merge!(trace: transaction.get_trace_context)
|
58
|
-
event.timestamp = transaction.timestamp
|
59
|
-
event.start_timestamp = transaction.start_timestamp
|
60
|
-
|
61
|
-
finished_spans = transaction.span_recorder.spans.select { |span| span.timestamp && span != transaction }
|
62
|
-
event.spans = finished_spans.map(&:to_hash)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def send_event(event, hint = nil)
|
67
|
-
return false unless configuration.sending_allowed?
|
68
|
-
|
69
|
-
event = configuration.before_send.call(event, hint) if configuration.before_send
|
70
|
-
if event.nil?
|
71
|
-
configuration.logger.info(LOGGER_PROGNAME) { "Discarded event because before_send returned nil" }
|
72
|
-
return
|
73
|
-
end
|
74
|
-
|
75
|
-
transport.send_event(event)
|
76
|
-
|
77
|
-
event
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|