jones-gem 2.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +1 -0
- data/.rubocop.yml +74 -0
- data/.travis.yml +47 -0
- data/Gemfile +38 -0
- data/LICENSE +201 -0
- data/README.md +132 -0
- data/Rakefile +29 -0
- data/changelog.md +442 -0
- data/docs/Makefile +130 -0
- data/docs/breadcrumbs.rst +51 -0
- data/docs/conf.py +228 -0
- data/docs/config.rst +260 -0
- data/docs/context.rst +141 -0
- data/docs/index.rst +113 -0
- data/docs/install.rst +40 -0
- data/docs/integrations/heroku.rst +11 -0
- data/docs/integrations/index.rst +59 -0
- data/docs/integrations/puma.rst +30 -0
- data/docs/integrations/rack.rst +27 -0
- data/docs/integrations/rails.rst +84 -0
- data/docs/make.bat +155 -0
- data/docs/processors.rst +124 -0
- data/docs/sentry-doc-config.json +31 -0
- data/docs/usage.rst +176 -0
- data/exe/raven +32 -0
- data/jones-gem.gemspec +22 -0
- data/lib/raven.rb +3 -0
- data/lib/raven/backtrace.rb +137 -0
- data/lib/raven/base.rb +106 -0
- data/lib/raven/breadcrumbs.rb +76 -0
- data/lib/raven/breadcrumbs/activesupport.rb +19 -0
- data/lib/raven/breadcrumbs/logger.rb +93 -0
- data/lib/raven/cli.rb +59 -0
- data/lib/raven/client.rb +142 -0
- data/lib/raven/configuration.rb +434 -0
- data/lib/raven/context.rb +43 -0
- data/lib/raven/event.rb +259 -0
- data/lib/raven/instance.rb +221 -0
- data/lib/raven/integrations/delayed_job.rb +58 -0
- data/lib/raven/integrations/rack-timeout.rb +19 -0
- data/lib/raven/integrations/rack.rb +139 -0
- data/lib/raven/integrations/rails.rb +79 -0
- data/lib/raven/integrations/rails/active_job.rb +55 -0
- data/lib/raven/integrations/rails/controller_methods.rb +13 -0
- data/lib/raven/integrations/rails/controller_transaction.rb +13 -0
- data/lib/raven/integrations/rails/overrides/debug_exceptions_catcher.rb +31 -0
- data/lib/raven/integrations/rails/overrides/streaming_reporter.rb +23 -0
- data/lib/raven/integrations/railties.rb +1 -0
- data/lib/raven/integrations/rake.rb +18 -0
- data/lib/raven/integrations/sidekiq.rb +87 -0
- data/lib/raven/integrations/tasks.rb +11 -0
- data/lib/raven/interface.rb +25 -0
- data/lib/raven/interfaces/exception.rb +15 -0
- data/lib/raven/interfaces/http.rb +16 -0
- data/lib/raven/interfaces/message.rb +20 -0
- data/lib/raven/interfaces/single_exception.rb +14 -0
- data/lib/raven/interfaces/stack_trace.rb +69 -0
- data/lib/raven/linecache.rb +41 -0
- data/lib/raven/logger.rb +19 -0
- data/lib/raven/processor.rb +15 -0
- data/lib/raven/processor/cookies.rb +26 -0
- data/lib/raven/processor/http_headers.rb +55 -0
- data/lib/raven/processor/post_data.rb +22 -0
- data/lib/raven/processor/removecircularreferences.rb +17 -0
- data/lib/raven/processor/removestacktrace.rb +24 -0
- data/lib/raven/processor/sanitizedata.rb +88 -0
- data/lib/raven/processor/utf8conversion.rb +52 -0
- data/lib/raven/transports.rb +15 -0
- data/lib/raven/transports/dummy.rb +16 -0
- data/lib/raven/transports/http.rb +66 -0
- data/lib/raven/utils/deep_merge.rb +22 -0
- data/lib/raven/utils/real_ip.rb +62 -0
- data/lib/raven/version.rb +5 -0
- data/lib/sentry-raven-without-integrations.rb +1 -0
- data/lib/sentry-raven.rb +1 -0
- metadata +141 -0
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'delayed_job'
|
2
|
+
|
3
|
+
module Delayed
|
4
|
+
module Plugins
|
5
|
+
class Raven < ::Delayed::Plugin
|
6
|
+
callbacks do |lifecycle|
|
7
|
+
lifecycle.around(:invoke_job) do |job, *args, &block|
|
8
|
+
begin
|
9
|
+
# Forward the call to the next callback in the callback chain
|
10
|
+
block.call(job, *args)
|
11
|
+
|
12
|
+
rescue Exception => exception
|
13
|
+
# Log error to Sentry
|
14
|
+
extra = {
|
15
|
+
:delayed_job => {
|
16
|
+
:id => job.id,
|
17
|
+
:priority => job.priority,
|
18
|
+
:attempts => job.attempts,
|
19
|
+
:run_at => job.run_at,
|
20
|
+
:locked_at => job.locked_at,
|
21
|
+
:locked_by => job.locked_by,
|
22
|
+
:queue => job.queue,
|
23
|
+
:created_at => job.created_at
|
24
|
+
}
|
25
|
+
}
|
26
|
+
# last_error can be nil
|
27
|
+
extra[:last_error] = job.last_error[0...1000] if job.last_error
|
28
|
+
# handlers are YAML objects in strings, we definitely can't
|
29
|
+
# report all of that or the event will get truncated randomly
|
30
|
+
extra[:handler] = job.handler[0...1000] if job.handler
|
31
|
+
|
32
|
+
if job.respond_to?('payload_object') && job.payload_object.respond_to?('job_data')
|
33
|
+
extra[:active_job] = job.payload_object.job_data
|
34
|
+
end
|
35
|
+
::Raven.capture_exception(exception,
|
36
|
+
:logger => 'delayed_job',
|
37
|
+
:tags => {
|
38
|
+
:delayed_job_queue => job.queue,
|
39
|
+
:delayed_job_id => job.id
|
40
|
+
},
|
41
|
+
:extra => extra)
|
42
|
+
|
43
|
+
# Make sure we propagate the failure!
|
44
|
+
raise exception
|
45
|
+
ensure
|
46
|
+
::Raven::Context.clear!
|
47
|
+
::Raven::BreadcrumbBuffer.clear!
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# Register DelayedJob Raven plugin
|
57
|
+
#
|
58
|
+
Delayed::Worker.plugins << Delayed::Plugins::Raven
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# We need to do this because of the way integration loading works
|
2
|
+
require "rack/timeout/base" unless defined?(Rack::Timeout)
|
3
|
+
|
4
|
+
# This integration is a good example of how to change how exceptions
|
5
|
+
# get grouped by Sentry's UI. Simply override #raven_context in
|
6
|
+
# the exception class, and append something to the fingerprint
|
7
|
+
# that will distinguish exceptions in the way you desire.
|
8
|
+
module RackTimeoutExtensions
|
9
|
+
def raven_context
|
10
|
+
# Only rack-timeout 0.3.0+ provides the request environment, but we can't
|
11
|
+
# gate this based on a gem version constant because rack-timeout does
|
12
|
+
# not provide one.
|
13
|
+
{ :fingerprint => ["{{ default }}", env["REQUEST_URI"]] } if defined?(env)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Include is private in Ruby 1.9
|
18
|
+
Rack::Timeout::Error.__send__(:include, RackTimeoutExtensions)
|
19
|
+
Rack::Timeout::RequestTimeoutException.__send__(:include, RackTimeoutExtensions)
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'rack'
|
3
|
+
|
4
|
+
module Raven
|
5
|
+
# Middleware for Rack applications. Any errors raised by the upstream
|
6
|
+
# application will be delivered to Sentry and re-raised.
|
7
|
+
#
|
8
|
+
# Synopsis:
|
9
|
+
#
|
10
|
+
# require 'rack'
|
11
|
+
# require 'raven'
|
12
|
+
#
|
13
|
+
# Raven.configure do |config|
|
14
|
+
# config.server = 'http://my_dsn'
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# app = Rack::Builder.app do
|
18
|
+
# use Raven::Rack
|
19
|
+
# run lambda { |env| raise "Rack down" }
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# Use a standard Raven.configure call to configure your server credentials.
|
23
|
+
class Rack
|
24
|
+
def self.capture_type(exception, env, options = {})
|
25
|
+
if env['raven.requested_at']
|
26
|
+
options[:time_spent] = Time.now - env['raven.requested_at']
|
27
|
+
end
|
28
|
+
Raven.capture_type(exception, options) do |evt|
|
29
|
+
evt.interface :http do |int|
|
30
|
+
int.from_rack(env)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
class << self
|
35
|
+
alias capture_message capture_type
|
36
|
+
alias capture_exception capture_type
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize(app)
|
40
|
+
@app = app
|
41
|
+
end
|
42
|
+
|
43
|
+
def call(env)
|
44
|
+
# store the current environment in our local context for arbitrary
|
45
|
+
# callers
|
46
|
+
env['raven.requested_at'] = Time.now
|
47
|
+
Raven.rack_context(env)
|
48
|
+
Raven.context.transaction.push(env["PATH_INFO"]) if env["PATH_INFO"]
|
49
|
+
|
50
|
+
begin
|
51
|
+
response = @app.call(env)
|
52
|
+
rescue Error
|
53
|
+
raise # Don't capture Raven errors
|
54
|
+
rescue Exception => e
|
55
|
+
Raven::Rack.capture_exception(e, env)
|
56
|
+
raise
|
57
|
+
end
|
58
|
+
|
59
|
+
error = env['rack.exception'] || env['sinatra.error']
|
60
|
+
Raven::Rack.capture_exception(error, env) if error
|
61
|
+
|
62
|
+
response
|
63
|
+
ensure
|
64
|
+
Context.clear!
|
65
|
+
BreadcrumbBuffer.clear!
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
module RackInterface
|
70
|
+
def from_rack(env_hash)
|
71
|
+
req = ::Rack::Request.new(env_hash)
|
72
|
+
|
73
|
+
self.url = req.scheme && req.url.split('?').first
|
74
|
+
self.method = req.request_method
|
75
|
+
self.query_string = req.query_string
|
76
|
+
self.data = read_data_from(req)
|
77
|
+
self.cookies = req.cookies
|
78
|
+
|
79
|
+
self.headers = format_headers_for_sentry(env_hash)
|
80
|
+
self.env = format_env_for_sentry(env_hash)
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
# See Sentry server default limits at
|
86
|
+
# https://github.com/getsentry/sentry/blob/master/src/sentry/conf/server.py
|
87
|
+
def read_data_from(request)
|
88
|
+
if request.form_data?
|
89
|
+
request.POST
|
90
|
+
elsif request.body # JSON requests, etc
|
91
|
+
data = request.body.read(4096 * 4) # Sentry server limit
|
92
|
+
request.body.rewind
|
93
|
+
data
|
94
|
+
end
|
95
|
+
rescue IOError => ex
|
96
|
+
ex.message
|
97
|
+
end
|
98
|
+
|
99
|
+
def format_headers_for_sentry(env_hash)
|
100
|
+
env_hash.each_with_object({}) do |(key, value), memo|
|
101
|
+
begin
|
102
|
+
key = key.to_s # rack env can contain symbols
|
103
|
+
value = value.to_s
|
104
|
+
next unless key.upcase == key # Non-upper case stuff isn't either
|
105
|
+
|
106
|
+
# Rack adds in an incorrect HTTP_VERSION key, which causes downstream
|
107
|
+
# to think this is a Version header. Instead, this is mapped to
|
108
|
+
# env['SERVER_PROTOCOL']. But we don't want to ignore a valid header
|
109
|
+
# if the request has legitimately sent a Version header themselves.
|
110
|
+
# See: https://github.com/rack/rack/blob/028438f/lib/rack/handler/cgi.rb#L29
|
111
|
+
next if key == 'HTTP_VERSION' && value == env_hash['SERVER_PROTOCOL']
|
112
|
+
next if key == 'HTTP_COOKIE' # Cookies don't go here, they go somewhere else
|
113
|
+
|
114
|
+
next unless key.start_with?('HTTP_') || %w(CONTENT_TYPE CONTENT_LENGTH).include?(key)
|
115
|
+
# Rack stores headers as HTTP_WHAT_EVER, we need What-Ever
|
116
|
+
key = key.gsub("HTTP_", "")
|
117
|
+
key = key.split('_').map(&:capitalize).join('-')
|
118
|
+
memo[key] = value
|
119
|
+
rescue StandardError => e
|
120
|
+
# Rails adds objects to the Rack env that can sometimes raise exceptions
|
121
|
+
# when `to_s` is called.
|
122
|
+
# See: https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/remote_ip.rb#L134
|
123
|
+
Raven.logger.warn("Error raised while formatting headers: #{e.message}")
|
124
|
+
next
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def format_env_for_sentry(env_hash)
|
130
|
+
env_hash.select do |k, _v|
|
131
|
+
%w(REMOTE_ADDR SERVER_NAME SERVER_PORT).include? k.to_s
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
class HttpInterface
|
137
|
+
include RackInterface
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'rails'
|
2
|
+
|
3
|
+
module Raven
|
4
|
+
class Rails < ::Rails::Railtie
|
5
|
+
require 'raven/integrations/rails/overrides/streaming_reporter'
|
6
|
+
require 'raven/integrations/rails/controller_methods'
|
7
|
+
require 'raven/integrations/rails/controller_transaction'
|
8
|
+
|
9
|
+
initializer "raven.use_rack_middleware" do |app|
|
10
|
+
app.config.middleware.insert 0, Raven::Rack
|
11
|
+
end
|
12
|
+
|
13
|
+
initializer 'raven.action_controller' do
|
14
|
+
ActiveSupport.on_load :action_controller do
|
15
|
+
include Raven::Rails::ControllerMethods
|
16
|
+
include Raven::Rails::ControllerTransaction
|
17
|
+
if ::Rails::VERSION::STRING >= "4.0.0"
|
18
|
+
Raven.safely_prepend(
|
19
|
+
"StreamingReporter",
|
20
|
+
:from => Raven::Rails::Overrides,
|
21
|
+
:to => ActionController::Live
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
initializer 'raven.action_view' do
|
28
|
+
ActiveSupport.on_load :action_view do
|
29
|
+
Raven.safely_prepend(
|
30
|
+
"StreamingReporter",
|
31
|
+
:from => Raven::Rails::Overrides,
|
32
|
+
:to => ActionView::StreamingTemplateRenderer::Body
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
config.before_initialize do
|
38
|
+
Raven.configuration.logger = ::Rails.logger
|
39
|
+
end
|
40
|
+
|
41
|
+
config.after_initialize do
|
42
|
+
if Raven.configuration.rails_activesupport_breadcrumbs
|
43
|
+
require 'raven/breadcrumbs/activesupport'
|
44
|
+
Raven::ActiveSupportBreadcrumbs.inject
|
45
|
+
end
|
46
|
+
|
47
|
+
if Raven.configuration.rails_report_rescued_exceptions
|
48
|
+
require 'raven/integrations/rails/overrides/debug_exceptions_catcher'
|
49
|
+
if defined?(::ActionDispatch::DebugExceptions)
|
50
|
+
exceptions_class = ::ActionDispatch::DebugExceptions
|
51
|
+
elsif defined?(::ActionDispatch::ShowExceptions)
|
52
|
+
exceptions_class = ::ActionDispatch::ShowExceptions
|
53
|
+
end
|
54
|
+
|
55
|
+
Raven.safely_prepend(
|
56
|
+
"DebugExceptionsCatcher",
|
57
|
+
:from => Raven::Rails::Overrides,
|
58
|
+
:to => exceptions_class
|
59
|
+
)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
initializer 'raven.active_job' do
|
64
|
+
ActiveSupport.on_load :active_job do
|
65
|
+
require 'raven/integrations/rails/active_job'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
rake_tasks do
|
70
|
+
require 'raven/integrations/tasks'
|
71
|
+
end
|
72
|
+
|
73
|
+
if defined?(runner)
|
74
|
+
runner do
|
75
|
+
Raven.capture
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Raven
|
2
|
+
class Rails
|
3
|
+
module ActiveJobExtensions
|
4
|
+
ALREADY_SUPPORTED_SENTRY_ADAPTERS = %w(
|
5
|
+
ActiveJob::QueueAdapters::SidekiqAdapter
|
6
|
+
ActiveJob::QueueAdapters::DelayedJobAdapter
|
7
|
+
).freeze
|
8
|
+
|
9
|
+
def self.included(base)
|
10
|
+
base.class_eval do
|
11
|
+
around_perform do |job, block|
|
12
|
+
capture_and_reraise_with_sentry(job, block)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def capture_and_reraise_with_sentry(job, block)
|
18
|
+
block.call
|
19
|
+
rescue Exception => exception # rubocop:disable Lint/RescueException
|
20
|
+
return if rescue_with_handler(exception)
|
21
|
+
unless already_supported_by_specific_integration?(job)
|
22
|
+
Raven.capture_exception(exception, :extra => raven_context(job))
|
23
|
+
end
|
24
|
+
raise exception
|
25
|
+
ensure
|
26
|
+
Context.clear!
|
27
|
+
BreadcrumbBuffer.clear!
|
28
|
+
end
|
29
|
+
|
30
|
+
def already_supported_by_specific_integration?(job)
|
31
|
+
ALREADY_SUPPORTED_SENTRY_ADAPTERS.include?(job.class.queue_adapter.to_s)
|
32
|
+
end
|
33
|
+
|
34
|
+
def raven_context(job)
|
35
|
+
ctx = {
|
36
|
+
:active_job => job.class.name,
|
37
|
+
:arguments => job.arguments,
|
38
|
+
:scheduled_at => job.scheduled_at,
|
39
|
+
:job_id => job.job_id,
|
40
|
+
:locale => job.locale
|
41
|
+
}
|
42
|
+
# Add provider_job_id details if Rails 5
|
43
|
+
if job.respond_to?(:provider_job_id)
|
44
|
+
ctx[:provider_job_id] = job.provider_job_id
|
45
|
+
end
|
46
|
+
|
47
|
+
ctx
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class ActiveJob::Base
|
54
|
+
include Raven::Rails::ActiveJobExtensions
|
55
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Raven
|
2
|
+
class Rails
|
3
|
+
module ControllerMethods
|
4
|
+
def capture_message(message, options = {})
|
5
|
+
Raven::Rack.capture_message(message, request.env, options)
|
6
|
+
end
|
7
|
+
|
8
|
+
def capture_exception(exception, options = {})
|
9
|
+
Raven::Rack.capture_exception(exception, request.env, options)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Raven
|
2
|
+
class Rails
|
3
|
+
module ControllerTransaction
|
4
|
+
def self.included(base)
|
5
|
+
base.around_action do |controller, block|
|
6
|
+
Raven.context.transaction.push "#{controller.class}##{controller.action_name}"
|
7
|
+
block.call
|
8
|
+
Raven.context.transaction.pop
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Raven
|
2
|
+
class Rails
|
3
|
+
module Overrides
|
4
|
+
module DebugExceptionsCatcher
|
5
|
+
def render_exception(env_or_request, exception)
|
6
|
+
begin
|
7
|
+
env = env_or_request.respond_to?(:env) ? env_or_request.env : env_or_request
|
8
|
+
Raven::Rack.capture_exception(exception, env)
|
9
|
+
rescue # rubocop:disable Lint/HandleExceptions
|
10
|
+
end
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module OldDebugExceptionsCatcher
|
16
|
+
def self.included(base)
|
17
|
+
base.send(:alias_method_chain, :render_exception, :raven)
|
18
|
+
end
|
19
|
+
|
20
|
+
def render_exception_with_raven(env_or_request, exception)
|
21
|
+
begin
|
22
|
+
env = env_or_request.respond_to?(:env) ? env_or_request.env : env_or_request
|
23
|
+
Raven::Rack.capture_exception(exception, env)
|
24
|
+
rescue # rubocop:disable Lint/HandleExceptions
|
25
|
+
end
|
26
|
+
render_exception_without_raven(env_or_request, exception)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Raven
|
2
|
+
class Rails
|
3
|
+
module Overrides
|
4
|
+
module StreamingReporter
|
5
|
+
def log_error(exception)
|
6
|
+
Raven.capture_exception(exception)
|
7
|
+
super
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module OldStreamingReporter
|
12
|
+
def self.included(base)
|
13
|
+
base.send(:alias_method_chain, :log_error, :raven)
|
14
|
+
end
|
15
|
+
|
16
|
+
def log_error_with_raven(exception)
|
17
|
+
Raven.capture_exception(exception)
|
18
|
+
log_error_without_raven(exception)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'raven/integrations/rails'
|