sentry-ruby 4.0.0 → 4.1.3
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/CHANGELOG.md +78 -0
- data/Gemfile +2 -2
- data/README.md +49 -11
- data/lib/sentry-ruby.rb +40 -18
- data/lib/sentry/background_worker.rb +37 -0
- data/lib/sentry/backtrace.rb +3 -5
- data/lib/sentry/client.rb +26 -10
- data/lib/sentry/configuration.rb +14 -5
- data/lib/sentry/event.rb +27 -33
- data/lib/sentry/hub.rb +7 -7
- data/lib/sentry/integrable.rb +24 -0
- data/lib/sentry/interfaces/request.rb +50 -31
- data/lib/sentry/interfaces/stacktrace.rb +39 -6
- data/lib/sentry/rack.rb +2 -3
- data/lib/sentry/rack/capture_exceptions.rb +62 -0
- data/lib/sentry/rack/deprecations.rb +19 -0
- data/lib/sentry/rake.rb +17 -0
- data/lib/sentry/scope.rb +2 -2
- data/lib/sentry/span.rb +5 -28
- data/lib/sentry/transaction.rb +44 -0
- data/lib/sentry/transport.rb +12 -21
- data/lib/sentry/transport/http_transport.rb +3 -6
- data/lib/sentry/utils/request_id.rb +2 -2
- data/lib/sentry/version.rb +1 -1
- data/sentry-ruby.gemspec +1 -0
- metadata +27 -5
- data/lib/sentry/rack/capture_exception.rb +0 -45
- data/lib/sentry/rack/tracing.rb +0 -39
- data/lib/sentry/transport/state.rb +0 -40
@@ -0,0 +1,19 @@
|
|
1
|
+
module Sentry
|
2
|
+
module Rack
|
3
|
+
class DeprecatedMiddleware
|
4
|
+
def initialize(_)
|
5
|
+
raise Sentry::Error.new <<~MSG
|
6
|
+
|
7
|
+
You're seeing this message because #{self.class} has been replaced by Sentry::Rack::CaptureExceptions.
|
8
|
+
Removing this middleware from your app and upgrading sentry-rails to 4.1.0+ should solve the issue.
|
9
|
+
MSG
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Tracing < DeprecatedMiddleware
|
14
|
+
end
|
15
|
+
|
16
|
+
class CaptureException < DeprecatedMiddleware
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/sentry/rake.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "rake"
|
2
|
+
require "rake/task"
|
3
|
+
|
4
|
+
module Rake
|
5
|
+
class Application
|
6
|
+
alias orig_display_error_messsage display_error_message
|
7
|
+
def display_error_message(ex)
|
8
|
+
Sentry.capture_exception(ex, hint: { background: false }) do |scope|
|
9
|
+
task_name = top_level_tasks.join(' ')
|
10
|
+
scope.set_transaction_name(task_name)
|
11
|
+
scope.set_tag("rake_task", task_name)
|
12
|
+
end if Sentry.initialized?
|
13
|
+
|
14
|
+
orig_display_error_messsage(ex)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/sentry/scope.rb
CHANGED
@@ -29,7 +29,7 @@ module Sentry
|
|
29
29
|
event.level = level
|
30
30
|
event.transaction = transaction_names.last
|
31
31
|
event.breadcrumbs = breadcrumbs
|
32
|
-
event.rack_env = rack_env
|
32
|
+
event.rack_env = rack_env if rack_env
|
33
33
|
|
34
34
|
unless @event_processors.empty?
|
35
35
|
@event_processors.each do |processor_block|
|
@@ -57,7 +57,7 @@ module Sentry
|
|
57
57
|
copy.user = user.deep_dup
|
58
58
|
copy.transaction_names = transaction_names.deep_dup
|
59
59
|
copy.fingerprint = fingerprint.deep_dup
|
60
|
-
copy.span = span
|
60
|
+
copy.span = span.deep_dup
|
61
61
|
copy
|
62
62
|
end
|
63
63
|
|
data/lib/sentry/span.rb
CHANGED
@@ -35,11 +35,6 @@ module Sentry
|
|
35
35
|
@tags = {}
|
36
36
|
end
|
37
37
|
|
38
|
-
def set_span_recorder
|
39
|
-
@span_recorder = SpanRecorder.new(1000)
|
40
|
-
@span_recorder.add(self)
|
41
|
-
end
|
42
|
-
|
43
38
|
def finish
|
44
39
|
# already finished
|
45
40
|
return if @timestamp
|
@@ -82,14 +77,7 @@ module Sentry
|
|
82
77
|
|
83
78
|
def start_child(**options)
|
84
79
|
options = options.dup.merge(trace_id: @trace_id, parent_span_id: @span_id, sampled: @sampled)
|
85
|
-
|
86
|
-
child_span.span_recorder = @span_recorder
|
87
|
-
|
88
|
-
if @span_recorder && @sampled
|
89
|
-
@span_recorder.add(child_span)
|
90
|
-
end
|
91
|
-
|
92
|
-
child_span
|
80
|
+
Span.new(**options)
|
93
81
|
end
|
94
82
|
|
95
83
|
def with_child_span(**options, &block)
|
@@ -100,6 +88,10 @@ module Sentry
|
|
100
88
|
child_span.finish
|
101
89
|
end
|
102
90
|
|
91
|
+
def deep_dup
|
92
|
+
dup
|
93
|
+
end
|
94
|
+
|
103
95
|
def set_op(op)
|
104
96
|
@op = op
|
105
97
|
end
|
@@ -136,20 +128,5 @@ module Sentry
|
|
136
128
|
def set_tag(key, value)
|
137
129
|
@tags[key] = value
|
138
130
|
end
|
139
|
-
|
140
|
-
class SpanRecorder
|
141
|
-
attr_reader :max_length, :spans
|
142
|
-
|
143
|
-
def initialize(max_length)
|
144
|
-
@max_length = max_length
|
145
|
-
@spans = []
|
146
|
-
end
|
147
|
-
|
148
|
-
def add(span)
|
149
|
-
if @spans.count < @max_length
|
150
|
-
@spans << span
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
131
|
end
|
155
132
|
end
|
data/lib/sentry/transaction.rb
CHANGED
@@ -20,6 +20,11 @@ module Sentry
|
|
20
20
|
set_span_recorder
|
21
21
|
end
|
22
22
|
|
23
|
+
def set_span_recorder
|
24
|
+
@span_recorder = SpanRecorder.new(1000)
|
25
|
+
@span_recorder.add(self)
|
26
|
+
end
|
27
|
+
|
23
28
|
def self.from_sentry_trace(sentry_trace, **options)
|
24
29
|
return unless sentry_trace
|
25
30
|
|
@@ -37,6 +42,30 @@ module Sentry
|
|
37
42
|
hash
|
38
43
|
end
|
39
44
|
|
45
|
+
def start_child(**options)
|
46
|
+
child_span = super
|
47
|
+
child_span.span_recorder = @span_recorder
|
48
|
+
|
49
|
+
if @sampled
|
50
|
+
@span_recorder.add(child_span)
|
51
|
+
end
|
52
|
+
|
53
|
+
child_span
|
54
|
+
end
|
55
|
+
|
56
|
+
def deep_dup
|
57
|
+
copy = super
|
58
|
+
copy.set_span_recorder
|
59
|
+
|
60
|
+
@span_recorder.spans.each do |span|
|
61
|
+
# span_recorder's first span is the current span, which should not be added to the copy's spans
|
62
|
+
next if span == self
|
63
|
+
copy.span_recorder.add(span.dup)
|
64
|
+
end
|
65
|
+
|
66
|
+
copy
|
67
|
+
end
|
68
|
+
|
40
69
|
def set_initial_sample_desicion(sampling_context = {})
|
41
70
|
unless Sentry.configuration.tracing_enabled?
|
42
71
|
@sampled = false
|
@@ -109,5 +138,20 @@ module Sentry
|
|
109
138
|
result += " <#{@name}>" if @name
|
110
139
|
result
|
111
140
|
end
|
141
|
+
|
142
|
+
class SpanRecorder
|
143
|
+
attr_reader :max_length, :spans
|
144
|
+
|
145
|
+
def initialize(max_length)
|
146
|
+
@max_length = max_length
|
147
|
+
@spans = []
|
148
|
+
end
|
149
|
+
|
150
|
+
def add(span)
|
151
|
+
if @spans.count < @max_length
|
152
|
+
@spans << span
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
112
156
|
end
|
113
157
|
end
|
data/lib/sentry/transport.rb
CHANGED
@@ -1,20 +1,17 @@
|
|
1
1
|
require "json"
|
2
2
|
require "base64"
|
3
|
-
require "sentry/transport/state"
|
4
3
|
|
5
4
|
module Sentry
|
6
5
|
class Transport
|
7
6
|
PROTOCOL_VERSION = '5'
|
8
7
|
USER_AGENT = "sentry-ruby/#{Sentry::VERSION}"
|
9
|
-
CONTENT_TYPE = 'application/json'
|
10
8
|
|
11
|
-
attr_accessor :configuration
|
9
|
+
attr_accessor :configuration
|
12
10
|
|
13
11
|
def initialize(configuration)
|
14
12
|
@configuration = configuration
|
15
13
|
@transport_configuration = configuration.transport
|
16
14
|
@dsn = configuration.dsn
|
17
|
-
@state = State.new
|
18
15
|
end
|
19
16
|
|
20
17
|
def send_data(data, options = {})
|
@@ -22,13 +19,17 @@ module Sentry
|
|
22
19
|
end
|
23
20
|
|
24
21
|
def send_event(event)
|
25
|
-
|
22
|
+
unless configuration.sending_allowed?
|
23
|
+
configuration.logger.debug(LOGGER_PROGNAME) { "Event not sent: #{configuration.error_messages}" }
|
24
|
+
return
|
25
|
+
end
|
26
|
+
|
27
|
+
encoded_data = prepare_encoded_event(event)
|
26
28
|
|
27
29
|
return nil unless encoded_data
|
28
30
|
|
29
|
-
send_data(encoded_data
|
31
|
+
send_data(encoded_data)
|
30
32
|
|
31
|
-
state.success
|
32
33
|
event
|
33
34
|
rescue => e
|
34
35
|
failed_for_exception(e, event)
|
@@ -57,7 +58,7 @@ module Sentry
|
|
57
58
|
#{JSON.generate(event_hash)}
|
58
59
|
ENVELOPE
|
59
60
|
|
60
|
-
|
61
|
+
envelope
|
61
62
|
end
|
62
63
|
|
63
64
|
private
|
@@ -66,27 +67,17 @@ module Sentry
|
|
66
67
|
# Convert to hash
|
67
68
|
event_hash = event.to_hash
|
68
69
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
event_id = event_hash[:event_id] || event_hash['event_id']
|
75
|
-
configuration.logger.info(LOGGER_PROGNAME) { "Sending event #{event_id} to Sentry" }
|
70
|
+
event_id = event_hash[:event_id] || event_hash["event_id"]
|
71
|
+
event_type = event_hash[:type] || event_hash["type"]
|
72
|
+
configuration.logger.info(LOGGER_PROGNAME) { "Sending #{event_type} #{event_id} to Sentry" }
|
76
73
|
encode(event_hash)
|
77
74
|
end
|
78
75
|
|
79
76
|
def failed_for_exception(e, event)
|
80
|
-
@state.failure
|
81
77
|
configuration.logger.warn(LOGGER_PROGNAME) { "Unable to record event with remote Sentry server (#{e.class} - #{e.message}):\n#{e.backtrace[0..10].join("\n")}" }
|
82
78
|
log_not_sending(event)
|
83
79
|
end
|
84
80
|
|
85
|
-
def failed_for_previous_failure(event)
|
86
|
-
configuration.logger.warn(LOGGER_PROGNAME) { "Not sending event due to previous failure(s)." }
|
87
|
-
log_not_sending(event)
|
88
|
-
end
|
89
|
-
|
90
81
|
def log_not_sending(event)
|
91
82
|
configuration.logger.warn(LOGGER_PROGNAME) { "Failed to submit event. Unreported Event: #{Event.get_log_message(event.to_hash)}" }
|
92
83
|
end
|
@@ -2,6 +2,7 @@ require 'faraday'
|
|
2
2
|
|
3
3
|
module Sentry
|
4
4
|
class HTTPTransport < Transport
|
5
|
+
CONTENT_TYPE = 'application/json'
|
5
6
|
attr_reader :conn, :adapter
|
6
7
|
|
7
8
|
def initialize(*args)
|
@@ -11,13 +12,9 @@ module Sentry
|
|
11
12
|
@endpoint = @dsn.envelope_endpoint
|
12
13
|
end
|
13
14
|
|
14
|
-
def send_data(data
|
15
|
-
unless configuration.sending_allowed?
|
16
|
-
logger.debug(LOGGER_PROGNAME) { "Event not sent: #{configuration.error_messages}" }
|
17
|
-
end
|
18
|
-
|
15
|
+
def send_data(data)
|
19
16
|
conn.post @endpoint do |req|
|
20
|
-
req.headers['Content-Type'] =
|
17
|
+
req.headers['Content-Type'] = CONTENT_TYPE
|
21
18
|
req.headers['X-Sentry-Auth'] = generate_auth_header
|
22
19
|
req.body = data
|
23
20
|
end
|
@@ -4,9 +4,9 @@ module Sentry
|
|
4
4
|
REQUEST_ID_HEADERS = %w(action_dispatch.request_id HTTP_X_REQUEST_ID).freeze
|
5
5
|
|
6
6
|
# Request ID based on ActionDispatch::RequestId
|
7
|
-
def self.read_from(
|
7
|
+
def self.read_from(env)
|
8
8
|
REQUEST_ID_HEADERS.each do |key|
|
9
|
-
request_id =
|
9
|
+
request_id = env[key]
|
10
10
|
return request_id if request_id
|
11
11
|
end
|
12
12
|
nil
|
data/lib/sentry/version.rb
CHANGED
data/sentry-ruby.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sentry-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sentry Team
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -24,6 +24,26 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: concurrent-ruby
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 1.0.2
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '1.0'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.0.2
|
27
47
|
description: A gem that provides a client interface for the Sentry error logger
|
28
48
|
email: accounts@sentry.io
|
29
49
|
executables: []
|
@@ -45,6 +65,7 @@ files:
|
|
45
65
|
- bin/console
|
46
66
|
- bin/setup
|
47
67
|
- lib/sentry-ruby.rb
|
68
|
+
- lib/sentry/background_worker.rb
|
48
69
|
- lib/sentry/backtrace.rb
|
49
70
|
- lib/sentry/benchmarks/benchmark_transport.rb
|
50
71
|
- lib/sentry/breadcrumb.rb
|
@@ -57,6 +78,7 @@ files:
|
|
57
78
|
- lib/sentry/dsn.rb
|
58
79
|
- lib/sentry/event.rb
|
59
80
|
- lib/sentry/hub.rb
|
81
|
+
- lib/sentry/integrable.rb
|
60
82
|
- lib/sentry/interface.rb
|
61
83
|
- lib/sentry/interfaces/exception.rb
|
62
84
|
- lib/sentry/interfaces/request.rb
|
@@ -65,8 +87,9 @@ files:
|
|
65
87
|
- lib/sentry/linecache.rb
|
66
88
|
- lib/sentry/logger.rb
|
67
89
|
- lib/sentry/rack.rb
|
68
|
-
- lib/sentry/rack/
|
69
|
-
- lib/sentry/rack/
|
90
|
+
- lib/sentry/rack/capture_exceptions.rb
|
91
|
+
- lib/sentry/rack/deprecations.rb
|
92
|
+
- lib/sentry/rake.rb
|
70
93
|
- lib/sentry/scope.rb
|
71
94
|
- lib/sentry/span.rb
|
72
95
|
- lib/sentry/transaction.rb
|
@@ -75,7 +98,6 @@ files:
|
|
75
98
|
- lib/sentry/transport/configuration.rb
|
76
99
|
- lib/sentry/transport/dummy_transport.rb
|
77
100
|
- lib/sentry/transport/http_transport.rb
|
78
|
-
- lib/sentry/transport/state.rb
|
79
101
|
- lib/sentry/utils/exception_cause_chain.rb
|
80
102
|
- lib/sentry/utils/real_ip.rb
|
81
103
|
- lib/sentry/utils/request_id.rb
|
@@ -1,45 +0,0 @@
|
|
1
|
-
module Sentry
|
2
|
-
module Rack
|
3
|
-
class CaptureException
|
4
|
-
def initialize(app)
|
5
|
-
@app = app
|
6
|
-
end
|
7
|
-
|
8
|
-
def call(env)
|
9
|
-
# this call clones the main (global) hub
|
10
|
-
# and assigns it to the current thread's Sentry#get_current_hub
|
11
|
-
# it's essential for multi-thread servers (e.g. puma)
|
12
|
-
Sentry.clone_hub_to_current_thread unless Sentry.get_current_hub
|
13
|
-
# this call creates an isolated scope for every request
|
14
|
-
# it's essential for multi-process servers (e.g. unicorn)
|
15
|
-
Sentry.with_scope do |scope|
|
16
|
-
# there could be some breadcrumbs already stored in the top-level scope
|
17
|
-
# and for request information, we don't need those breadcrumbs
|
18
|
-
scope.clear_breadcrumbs
|
19
|
-
env['sentry.client'] = Sentry.get_current_client
|
20
|
-
|
21
|
-
scope.set_transaction_name(env["PATH_INFO"]) if env["PATH_INFO"]
|
22
|
-
scope.set_rack_env(env)
|
23
|
-
|
24
|
-
begin
|
25
|
-
response = @app.call(env)
|
26
|
-
rescue Sentry::Error
|
27
|
-
raise # Don't capture Sentry errors
|
28
|
-
rescue Exception => e
|
29
|
-
Sentry.capture_exception(e)
|
30
|
-
raise
|
31
|
-
end
|
32
|
-
|
33
|
-
exception = collect_exception(env)
|
34
|
-
Sentry.capture_exception(exception) if exception
|
35
|
-
|
36
|
-
response
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def collect_exception(env)
|
41
|
-
env['rack.exception'] || env['sinatra.error']
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
data/lib/sentry/rack/tracing.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
module Sentry
|
2
|
-
module Rack
|
3
|
-
class Tracing
|
4
|
-
def initialize(app)
|
5
|
-
@app = app
|
6
|
-
end
|
7
|
-
|
8
|
-
def call(env)
|
9
|
-
Sentry.clone_hub_to_current_thread unless Sentry.get_current_hub
|
10
|
-
|
11
|
-
if Sentry.configuration.traces_sample_rate.to_f == 0.0
|
12
|
-
return @app.call(env)
|
13
|
-
end
|
14
|
-
|
15
|
-
Sentry.with_scope do |scope|
|
16
|
-
scope.clear_breadcrumbs
|
17
|
-
scope.set_transaction_name(env["PATH_INFO"]) if env["PATH_INFO"]
|
18
|
-
span = Sentry.start_transaction(name: scope.transaction_name, op: "rack.request")
|
19
|
-
scope.set_span(span)
|
20
|
-
|
21
|
-
begin
|
22
|
-
response = @app.call(env)
|
23
|
-
rescue
|
24
|
-
finish_span(span, 500)
|
25
|
-
raise
|
26
|
-
end
|
27
|
-
|
28
|
-
finish_span(span, response[0])
|
29
|
-
response
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def finish_span(span, status_code)
|
34
|
-
span.set_http_status(status_code)
|
35
|
-
span.finish
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|