sentry-ruby 0.3.0 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +102 -24
  3. metadata +41 -54
  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 -31
  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/backtrace.rb +0 -128
  15. data/lib/sentry/benchmarks/benchmark_transport.rb +0 -14
  16. data/lib/sentry/breadcrumb/sentry_logger.rb +0 -87
  17. data/lib/sentry/breadcrumb.rb +0 -25
  18. data/lib/sentry/breadcrumb_buffer.rb +0 -47
  19. data/lib/sentry/client.rb +0 -80
  20. data/lib/sentry/configuration.rb +0 -387
  21. data/lib/sentry/core_ext/object/deep_dup.rb +0 -57
  22. data/lib/sentry/core_ext/object/duplicable.rb +0 -153
  23. data/lib/sentry/dsn.rb +0 -48
  24. data/lib/sentry/event.rb +0 -177
  25. data/lib/sentry/hub.rb +0 -137
  26. data/lib/sentry/interface.rb +0 -22
  27. data/lib/sentry/interfaces/exception.rb +0 -11
  28. data/lib/sentry/interfaces/request.rb +0 -95
  29. data/lib/sentry/interfaces/single_exception.rb +0 -14
  30. data/lib/sentry/interfaces/stacktrace.rb +0 -57
  31. data/lib/sentry/linecache.rb +0 -44
  32. data/lib/sentry/logger.rb +0 -20
  33. data/lib/sentry/rack/capture_exception.rb +0 -45
  34. data/lib/sentry/rack/tracing.rb +0 -39
  35. data/lib/sentry/rack.rb +0 -5
  36. data/lib/sentry/scope.rb +0 -214
  37. data/lib/sentry/span.rb +0 -155
  38. data/lib/sentry/transaction.rb +0 -113
  39. data/lib/sentry/transaction_event.rb +0 -29
  40. data/lib/sentry/transport/configuration.rb +0 -21
  41. data/lib/sentry/transport/dummy_transport.rb +0 -14
  42. data/lib/sentry/transport/http_transport.rb +0 -65
  43. data/lib/sentry/transport/state.rb +0 -40
  44. data/lib/sentry/transport.rb +0 -97
  45. data/lib/sentry/utils/exception_cause_chain.rb +0 -20
  46. data/lib/sentry/utils/real_ip.rb +0 -70
  47. data/lib/sentry/utils/request_id.rb +0 -16
  48. data/lib/sentry/version.rb +0 -3
  49. data/lib/sentry-ruby.rb +0 -123
  50. data/sentry-ruby.gemspec +0 -26
data/lib/sentry/scope.rb DELETED
@@ -1,214 +0,0 @@
1
- require "sentry/breadcrumb_buffer"
2
- require "etc"
3
-
4
- module Sentry
5
- class Scope
6
- ATTRIBUTES = [:transaction_names, :contexts, :extra, :tags, :user, :level, :breadcrumbs, :fingerprint, :event_processors, :rack_env, :span]
7
-
8
- attr_reader(*ATTRIBUTES)
9
-
10
- def initialize
11
- set_default_value
12
- end
13
-
14
- def clear
15
- set_default_value
16
- end
17
-
18
- def apply_to_event(event, hint = nil)
19
- event.tags = tags.merge(event.tags)
20
- event.user = user.merge(event.user)
21
- event.extra = extra.merge(event.extra)
22
- event.contexts = contexts.merge(event.contexts)
23
-
24
- if span
25
- event.contexts[:trace] = span.get_trace_context
26
- end
27
-
28
- event.fingerprint = fingerprint
29
- event.level = level
30
- event.transaction = transaction_names.last
31
- event.breadcrumbs = breadcrumbs
32
- event.rack_env = rack_env
33
-
34
- unless @event_processors.empty?
35
- @event_processors.each do |processor_block|
36
- event = processor_block.call(event, hint)
37
- end
38
- end
39
-
40
- event
41
- end
42
-
43
- def add_breadcrumb(breadcrumb)
44
- breadcrumbs.record(breadcrumb)
45
- end
46
-
47
- def clear_breadcrumbs
48
- @breadcrumbs = BreadcrumbBuffer.new
49
- end
50
-
51
- def dup
52
- copy = super
53
- copy.breadcrumbs = breadcrumbs.dup
54
- copy.contexts = contexts.deep_dup
55
- copy.extra = extra.deep_dup
56
- copy.tags = tags.deep_dup
57
- copy.user = user.deep_dup
58
- copy.transaction_names = transaction_names.deep_dup
59
- copy.fingerprint = fingerprint.deep_dup
60
- copy.span = span
61
- copy
62
- end
63
-
64
- def update_from_scope(scope)
65
- self.breadcrumbs = scope.breadcrumbs
66
- self.contexts = scope.contexts
67
- self.extra = scope.extra
68
- self.tags = scope.tags
69
- self.user = scope.user
70
- self.transaction_names = scope.transaction_names
71
- self.fingerprint = scope.fingerprint
72
- self.span = scope.span
73
- end
74
-
75
- def update_from_options(
76
- contexts: nil,
77
- extra: nil,
78
- tags: nil,
79
- user: nil,
80
- level: nil,
81
- fingerprint: nil
82
- )
83
- self.contexts.merge!(contexts) if contexts
84
- self.extra.merge!(extra) if extra
85
- self.tags.merge!(tags) if tags
86
- self.user = user if user
87
- self.level = level if level
88
- self.fingerprint = fingerprint if fingerprint
89
- end
90
-
91
- def set_rack_env(env)
92
- env = env || {}
93
- @rack_env = env
94
- end
95
-
96
- def set_span(span)
97
- check_argument_type!(span, Span)
98
- @span = span
99
- end
100
-
101
- def set_user(user_hash)
102
- check_argument_type!(user_hash, Hash)
103
- @user = user_hash
104
- end
105
-
106
- def set_extras(extras_hash)
107
- check_argument_type!(extras_hash, Hash)
108
- @extra.merge!(extras_hash)
109
- end
110
-
111
- def set_extra(key, value)
112
- @extra.merge!(key => value)
113
- end
114
-
115
- def set_tags(tags_hash)
116
- check_argument_type!(tags_hash, Hash)
117
- @tags.merge!(tags_hash)
118
- end
119
-
120
- def set_tag(key, value)
121
- @tags.merge!(key => value)
122
- end
123
-
124
- def set_contexts(contexts_hash)
125
- check_argument_type!(contexts_hash, Hash)
126
- @contexts = contexts_hash
127
- end
128
-
129
- def set_context(key, value)
130
- @contexts.merge!(key => value)
131
- end
132
-
133
- def set_level(level)
134
- @level = level
135
- end
136
-
137
- def set_transaction_name(transaction_name)
138
- @transaction_names << transaction_name
139
- end
140
-
141
- def transaction_name
142
- @transaction_names.last
143
- end
144
-
145
- def get_transaction
146
- # transaction will always be the first in the span_recorder
147
- span.span_recorder.spans.first if span
148
- end
149
-
150
- def get_span
151
- span
152
- end
153
-
154
- def set_fingerprint(fingerprint)
155
- check_argument_type!(fingerprint, Array)
156
-
157
- @fingerprint = fingerprint
158
- end
159
-
160
- def add_event_processor(&block)
161
- @event_processors << block
162
- end
163
-
164
- protected
165
-
166
- # for duplicating scopes internally
167
- attr_writer(*ATTRIBUTES)
168
-
169
- private
170
-
171
- def check_argument_type!(argument, expected_type)
172
- unless argument.is_a?(expected_type)
173
- raise ArgumentError, "expect the argument to be a #{expected_type}, got #{argument.class} (#{argument})"
174
- end
175
- end
176
-
177
- def set_default_value
178
- @breadcrumbs = BreadcrumbBuffer.new
179
- @contexts = { :os => self.class.os_context, :runtime => self.class.runtime_context }
180
- @extra = {}
181
- @tags = {}
182
- @user = {}
183
- @level = :error
184
- @fingerprint = []
185
- @transaction_names = []
186
- @event_processors = []
187
- @rack_env = {}
188
- @span = nil
189
- end
190
-
191
- class << self
192
- def os_context
193
- @os_context ||=
194
- begin
195
- uname = Etc.uname
196
- {
197
- name: uname[:sysname] || RbConfig::CONFIG["host_os"],
198
- version: uname[:version],
199
- build: uname[:release],
200
- kernel_version: uname[:version]
201
- }
202
- end
203
- end
204
-
205
- def runtime_context
206
- @runtime_context ||= {
207
- name: RbConfig::CONFIG["ruby_install_name"],
208
- version: RUBY_DESCRIPTION || Sentry.sys_command("ruby -v")
209
- }
210
- end
211
- end
212
-
213
- end
214
- end
data/lib/sentry/span.rb DELETED
@@ -1,155 +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 set_span_recorder
39
- @span_recorder = SpanRecorder.new(1000)
40
- @span_recorder.add(self)
41
- end
42
-
43
- def finish
44
- # already finished
45
- return if @timestamp
46
-
47
- @timestamp = Sentry.utc_now.to_f
48
- self
49
- end
50
-
51
- def to_sentry_trace
52
- sampled_flag = ""
53
- sampled_flag = @sampled ? 1 : 0 unless @sampled.nil?
54
-
55
- "#{@trace_id}-#{@span_id}-#{sampled_flag}"
56
- end
57
-
58
- def to_hash
59
- {
60
- trace_id: @trace_id,
61
- span_id: @span_id,
62
- parent_span_id: @parent_span_id,
63
- start_timestamp: @start_timestamp,
64
- timestamp: @timestamp,
65
- description: @description,
66
- op: @op,
67
- status: @status,
68
- tags: @tags,
69
- data: @data
70
- }
71
- end
72
-
73
- def get_trace_context
74
- {
75
- trace_id: @trace_id,
76
- span_id: @span_id,
77
- description: @description,
78
- op: @op,
79
- status: @status
80
- }
81
- end
82
-
83
- def start_child(**options)
84
- 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
93
- end
94
-
95
- def with_child_span(**options, &block)
96
- child_span = start_child(**options)
97
-
98
- yield(child_span)
99
-
100
- child_span.finish
101
- end
102
-
103
- def set_op(op)
104
- @op = op
105
- end
106
-
107
- def set_description(description)
108
- @description = description
109
- end
110
-
111
- def set_status(status)
112
- @status = status
113
- end
114
-
115
- def set_timestamp(timestamp)
116
- @timestamp = timestamp
117
- end
118
-
119
- def set_http_status(status_code)
120
- status_code = status_code.to_i
121
- set_data("status_code", status_code)
122
-
123
- status =
124
- if status_code >= 200 && status_code < 299
125
- "ok"
126
- else
127
- STATUS_MAP[status_code]
128
- end
129
- set_status(status)
130
- end
131
-
132
- def set_data(key, value)
133
- @data[key] = value
134
- end
135
-
136
- def set_tag(key, value)
137
- @tags[key] = value
138
- 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
- end
155
- end
@@ -1,113 +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 self.from_sentry_trace(sentry_trace, **options)
24
- return unless sentry_trace
25
-
26
- match = SENTRY_TRACE_REGEXP.match(sentry_trace)
27
- trace_id, parent_span_id, sampled_flag = match[1..3]
28
-
29
- sampled = sampled_flag != "0"
30
-
31
- new(trace_id: trace_id, parent_span_id: parent_span_id, parent_sampled: sampled, **options)
32
- end
33
-
34
- def to_hash
35
- hash = super
36
- hash.merge!(name: @name, sampled: @sampled, parent_sampled: @parent_sampled)
37
- hash
38
- end
39
-
40
- def set_initial_sample_desicion(sampling_context = {})
41
- unless Sentry.configuration.tracing_enabled?
42
- @sampled = false
43
- return
44
- end
45
-
46
- return unless @sampled.nil?
47
-
48
- transaction_description = generate_transaction_description
49
-
50
- logger = Sentry.configuration.logger
51
- sample_rate = Sentry.configuration.traces_sample_rate
52
- traces_sampler = Sentry.configuration.traces_sampler
53
-
54
- if traces_sampler.is_a?(Proc)
55
- sampling_context = sampling_context.merge(
56
- parent_sampled: @parent_sampled,
57
- transaction_context: self.to_hash
58
- )
59
-
60
- sample_rate = traces_sampler.call(sampling_context)
61
- end
62
-
63
- unless [true, false].include?(sample_rate) || (sample_rate.is_a?(Float) && sample_rate >= 0.0 && sample_rate <= 1.0)
64
- @sampled = false
65
- logger.warn("#{MESSAGE_PREFIX} Discarding #{transaction_description} because of invalid sample_rate: #{sample_rate}")
66
- return
67
- end
68
-
69
- if sample_rate == 0.0 || sample_rate == false
70
- @sampled = false
71
- logger.debug("#{MESSAGE_PREFIX} Discarding #{transaction_description} because traces_sampler returned 0 or false")
72
- return
73
- end
74
-
75
- if sample_rate == true
76
- @sampled = true
77
- else
78
- @sampled = Random.rand < sample_rate
79
- end
80
-
81
- if @sampled
82
- logger.debug("#{MESSAGE_PREFIX} Starting #{transaction_description}")
83
- else
84
- logger.debug(
85
- "#{MESSAGE_PREFIX} Discarding #{transaction_description} because it's not included in the random sample (sampling rate = #{sample_rate})"
86
- )
87
- end
88
- end
89
-
90
- def finish(hub: nil)
91
- super() # Span#finish doesn't take arguments
92
-
93
- if @name.nil?
94
- @name = UNLABELD_NAME
95
- end
96
-
97
- return unless @sampled
98
-
99
- hub ||= Sentry.get_current_hub
100
- event = hub.current_client.event_from_transaction(self)
101
- hub.capture_event(event)
102
- end
103
-
104
- private
105
-
106
- def generate_transaction_description
107
- result = op.nil? ? "" : "<#{@op}> "
108
- result += "transaction"
109
- result += " <#{@name}>" if @name
110
- result
111
- end
112
- end
113
- 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,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,65 +0,0 @@
1
- require 'faraday'
2
-
3
- module Sentry
4
- class HTTPTransport < Transport
5
- attr_reader :conn, :adapter
6
-
7
- def initialize(*args)
8
- super
9
- @adapter = @transport_configuration.http_adapter || Faraday.default_adapter
10
- @conn = set_conn
11
- @endpoint = @dsn.envelope_endpoint
12
- end
13
-
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
-
19
- conn.post @endpoint do |req|
20
- req.headers['Content-Type'] = options[:content_type]
21
- req.headers['X-Sentry-Auth'] = generate_auth_header
22
- req.body = data
23
- end
24
- rescue Faraday::Error => e
25
- error_info = e.message
26
-
27
- if e.response
28
- error_info += "\nbody: #{e.response[:body]}"
29
- error_info += " Error in headers is: #{e.response[:headers]['x-sentry-error']}" if e.response[:headers]['x-sentry-error']
30
- end
31
-
32
- raise Sentry::Error, error_info
33
- end
34
-
35
- private
36
-
37
- def set_conn
38
- server = @dsn.server
39
-
40
- configuration.logger.debug(LOGGER_PROGNAME) { "Sentry HTTP Transport connecting to #{server}" }
41
-
42
- Faraday.new(server, :ssl => ssl_configuration, :proxy => @transport_configuration.proxy) do |builder|
43
- @transport_configuration.faraday_builder&.call(builder)
44
- builder.response :raise_error
45
- builder.options.merge! faraday_opts
46
- builder.headers[:user_agent] = "sentry-ruby/#{Sentry::VERSION}"
47
- builder.adapter(*adapter)
48
- end
49
- end
50
-
51
- # TODO: deprecate and replace where possible w/Faraday Builder
52
- def faraday_opts
53
- [:timeout, :open_timeout].each_with_object({}) do |opt, memo|
54
- memo[opt] = @transport_configuration.public_send(opt) if @transport_configuration.public_send(opt)
55
- end
56
- end
57
-
58
- def ssl_configuration
59
- (@transport_configuration.ssl || {}).merge(
60
- :verify => @transport_configuration.ssl_verification,
61
- :ca_file => @transport_configuration.ssl_ca_file
62
- )
63
- end
64
- end
65
- end
@@ -1,40 +0,0 @@
1
- module Sentry
2
- class Transport
3
- class State
4
- def initialize
5
- reset
6
- end
7
-
8
- def should_try?
9
- return true if @status == :online
10
-
11
- interval = @retry_after || [@retry_number, 6].min**2
12
- return true if Sentry.utc_now - @last_check >= interval
13
-
14
- false
15
- end
16
-
17
- def failure(retry_after = nil)
18
- @status = :error
19
- @retry_number += 1
20
- @last_check = Sentry.utc_now
21
- @retry_after = retry_after
22
- end
23
-
24
- def success
25
- reset
26
- end
27
-
28
- def reset
29
- @status = :online
30
- @retry_number = 0
31
- @last_check = nil
32
- @retry_after = nil
33
- end
34
-
35
- def failed?
36
- @status == :error
37
- end
38
- end
39
- end
40
- end