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.
@@ -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
@@ -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
@@ -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
 
@@ -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
- child_span = Span.new(options)
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
@@ -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
@@ -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, :state
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
- content_type, encoded_data = prepare_encoded_event(event)
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, content_type: content_type)
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
- [CONTENT_TYPE, envelope]
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
- unless @state.should_try?
70
- failed_for_previous_failure(event_hash)
71
- return
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, options = {})
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'] = options[: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(env_hash)
7
+ def self.read_from(env)
8
8
  REQUEST_ID_HEADERS.each do |key|
9
- request_id = env_hash[key]
9
+ request_id = env[key]
10
10
  return request_id if request_id
11
11
  end
12
12
  nil
@@ -1,3 +1,3 @@
1
1
  module Sentry
2
- VERSION = "4.0.0"
2
+ VERSION = "4.1.3"
3
3
  end
@@ -23,4 +23,5 @@ Gem::Specification.new do |spec|
23
23
  spec.require_paths = ["lib"]
24
24
 
25
25
  spec.add_dependency "faraday", ">= 1.0"
26
+ spec.add_dependency "concurrent-ruby", '~> 1.0', '>= 1.0.2'
26
27
  end
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.0.0
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: 2020-12-10 00:00:00.000000000 Z
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/capture_exception.rb
69
- - lib/sentry/rack/tracing.rb
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
@@ -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