sentry-ruby 4.1.2 → 4.1.5

Sign up to get free protection for your applications and to get access to all the features.
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