sentry-ruby 0.3.0 → 4.2.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 -14
  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
@@ -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
@@ -1,97 +0,0 @@
1
- require "json"
2
- require "base64"
3
- require "sentry/transport/state"
4
-
5
- module Sentry
6
- class Transport
7
- PROTOCOL_VERSION = '5'
8
- USER_AGENT = "sentry-ruby/#{Sentry::VERSION}"
9
- CONTENT_TYPE = 'application/json'
10
-
11
- attr_accessor :configuration, :state
12
-
13
- def initialize(configuration)
14
- @configuration = configuration
15
- @transport_configuration = configuration.transport
16
- @dsn = configuration.dsn
17
- @state = State.new
18
- end
19
-
20
- def send_data(data, options = {})
21
- raise NotImplementedError
22
- end
23
-
24
- def send_event(event)
25
- content_type, encoded_data = prepare_encoded_event(event)
26
-
27
- return nil unless encoded_data
28
-
29
- send_data(encoded_data, content_type: content_type)
30
-
31
- state.success
32
- event
33
- rescue => e
34
- failed_for_exception(e, event)
35
- nil
36
- end
37
-
38
- def generate_auth_header
39
- now = Sentry.utc_now.to_i
40
- fields = {
41
- 'sentry_version' => PROTOCOL_VERSION,
42
- 'sentry_client' => USER_AGENT,
43
- 'sentry_timestamp' => now,
44
- 'sentry_key' => @dsn.public_key
45
- }
46
- fields['sentry_secret'] = @dsn.secret_key if @dsn.secret_key
47
- 'Sentry ' + fields.map { |key, value| "#{key}=#{value}" }.join(', ')
48
- end
49
-
50
- def encode(event_hash)
51
- event_id = event_hash[:event_id] || event_hash['event_id']
52
- event_type = event_hash[:type] || event_hash['type']
53
-
54
- envelope = <<~ENVELOPE
55
- {"event_id":"#{event_id}","dsn":"#{configuration.dsn.to_s}","sdk":#{Sentry.sdk_meta.to_json},"sent_at":"#{Sentry.utc_now.iso8601}"}
56
- {"type":"#{event_type}","content_type":"application/json"}
57
- #{JSON.generate(event_hash)}
58
- ENVELOPE
59
-
60
- [CONTENT_TYPE, envelope]
61
- end
62
-
63
- private
64
-
65
- def prepare_encoded_event(event)
66
- # Convert to hash
67
- event_hash = event.to_hash
68
-
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" }
76
- encode(event_hash)
77
- end
78
-
79
- def failed_for_exception(e, event)
80
- @state.failure
81
- 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
- log_not_sending(event)
83
- end
84
-
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
- def log_not_sending(event)
91
- configuration.logger.warn(LOGGER_PROGNAME) { "Failed to submit event. Unreported Event: #{Event.get_log_message(event.to_hash)}" }
92
- end
93
- end
94
- end
95
-
96
- require "sentry/transport/dummy_transport"
97
- require "sentry/transport/http_transport"
@@ -1,20 +0,0 @@
1
- module Sentry
2
- module Utils
3
- module ExceptionCauseChain
4
- def self.exception_to_array(exception)
5
- if exception.respond_to?(:cause) && exception.cause
6
- exceptions = [exception]
7
- while exception.cause
8
- exception = exception.cause
9
- break if exceptions.any? { |e| e.object_id == exception.object_id }
10
-
11
- exceptions << exception
12
- end
13
- exceptions
14
- else
15
- [exception]
16
- end
17
- end
18
- end
19
- end
20
- end
@@ -1,70 +0,0 @@
1
- require 'ipaddr'
2
-
3
- # Based on ActionDispatch::RemoteIp. All security-related precautions from that
4
- # middleware have been removed, because the Event IP just needs to be accurate,
5
- # and spoofing an IP here only makes data inaccurate, not insecure. Don't re-use
6
- # this module if you have to *trust* the IP address.
7
- module Sentry
8
- module Utils
9
- class RealIp
10
- LOCAL_ADDRESSES = [
11
- "127.0.0.1", # localhost IPv4
12
- "::1", # localhost IPv6
13
- "fc00::/7", # private IPv6 range fc00::/7
14
- "10.0.0.0/8", # private IPv4 range 10.x.x.x
15
- "172.16.0.0/12", # private IPv4 range 172.16.0.0 .. 172.31.255.255
16
- "192.168.0.0/16" # private IPv4 range 192.168.x.x
17
- ].map { |proxy| IPAddr.new(proxy) }
18
-
19
- attr_reader :ip
20
-
21
- def initialize(
22
- remote_addr: nil,
23
- client_ip: nil,
24
- real_ip: nil,
25
- forwarded_for: nil
26
- )
27
- @remote_addr = remote_addr
28
- @client_ip = client_ip
29
- @real_ip = real_ip
30
- @forwarded_for = forwarded_for
31
- end
32
-
33
- def calculate_ip
34
- # CGI environment variable set by Rack
35
- remote_addr = ips_from(@remote_addr).last
36
-
37
- # Could be a CSV list and/or repeated headers that were concatenated.
38
- client_ips = ips_from(@client_ip)
39
- real_ips = ips_from(@real_ip)
40
- forwarded_ips = ips_from(@forwarded_for)
41
-
42
- ips = [client_ips, real_ips, forwarded_ips, remote_addr].flatten.compact
43
-
44
- # If every single IP option is in the trusted list, just return REMOTE_ADDR
45
- @ip = filter_local_addresses(ips).first || remote_addr
46
- end
47
-
48
- protected
49
-
50
- def ips_from(header)
51
- # Split the comma-separated list into an array of strings
52
- ips = header ? header.strip.split(/[,\s]+/) : []
53
- ips.select do |ip|
54
- begin
55
- # Only return IPs that are valid according to the IPAddr#new method
56
- range = IPAddr.new(ip).to_range
57
- # we want to make sure nobody is sneaking a netmask in
58
- range.begin == range.end
59
- rescue ArgumentError
60
- nil
61
- end
62
- end
63
- end
64
-
65
- def filter_local_addresses(ips)
66
- ips.reject { |ip| LOCAL_ADDRESSES.any? { |proxy| proxy === ip } }
67
- end
68
- end
69
- end
70
- end
@@ -1,16 +0,0 @@
1
- module Sentry
2
- module Utils
3
- module RequestId
4
- REQUEST_ID_HEADERS = %w(action_dispatch.request_id HTTP_X_REQUEST_ID).freeze
5
-
6
- # Request ID based on ActionDispatch::RequestId
7
- def self.read_from(env_hash)
8
- REQUEST_ID_HEADERS.each do |key|
9
- request_id = env_hash[key]
10
- return request_id if request_id
11
- end
12
- nil
13
- end
14
- end
15
- end
16
- end
@@ -1,3 +0,0 @@
1
- module Sentry
2
- VERSION = "0.3.0"
3
- end
data/lib/sentry-ruby.rb DELETED
@@ -1,123 +0,0 @@
1
- require "forwardable"
2
-
3
- require "sentry/version"
4
- require "sentry/core_ext/object/deep_dup"
5
- require "sentry/configuration"
6
- require "sentry/logger"
7
- require "sentry/event"
8
- require "sentry/transaction_event"
9
- require "sentry/span"
10
- require "sentry/transaction"
11
- require "sentry/hub"
12
- require "sentry/rack"
13
-
14
- module Sentry
15
- class Error < StandardError
16
- end
17
-
18
- META = { "name" => "sentry.ruby", "version" => Sentry::VERSION }.freeze
19
-
20
- LOGGER_PROGNAME = "sentry".freeze
21
-
22
- THREAD_LOCAL = :sentry_hub
23
-
24
- def self.sdk_meta
25
- META
26
- end
27
-
28
- def self.utc_now
29
- Time.now.utc
30
- end
31
-
32
- class << self
33
- extend Forwardable
34
-
35
- def_delegators :get_current_scope, :set_tags, :set_extras, :set_user
36
-
37
- def init(&block)
38
- config = Configuration.new
39
- yield(config)
40
- client = Client.new(config)
41
- scope = Scope.new
42
- hub = Hub.new(client, scope)
43
- Thread.current[THREAD_LOCAL] = hub
44
- @main_hub = hub
45
- end
46
-
47
- def get_main_hub
48
- @main_hub
49
- end
50
-
51
- def logger
52
- configuration.logger
53
- end
54
-
55
- def add_breadcrumb(breadcrumb, &block)
56
- get_current_scope.breadcrumbs.record(breadcrumb, &block)
57
- end
58
-
59
- def configuration
60
- get_current_client.configuration
61
- end
62
-
63
- def get_current_client
64
- get_current_hub.current_client
65
- end
66
-
67
- def get_current_hub
68
- # we need to assign a hub to the current thread if it doesn't have one yet
69
- #
70
- # ideally, we should do this proactively whenever a new thread is created
71
- # but it's impossible for the SDK to keep track every new thread
72
- # so we need to use this rather passive way to make sure the app doesn't crash
73
- Thread.current[THREAD_LOCAL] || clone_hub_to_current_thread
74
- end
75
-
76
- def clone_hub_to_current_thread
77
- Thread.current[THREAD_LOCAL] = get_main_hub.clone
78
- end
79
-
80
- def get_current_scope
81
- get_current_hub.current_scope
82
- end
83
-
84
- def with_scope(&block)
85
- get_current_hub.with_scope(&block)
86
- end
87
-
88
- def configure_scope(&block)
89
- get_current_hub.configure_scope(&block)
90
- end
91
-
92
- def send_event(event)
93
- get_current_client.send_event(event)
94
- end
95
-
96
- def capture_event(event)
97
- get_current_hub.capture_event(event)
98
- end
99
-
100
- def capture_exception(exception, **options, &block)
101
- get_current_hub.capture_exception(exception, **options, &block)
102
- end
103
-
104
- def capture_message(message, **options, &block)
105
- get_current_hub.capture_message(message, **options, &block)
106
- end
107
-
108
- def start_transaction(**options)
109
- get_current_hub.start_transaction(**options)
110
- end
111
-
112
- def last_event_id
113
- get_current_hub.last_event_id
114
- end
115
-
116
- def sys_command(command)
117
- result = `#{command} 2>&1` rescue nil
118
- return if result.nil? || result.empty? || ($CHILD_STATUS && $CHILD_STATUS.exitstatus != 0)
119
-
120
- result.strip
121
- end
122
- end
123
- end
data/sentry-ruby.gemspec DELETED
@@ -1,26 +0,0 @@
1
- require_relative "lib/sentry/version"
2
-
3
- Gem::Specification.new do |spec|
4
- spec.name = "sentry-ruby"
5
- spec.version = Sentry::VERSION
6
- spec.authors = ["Sentry Team"]
7
- spec.description = spec.summary = "A gem that provides a client interface for the Sentry error logger"
8
- spec.email = "accounts@sentry.io"
9
- spec.license = 'Apache-2.0'
10
- spec.homepage = "https://github.com/getsentry/raven-ruby"
11
-
12
- spec.platform = Gem::Platform::RUBY
13
- spec.required_ruby_version = '>= 2.4'
14
- spec.extra_rdoc_files = ["README.md", "LICENSE.txt"]
15
- spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples)'`.split("\n")
16
-
17
- spec.metadata["homepage_uri"] = spec.homepage
18
- spec.metadata["source_code_uri"] = spec.homepage
19
- spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md"
20
-
21
- spec.bindir = "exe"
22
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
- spec.require_paths = ["lib"]
24
-
25
- spec.add_dependency "faraday", ">= 1.0"
26
- end