mustwin-sentry-raven 0.11.2
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.
- checksums.yaml +15 -0
- data/LICENSE +201 -0
- data/README.md +54 -0
- data/bin/raven +42 -0
- data/lib/raven.rb +3 -0
- data/lib/raven/backtrace.rb +128 -0
- data/lib/raven/base.rb +225 -0
- data/lib/raven/better_attr_accessor.rb +44 -0
- data/lib/raven/cli.rb +63 -0
- data/lib/raven/client.rb +104 -0
- data/lib/raven/configuration.rb +173 -0
- data/lib/raven/context.rb +21 -0
- data/lib/raven/error.rb +4 -0
- data/lib/raven/event.rb +223 -0
- data/lib/raven/integrations/delayed_job.rb +49 -0
- data/lib/raven/interfaces.rb +34 -0
- data/lib/raven/interfaces/exception.rb +22 -0
- data/lib/raven/interfaces/http.rb +53 -0
- data/lib/raven/interfaces/message.rb +17 -0
- data/lib/raven/interfaces/stack_trace.rb +55 -0
- data/lib/raven/linecache.rb +23 -0
- data/lib/raven/logger.rb +22 -0
- data/lib/raven/okjson.rb +609 -0
- data/lib/raven/processor.rb +28 -0
- data/lib/raven/processor/removecircularreferences.rb +17 -0
- data/lib/raven/processor/sanitizedata.rb +42 -0
- data/lib/raven/processor/utf8conversion.rb +26 -0
- data/lib/raven/rack.rb +75 -0
- data/lib/raven/rails/controller_methods.rb +13 -0
- data/lib/raven/rails/middleware/debug_exceptions_catcher.rb +16 -0
- data/lib/raven/railtie.rb +38 -0
- data/lib/raven/rake.rb +13 -0
- data/lib/raven/sidekiq.rb +27 -0
- data/lib/raven/tasks.rb +12 -0
- data/lib/raven/transports.rb +27 -0
- data/lib/raven/transports/http.rb +56 -0
- data/lib/raven/transports/udp.rb +30 -0
- data/lib/raven/version.rb +3 -0
- data/lib/sentry-raven.rb +1 -0
- metadata +168 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Raven
|
4
|
+
class Processor
|
5
|
+
attr_accessor :sanitize_fields
|
6
|
+
|
7
|
+
def initialize(client)
|
8
|
+
@client = client
|
9
|
+
@sanitize_fields = client.configuration.sanitize_fields
|
10
|
+
end
|
11
|
+
|
12
|
+
def process(data)
|
13
|
+
data
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def parse_json_or_nil(string)
|
19
|
+
begin
|
20
|
+
result = OkJson.decode(string)
|
21
|
+
result.is_a?(String) ? nil : result
|
22
|
+
rescue Raven::OkJson::Error
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Raven
|
2
|
+
class Processor::RemoveCircularReferences < Processor
|
3
|
+
|
4
|
+
def process(v, visited = [])
|
5
|
+
return "(...)" if visited.include?(v.__id__)
|
6
|
+
visited += [v.__id__]
|
7
|
+
if v.is_a?(Hash)
|
8
|
+
v.reduce({}) { |memo, (k, v_)| memo[k] = process(v_, visited); memo }
|
9
|
+
elsif v.is_a?(Array)
|
10
|
+
v.map { |v_| process(v_, visited) }
|
11
|
+
else
|
12
|
+
v
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Raven
|
2
|
+
class Processor::SanitizeData < Processor
|
3
|
+
STRING_MASK = '********'
|
4
|
+
INT_MASK = 0
|
5
|
+
DEFAULT_FIELDS = %w(authorization password passwd secret ssn social(.*)?sec)
|
6
|
+
VALUES_RE = /^\d{16}$/
|
7
|
+
|
8
|
+
def process(value)
|
9
|
+
fields_re = /(#{(DEFAULT_FIELDS + @sanitize_fields).join("|")})/i
|
10
|
+
|
11
|
+
value.inject(value) do |value,(k,v)|
|
12
|
+
v = k if v.nil?
|
13
|
+
if v.is_a?(Hash) || v.is_a?(Array)
|
14
|
+
process(v)
|
15
|
+
elsif v.is_a?(String) && (json = parse_json_or_nil(v))
|
16
|
+
#if this string is actually a json obj, convert and sanitize
|
17
|
+
value = modify_in_place(value, [k,v], process(json).to_json)
|
18
|
+
elsif v.is_a?(Integer) && (VALUES_RE.match(v.to_s) || fields_re.match(k.to_s))
|
19
|
+
value = modify_in_place(value, [k,v], INT_MASK)
|
20
|
+
elsif VALUES_RE.match(v.to_s) || fields_re.match(k.to_s)
|
21
|
+
value = modify_in_place(value, [k,v], STRING_MASK)
|
22
|
+
else
|
23
|
+
value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
value
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def modify_in_place(original_parent, original_child, new_child)
|
32
|
+
if original_parent.is_a?(Array)
|
33
|
+
index = original_parent.index(original_child[0])
|
34
|
+
original_parent[index] = new_child
|
35
|
+
elsif original_parent.is_a?(Hash)
|
36
|
+
original_parent[original_child[0]] = new_child
|
37
|
+
end
|
38
|
+
original_parent
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Raven
|
2
|
+
class Processor::UTF8Conversion < Processor
|
3
|
+
|
4
|
+
def process(value)
|
5
|
+
if value.is_a? Array
|
6
|
+
value.map { |v_| process v_ }
|
7
|
+
elsif value.is_a? Hash
|
8
|
+
value.merge(value) { |k, v_| process v_ }
|
9
|
+
else
|
10
|
+
clean_invalid_utf8_bytes(value)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def clean_invalid_utf8_bytes(obj)
|
17
|
+
if obj.respond_to?(:to_utf8)
|
18
|
+
obj.to_utf8
|
19
|
+
elsif obj.respond_to?(:encoding)
|
20
|
+
obj.encode('UTF-16', :invalid => :replace, :undef => :replace, :replace => '').encode('UTF-8')
|
21
|
+
else
|
22
|
+
obj
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/raven/rack.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
3
|
+
module Raven
|
4
|
+
# Middleware for Rack applications. Any errors raised by the upstream
|
5
|
+
# application will be delivered to Sentry and re-raised.
|
6
|
+
#
|
7
|
+
# Synopsis:
|
8
|
+
#
|
9
|
+
# require 'rack'
|
10
|
+
# require 'raven'
|
11
|
+
#
|
12
|
+
# Raven.configure do |config|
|
13
|
+
# config.server = 'http://my_dsn'
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# app = Rack::Builder.app do
|
17
|
+
# use Raven::Rack
|
18
|
+
# run lambda { |env| raise "Rack down" }
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# Use a standard Raven.configure call to configure your server credentials.
|
22
|
+
class Rack
|
23
|
+
def self.capture_exception(exception, env, options = {})
|
24
|
+
if env['requested_at']
|
25
|
+
options[:time_spent] = Time.now - env['requested_at']
|
26
|
+
end
|
27
|
+
Raven.capture_exception(exception, options) do |evt|
|
28
|
+
evt.interface :http do |int|
|
29
|
+
int.from_rack(env)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.capture_message(message, env, options = {})
|
35
|
+
if env['requested_at']
|
36
|
+
options[:time_spent] = Time.now - env['requested_at']
|
37
|
+
end
|
38
|
+
Raven.capture_message(message, options) do |evt|
|
39
|
+
evt.interface :http do |int|
|
40
|
+
int.from_rack(env)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize(app)
|
46
|
+
@app = app
|
47
|
+
end
|
48
|
+
|
49
|
+
def call(env)
|
50
|
+
# clear context at the beginning of the request to ensure a clean slate
|
51
|
+
Context.clear!
|
52
|
+
|
53
|
+
# store the current environment in our local context for arbitrary
|
54
|
+
# callers
|
55
|
+
env['requested_at'] = Time.now
|
56
|
+
Raven.rack_context(env)
|
57
|
+
|
58
|
+
begin
|
59
|
+
response = @app.call(env)
|
60
|
+
rescue Error
|
61
|
+
raise # Don't capture Raven errors
|
62
|
+
rescue Exception => e
|
63
|
+
Raven.logger.debug "Collecting %p: %s" % [ e.class, e.message ]
|
64
|
+
Raven::Rack.capture_exception(e, env)
|
65
|
+
raise
|
66
|
+
end
|
67
|
+
|
68
|
+
error = env['rack.exception'] || env['sinatra.error']
|
69
|
+
|
70
|
+
Raven::Rack.capture_exception(error, env) if error
|
71
|
+
|
72
|
+
response
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Raven
|
2
|
+
module 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,16 @@
|
|
1
|
+
module Raven
|
2
|
+
module Rails
|
3
|
+
module Middleware
|
4
|
+
module DebugExceptionsCatcher
|
5
|
+
def self.included(base)
|
6
|
+
base.send(:alias_method_chain, :render_exception, :raven)
|
7
|
+
end
|
8
|
+
|
9
|
+
def render_exception_with_raven(env, exception)
|
10
|
+
Raven::Rack.capture_exception(exception, env)
|
11
|
+
render_exception_without_raven(env, exception)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'raven'
|
2
|
+
require 'rails'
|
3
|
+
|
4
|
+
module Raven
|
5
|
+
class Railtie < ::Rails::Railtie
|
6
|
+
initializer "raven.use_rack_middleware" do |app|
|
7
|
+
app.config.middleware.insert 0, "Raven::Rack"
|
8
|
+
end
|
9
|
+
|
10
|
+
initializer 'raven.action_controller' do
|
11
|
+
ActiveSupport.on_load :action_controller do
|
12
|
+
require 'raven/rails/controller_methods'
|
13
|
+
include Raven::Rails::ControllerMethods
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
config.after_initialize do
|
18
|
+
Raven.configure(true) do |config|
|
19
|
+
config.logger ||= ::Rails.logger
|
20
|
+
config.project_root ||= ::Rails.root
|
21
|
+
end
|
22
|
+
|
23
|
+
if Raven.configuration.catch_debugged_exceptions
|
24
|
+
if defined?(::ActionDispatch::DebugExceptions)
|
25
|
+
require 'raven/rails/middleware/debug_exceptions_catcher'
|
26
|
+
::ActionDispatch::DebugExceptions.send(:include, Raven::Rails::Middleware::DebugExceptionsCatcher)
|
27
|
+
elsif defined?(::ActionDispatch::ShowExceptions)
|
28
|
+
require 'raven/rails/middleware/debug_exceptions_catcher'
|
29
|
+
::ActionDispatch::ShowExceptions.send(:include, Raven::Rails::Middleware::DebugExceptionsCatcher)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
rake_tasks do
|
35
|
+
require 'raven/tasks'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/raven/rake.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'raven'
|
2
|
+
require 'rake/task'
|
3
|
+
|
4
|
+
module Rake
|
5
|
+
class Application
|
6
|
+
alias :orig_display_error_messsage :display_error_message
|
7
|
+
def display_error_message(ex)
|
8
|
+
Raven.capture_exception ex, :logger => 'rake', :tags => { 'rake_task' => @name }
|
9
|
+
orig_display_error_messsage(ex)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
3
|
+
module Raven
|
4
|
+
class Sidekiq
|
5
|
+
def call(worker, msg, queue)
|
6
|
+
started_at = Time.now
|
7
|
+
yield
|
8
|
+
rescue => ex
|
9
|
+
Raven.capture_exception(ex, :extra => { :sidekiq => msg },
|
10
|
+
:time_spent => Time.now-started_at)
|
11
|
+
raise
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
if Sidekiq::VERSION < '3'
|
17
|
+
# old behavior
|
18
|
+
::Sidekiq.configure_server do |config|
|
19
|
+
config.server_middleware do |chain|
|
20
|
+
chain.add ::Raven::Sidekiq
|
21
|
+
end
|
22
|
+
end
|
23
|
+
else
|
24
|
+
Sidekiq.configure_server do |config|
|
25
|
+
config.error_handlers << Proc.new {|ex,context| Raven.capture_exception(ex, :extra => {:sidekiq => context}) }
|
26
|
+
end
|
27
|
+
end
|
data/lib/raven/tasks.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'raven'
|
3
|
+
require 'raven/cli'
|
4
|
+
|
5
|
+
namespace :raven do
|
6
|
+
desc "Send a test event to the remote Sentry server"
|
7
|
+
task :test, [:dsn] do |t, args|
|
8
|
+
Rake::Task["environment"].invoke if defined? Rails
|
9
|
+
|
10
|
+
Raven::CLI.test(args.dsn)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'raven/error'
|
2
|
+
|
3
|
+
module Raven
|
4
|
+
module Transports
|
5
|
+
class Transport
|
6
|
+
|
7
|
+
attr_accessor :configuration
|
8
|
+
|
9
|
+
def initialize(configuration)
|
10
|
+
@configuration = configuration
|
11
|
+
end
|
12
|
+
|
13
|
+
def send(auth_header, data, options = {})
|
14
|
+
raise Error.new('Abstract method not implemented')
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def verify_configuration
|
20
|
+
raise Error.new('No server specified') unless self.configuration.server
|
21
|
+
raise Error.new('No public key specified') unless self.configuration.public_key
|
22
|
+
raise Error.new('No secret key specified') unless self.configuration.secret_key
|
23
|
+
raise Error.new('No project ID specified') unless self.configuration.project_id
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
require 'raven/transports'
|
4
|
+
require 'raven/error'
|
5
|
+
|
6
|
+
module Raven
|
7
|
+
module Transports
|
8
|
+
class HTTP < Transport
|
9
|
+
|
10
|
+
def send(auth_header, data, options = {})
|
11
|
+
project_id = self.configuration[:project_id]
|
12
|
+
path = self.configuration[:path].gsub('/sentry', '') + "/"
|
13
|
+
|
14
|
+
response = conn.post "#{path}api/#{project_id}/store/" do |req|
|
15
|
+
req.headers['Content-Type'] = options[:content_type]
|
16
|
+
req.headers['X-Sentry-Auth'] = auth_header
|
17
|
+
req.body = data
|
18
|
+
end
|
19
|
+
Raven.logger.warn "Error from Sentry server (#{response.status}): #{response.body}" unless response.status == 200
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def conn
|
25
|
+
@conn ||= begin
|
26
|
+
self.verify_configuration
|
27
|
+
|
28
|
+
Raven.logger.debug "Raven HTTP Transport connecting to #{self.configuration.server}"
|
29
|
+
|
30
|
+
ssl_configuration = self.configuration.ssl || {}
|
31
|
+
ssl_configuration[:verify] = self.configuration.ssl_verification
|
32
|
+
|
33
|
+
conn = Faraday.new(
|
34
|
+
:url => self.configuration[:server],
|
35
|
+
:ssl => ssl_configuration
|
36
|
+
) do |builder|
|
37
|
+
builder.adapter(*adapter)
|
38
|
+
end
|
39
|
+
|
40
|
+
if self.configuration.timeout
|
41
|
+
conn.options[:timeout] = self.configuration.timeout
|
42
|
+
end
|
43
|
+
if self.configuration.open_timeout
|
44
|
+
conn.options[:open_timeout] = self.configuration.open_timeout
|
45
|
+
end
|
46
|
+
|
47
|
+
conn
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def adapter
|
52
|
+
configuration.http_adapter || Faraday.default_adapter
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
require 'raven/transports'
|
4
|
+
require 'raven/error'
|
5
|
+
|
6
|
+
module Raven
|
7
|
+
module Transports
|
8
|
+
class UDP < Transport
|
9
|
+
|
10
|
+
def send(auth_header, data, options = {})
|
11
|
+
conn.send "#{auth_header}\n\n#{data}", 0
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def conn
|
17
|
+
@conn ||= begin
|
18
|
+
sock = UDPSocket.new
|
19
|
+
sock.connect(self.configuration.host, self.configuration.port)
|
20
|
+
sock
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def verify_configuration
|
25
|
+
super
|
26
|
+
raise Error.new('No port specified') unless self.configuration.port
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/sentry-raven.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "raven"
|