sentry-ruby 4.1.2 → 4.1.5

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -7
  3. metadata +21 -57
  4. data/.craft.yml +0 -19
  5. data/.gitignore +0 -11
  6. data/.rspec +0 -3
  7. data/.travis.yml +0 -6
  8. data/CHANGELOG.md +0 -102
  9. data/CODE_OF_CONDUCT.md +0 -74
  10. data/Gemfile +0 -16
  11. data/Rakefile +0 -8
  12. data/bin/console +0 -14
  13. data/bin/setup +0 -8
  14. data/lib/sentry-ruby.rb +0 -152
  15. data/lib/sentry/background_worker.rb +0 -37
  16. data/lib/sentry/backtrace.rb +0 -128
  17. data/lib/sentry/benchmarks/benchmark_transport.rb +0 -14
  18. data/lib/sentry/breadcrumb.rb +0 -25
  19. data/lib/sentry/breadcrumb/sentry_logger.rb +0 -87
  20. data/lib/sentry/breadcrumb_buffer.rb +0 -47
  21. data/lib/sentry/client.rb +0 -90
  22. data/lib/sentry/configuration.rb +0 -399
  23. data/lib/sentry/core_ext/object/deep_dup.rb +0 -57
  24. data/lib/sentry/core_ext/object/duplicable.rb +0 -153
  25. data/lib/sentry/dsn.rb +0 -48
  26. data/lib/sentry/event.rb +0 -177
  27. data/lib/sentry/hub.rb +0 -137
  28. data/lib/sentry/integrable.rb +0 -24
  29. data/lib/sentry/interface.rb +0 -22
  30. data/lib/sentry/interfaces/exception.rb +0 -11
  31. data/lib/sentry/interfaces/request.rb +0 -74
  32. data/lib/sentry/interfaces/single_exception.rb +0 -14
  33. data/lib/sentry/interfaces/stacktrace.rb +0 -57
  34. data/lib/sentry/linecache.rb +0 -44
  35. data/lib/sentry/logger.rb +0 -20
  36. data/lib/sentry/rack.rb +0 -5
  37. data/lib/sentry/rack/capture_exceptions.rb +0 -62
  38. data/lib/sentry/rack/deprecations.rb +0 -19
  39. data/lib/sentry/rack/interface.rb +0 -22
  40. data/lib/sentry/rake.rb +0 -17
  41. data/lib/sentry/scope.rb +0 -214
  42. data/lib/sentry/span.rb +0 -132
  43. data/lib/sentry/transaction.rb +0 -157
  44. data/lib/sentry/transaction_event.rb +0 -29
  45. data/lib/sentry/transport.rb +0 -88
  46. data/lib/sentry/transport/configuration.rb +0 -21
  47. data/lib/sentry/transport/dummy_transport.rb +0 -14
  48. data/lib/sentry/transport/http_transport.rb +0 -62
  49. data/lib/sentry/utils/exception_cause_chain.rb +0 -20
  50. data/lib/sentry/utils/real_ip.rb +0 -70
  51. data/lib/sentry/utils/request_id.rb +0 -16
  52. data/lib/sentry/version.rb +0 -3
  53. data/sentry-ruby.gemspec +0 -27
@@ -1,132 +0,0 @@
1
- # frozen_string_literal: true
2
- require "securerandom"
3
-
4
- module Sentry
5
- class Span
6
- STATUS_MAP = {
7
- 400 => "invalid_argument",
8
- 401 => "unauthenticated",
9
- 403 => "permission_denied",
10
- 404 => "not_found",
11
- 409 => "already_exists",
12
- 429 => "resource_exhausted",
13
- 499 => "cancelled",
14
- 500 => "internal_error",
15
- 501 => "unimplemented",
16
- 503 => "unavailable",
17
- 504 => "deadline_exceeded"
18
- }
19
-
20
-
21
- attr_reader :trace_id, :span_id, :parent_span_id, :sampled, :start_timestamp, :timestamp, :description, :op, :status, :tags, :data
22
- attr_accessor :span_recorder
23
-
24
- def initialize(description: nil, op: nil, status: nil, trace_id: nil, parent_span_id: nil, sampled: nil, start_timestamp: nil, timestamp: nil)
25
- @trace_id = trace_id || SecureRandom.uuid.delete("-")
26
- @span_id = SecureRandom.hex(8)
27
- @parent_span_id = parent_span_id
28
- @sampled = sampled
29
- @start_timestamp = start_timestamp || Sentry.utc_now.to_f
30
- @timestamp = timestamp
31
- @description = description
32
- @op = op
33
- @status = status
34
- @data = {}
35
- @tags = {}
36
- end
37
-
38
- def finish
39
- # already finished
40
- return if @timestamp
41
-
42
- @timestamp = Sentry.utc_now.to_f
43
- self
44
- end
45
-
46
- def to_sentry_trace
47
- sampled_flag = ""
48
- sampled_flag = @sampled ? 1 : 0 unless @sampled.nil?
49
-
50
- "#{@trace_id}-#{@span_id}-#{sampled_flag}"
51
- end
52
-
53
- def to_hash
54
- {
55
- trace_id: @trace_id,
56
- span_id: @span_id,
57
- parent_span_id: @parent_span_id,
58
- start_timestamp: @start_timestamp,
59
- timestamp: @timestamp,
60
- description: @description,
61
- op: @op,
62
- status: @status,
63
- tags: @tags,
64
- data: @data
65
- }
66
- end
67
-
68
- def get_trace_context
69
- {
70
- trace_id: @trace_id,
71
- span_id: @span_id,
72
- description: @description,
73
- op: @op,
74
- status: @status
75
- }
76
- end
77
-
78
- def start_child(**options)
79
- options = options.dup.merge(trace_id: @trace_id, parent_span_id: @span_id, sampled: @sampled)
80
- Span.new(**options)
81
- end
82
-
83
- def with_child_span(**options, &block)
84
- child_span = start_child(**options)
85
-
86
- yield(child_span)
87
-
88
- child_span.finish
89
- end
90
-
91
- def deep_dup
92
- dup
93
- end
94
-
95
- def set_op(op)
96
- @op = op
97
- end
98
-
99
- def set_description(description)
100
- @description = description
101
- end
102
-
103
- def set_status(status)
104
- @status = status
105
- end
106
-
107
- def set_timestamp(timestamp)
108
- @timestamp = timestamp
109
- end
110
-
111
- def set_http_status(status_code)
112
- status_code = status_code.to_i
113
- set_data("status_code", status_code)
114
-
115
- status =
116
- if status_code >= 200 && status_code < 299
117
- "ok"
118
- else
119
- STATUS_MAP[status_code]
120
- end
121
- set_status(status)
122
- end
123
-
124
- def set_data(key, value)
125
- @data[key] = value
126
- end
127
-
128
- def set_tag(key, value)
129
- @tags[key] = value
130
- end
131
- end
132
- end
@@ -1,157 +0,0 @@
1
- module Sentry
2
- class Transaction < Span
3
- SENTRY_TRACE_REGEXP = Regexp.new(
4
- "^[ \t]*" + # whitespace
5
- "([0-9a-f]{32})?" + # trace_id
6
- "-?([0-9a-f]{16})?" + # span_id
7
- "-?([01])?" + # sampled
8
- "[ \t]*$" # whitespace
9
- )
10
- UNLABELD_NAME = "<unlabeled transaction>".freeze
11
- MESSAGE_PREFIX = "[Tracing]"
12
-
13
- attr_reader :name, :parent_sampled
14
-
15
- def initialize(name: nil, parent_sampled: nil, **options)
16
- super(**options)
17
-
18
- @name = name
19
- @parent_sampled = parent_sampled
20
- set_span_recorder
21
- end
22
-
23
- def set_span_recorder
24
- @span_recorder = SpanRecorder.new(1000)
25
- @span_recorder.add(self)
26
- end
27
-
28
- def self.from_sentry_trace(sentry_trace, **options)
29
- return unless sentry_trace
30
-
31
- match = SENTRY_TRACE_REGEXP.match(sentry_trace)
32
- trace_id, parent_span_id, sampled_flag = match[1..3]
33
-
34
- sampled = sampled_flag != "0"
35
-
36
- new(trace_id: trace_id, parent_span_id: parent_span_id, parent_sampled: sampled, **options)
37
- end
38
-
39
- def to_hash
40
- hash = super
41
- hash.merge!(name: @name, sampled: @sampled, parent_sampled: @parent_sampled)
42
- hash
43
- end
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
-
69
- def set_initial_sample_desicion(sampling_context = {})
70
- unless Sentry.configuration.tracing_enabled?
71
- @sampled = false
72
- return
73
- end
74
-
75
- return unless @sampled.nil?
76
-
77
- transaction_description = generate_transaction_description
78
-
79
- logger = Sentry.configuration.logger
80
- sample_rate = Sentry.configuration.traces_sample_rate
81
- traces_sampler = Sentry.configuration.traces_sampler
82
-
83
- if traces_sampler.is_a?(Proc)
84
- sampling_context = sampling_context.merge(
85
- parent_sampled: @parent_sampled,
86
- transaction_context: self.to_hash
87
- )
88
-
89
- sample_rate = traces_sampler.call(sampling_context)
90
- end
91
-
92
- unless [true, false].include?(sample_rate) || (sample_rate.is_a?(Float) && sample_rate >= 0.0 && sample_rate <= 1.0)
93
- @sampled = false
94
- logger.warn("#{MESSAGE_PREFIX} Discarding #{transaction_description} because of invalid sample_rate: #{sample_rate}")
95
- return
96
- end
97
-
98
- if sample_rate == 0.0 || sample_rate == false
99
- @sampled = false
100
- logger.debug("#{MESSAGE_PREFIX} Discarding #{transaction_description} because traces_sampler returned 0 or false")
101
- return
102
- end
103
-
104
- if sample_rate == true
105
- @sampled = true
106
- else
107
- @sampled = Random.rand < sample_rate
108
- end
109
-
110
- if @sampled
111
- logger.debug("#{MESSAGE_PREFIX} Starting #{transaction_description}")
112
- else
113
- logger.debug(
114
- "#{MESSAGE_PREFIX} Discarding #{transaction_description} because it's not included in the random sample (sampling rate = #{sample_rate})"
115
- )
116
- end
117
- end
118
-
119
- def finish(hub: nil)
120
- super() # Span#finish doesn't take arguments
121
-
122
- if @name.nil?
123
- @name = UNLABELD_NAME
124
- end
125
-
126
- return unless @sampled
127
-
128
- hub ||= Sentry.get_current_hub
129
- event = hub.current_client.event_from_transaction(self)
130
- hub.capture_event(event)
131
- end
132
-
133
- private
134
-
135
- def generate_transaction_description
136
- result = op.nil? ? "" : "<#{@op}> "
137
- result += "transaction"
138
- result += " <#{@name}>" if @name
139
- result
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
156
- end
157
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sentry
4
- class TransactionEvent < Event
5
- ATTRIBUTES = %i(
6
- event_id level timestamp start_timestamp
7
- release environment server_name modules
8
- user tags contexts extra
9
- transaction platform sdk type
10
- )
11
-
12
- attr_accessor(*ATTRIBUTES)
13
- attr_accessor :spans
14
-
15
- def start_timestamp=(time)
16
- @start_timestamp = time.is_a?(Time) ? time.to_f : time
17
- end
18
-
19
- def type
20
- "transaction"
21
- end
22
-
23
- def to_hash
24
- data = super
25
- data[:spans] = @spans.map(&:to_hash) if @spans
26
- data
27
- end
28
- end
29
- end
@@ -1,88 +0,0 @@
1
- require "json"
2
- require "base64"
3
-
4
- module Sentry
5
- class Transport
6
- PROTOCOL_VERSION = '5'
7
- USER_AGENT = "sentry-ruby/#{Sentry::VERSION}"
8
-
9
- attr_accessor :configuration
10
-
11
- def initialize(configuration)
12
- @configuration = configuration
13
- @transport_configuration = configuration.transport
14
- @dsn = configuration.dsn
15
- end
16
-
17
- def send_data(data, options = {})
18
- raise NotImplementedError
19
- end
20
-
21
- def send_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)
28
-
29
- return nil unless encoded_data
30
-
31
- send_data(encoded_data)
32
-
33
- event
34
- rescue => e
35
- failed_for_exception(e, event)
36
- nil
37
- end
38
-
39
- def generate_auth_header
40
- now = Sentry.utc_now.to_i
41
- fields = {
42
- 'sentry_version' => PROTOCOL_VERSION,
43
- 'sentry_client' => USER_AGENT,
44
- 'sentry_timestamp' => now,
45
- 'sentry_key' => @dsn.public_key
46
- }
47
- fields['sentry_secret'] = @dsn.secret_key if @dsn.secret_key
48
- 'Sentry ' + fields.map { |key, value| "#{key}=#{value}" }.join(', ')
49
- end
50
-
51
- def encode(event_hash)
52
- event_id = event_hash[:event_id] || event_hash['event_id']
53
- event_type = event_hash[:type] || event_hash['type']
54
-
55
- envelope = <<~ENVELOPE
56
- {"event_id":"#{event_id}","dsn":"#{configuration.dsn.to_s}","sdk":#{Sentry.sdk_meta.to_json},"sent_at":"#{Sentry.utc_now.iso8601}"}
57
- {"type":"#{event_type}","content_type":"application/json"}
58
- #{JSON.generate(event_hash)}
59
- ENVELOPE
60
-
61
- envelope
62
- end
63
-
64
- private
65
-
66
- def prepare_encoded_event(event)
67
- # Convert to hash
68
- event_hash = event.to_hash
69
-
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" }
73
- encode(event_hash)
74
- end
75
-
76
- def failed_for_exception(e, event)
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")}" }
78
- log_not_sending(event)
79
- end
80
-
81
- def log_not_sending(event)
82
- configuration.logger.warn(LOGGER_PROGNAME) { "Failed to submit event. Unreported Event: #{Event.get_log_message(event.to_hash)}" }
83
- end
84
- end
85
- end
86
-
87
- require "sentry/transport/dummy_transport"
88
- require "sentry/transport/http_transport"
@@ -1,21 +0,0 @@
1
- module Sentry
2
- class Transport
3
- class Configuration
4
- attr_accessor :timeout, :open_timeout, :proxy, :ssl, :ssl_ca_file, :ssl_verification, :http_adapter, :faraday_builder, :transport_class
5
-
6
- def initialize
7
- @ssl_verification = true
8
- @open_timeout = 1
9
- @timeout = 2
10
- end
11
-
12
- def transport_class=(klass)
13
- unless klass.is_a?(Class)
14
- raise Sentry::Error.new("config.transport.transport_class must a class. got: #{klass.class}")
15
- end
16
-
17
- @transport_class = klass
18
- end
19
- end
20
- end
21
- end
@@ -1,14 +0,0 @@
1
- module Sentry
2
- class DummyTransport < Transport
3
- attr_accessor :events
4
-
5
- def initialize(*)
6
- super
7
- @events = []
8
- end
9
-
10
- def send_event(event)
11
- @events << event
12
- end
13
- end
14
- end
@@ -1,62 +0,0 @@
1
- require 'faraday'
2
-
3
- module Sentry
4
- class HTTPTransport < Transport
5
- CONTENT_TYPE = 'application/json'
6
- attr_reader :conn, :adapter
7
-
8
- def initialize(*args)
9
- super
10
- @adapter = @transport_configuration.http_adapter || Faraday.default_adapter
11
- @conn = set_conn
12
- @endpoint = @dsn.envelope_endpoint
13
- end
14
-
15
- def send_data(data)
16
- conn.post @endpoint do |req|
17
- req.headers['Content-Type'] = CONTENT_TYPE
18
- req.headers['X-Sentry-Auth'] = generate_auth_header
19
- req.body = data
20
- end
21
- rescue Faraday::Error => e
22
- error_info = e.message
23
-
24
- if e.response
25
- error_info += "\nbody: #{e.response[:body]}"
26
- error_info += " Error in headers is: #{e.response[:headers]['x-sentry-error']}" if e.response[:headers]['x-sentry-error']
27
- end
28
-
29
- raise Sentry::Error, error_info
30
- end
31
-
32
- private
33
-
34
- def set_conn
35
- server = @dsn.server
36
-
37
- configuration.logger.debug(LOGGER_PROGNAME) { "Sentry HTTP Transport connecting to #{server}" }
38
-
39
- Faraday.new(server, :ssl => ssl_configuration, :proxy => @transport_configuration.proxy) do |builder|
40
- @transport_configuration.faraday_builder&.call(builder)
41
- builder.response :raise_error
42
- builder.options.merge! faraday_opts
43
- builder.headers[:user_agent] = "sentry-ruby/#{Sentry::VERSION}"
44
- builder.adapter(*adapter)
45
- end
46
- end
47
-
48
- # TODO: deprecate and replace where possible w/Faraday Builder
49
- def faraday_opts
50
- [:timeout, :open_timeout].each_with_object({}) do |opt, memo|
51
- memo[opt] = @transport_configuration.public_send(opt) if @transport_configuration.public_send(opt)
52
- end
53
- end
54
-
55
- def ssl_configuration
56
- (@transport_configuration.ssl || {}).merge(
57
- :verify => @transport_configuration.ssl_verification,
58
- :ca_file => @transport_configuration.ssl_ca_file
59
- )
60
- end
61
- end
62
- end