alec-gem 2.7.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 +7 -0
- data/.rspec +1 -0
- data/.rubocop.yml +74 -0
- data/.travis.yml +47 -0
- data/Gemfile +38 -0
- data/Gemfile.lock +215 -0
- data/LICENSE +201 -0
- data/README.md +132 -0
- data/Rakefile +29 -0
- data/alec-gem.gemspec +22 -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 +62 -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/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 +59 -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 +68 -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
- data/pkg/sentry-raven-2.7.2.gem +0 -0
- metadata +143 -0
data/exe/raven
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "raven"
|
4
|
+
require "raven/cli"
|
5
|
+
require "optparse"
|
6
|
+
|
7
|
+
parser = OptionParser.new do |opt|
|
8
|
+
opt.banner = "Usage: raven COMMAND [OPTIONS]"
|
9
|
+
opt.separator ""
|
10
|
+
opt.separator "Commands"
|
11
|
+
opt.separator " test: send a test event"
|
12
|
+
opt.separator ""
|
13
|
+
opt.separator "Options"
|
14
|
+
|
15
|
+
opt.on("-h", "--help", "help") do
|
16
|
+
puts parser
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
parser.parse!
|
21
|
+
|
22
|
+
case ARGV[0]
|
23
|
+
when "test"
|
24
|
+
dsn = ARGV[1] if ARGV.length > 1
|
25
|
+
if !dsn
|
26
|
+
puts "Usage: raven test <dsn>"
|
27
|
+
else
|
28
|
+
Raven::CLI.test(dsn)
|
29
|
+
end
|
30
|
+
else
|
31
|
+
puts parser
|
32
|
+
end
|
data/lib/raven.rb
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
## Inspired by Rails' and Airbrake's backtrace parsers.
|
2
|
+
|
3
|
+
module Raven
|
4
|
+
# Front end to parsing the backtrace for each notice
|
5
|
+
class Backtrace
|
6
|
+
# Handles backtrace parsing line by line
|
7
|
+
class Line
|
8
|
+
RB_EXTENSION = ".rb".freeze
|
9
|
+
# regexp (optional leading X: on windows, or JRuby9000 class-prefix)
|
10
|
+
RUBY_INPUT_FORMAT = /
|
11
|
+
^ \s* (?: [a-zA-Z]: | uri:classloader: )? ([^:]+ | <.*>):
|
12
|
+
(\d+)
|
13
|
+
(?: :in \s `([^']+)')?$
|
14
|
+
/x
|
15
|
+
|
16
|
+
# org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
|
17
|
+
JAVA_INPUT_FORMAT = /^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)$/
|
18
|
+
|
19
|
+
# The file portion of the line (such as app/models/user.rb)
|
20
|
+
attr_reader :file
|
21
|
+
|
22
|
+
# The line number portion of the line
|
23
|
+
attr_reader :number
|
24
|
+
|
25
|
+
# The method of the line (such as index)
|
26
|
+
attr_reader :method
|
27
|
+
|
28
|
+
# The module name (JRuby)
|
29
|
+
attr_reader :module_name
|
30
|
+
|
31
|
+
# Parses a single line of a given backtrace
|
32
|
+
# @param [String] unparsed_line The raw line from +caller+ or some backtrace
|
33
|
+
# @return [Line] The parsed backtrace line
|
34
|
+
def self.parse(unparsed_line)
|
35
|
+
ruby_match = unparsed_line.match(RUBY_INPUT_FORMAT)
|
36
|
+
if ruby_match
|
37
|
+
_, file, number, method = ruby_match.to_a
|
38
|
+
file.sub!(/\.class$/, RB_EXTENSION)
|
39
|
+
module_name = nil
|
40
|
+
else
|
41
|
+
java_match = unparsed_line.match(JAVA_INPUT_FORMAT)
|
42
|
+
_, module_name, method, file, number = java_match.to_a
|
43
|
+
end
|
44
|
+
new(file, number, method, module_name)
|
45
|
+
end
|
46
|
+
|
47
|
+
def initialize(file, number, method, module_name)
|
48
|
+
self.file = file
|
49
|
+
self.module_name = module_name
|
50
|
+
self.number = number.to_i
|
51
|
+
self.method = method
|
52
|
+
end
|
53
|
+
|
54
|
+
def in_app
|
55
|
+
if file =~ self.class.in_app_pattern
|
56
|
+
true
|
57
|
+
else
|
58
|
+
false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Reconstructs the line in a readable fashion
|
63
|
+
def to_s
|
64
|
+
"#{file}:#{number}:in `#{method}'"
|
65
|
+
end
|
66
|
+
|
67
|
+
def ==(other)
|
68
|
+
to_s == other.to_s
|
69
|
+
end
|
70
|
+
|
71
|
+
def inspect
|
72
|
+
"<Line:#{self}>"
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.in_app_pattern
|
76
|
+
@in_app_pattern ||= begin
|
77
|
+
project_root = Raven.configuration.project_root && Raven.configuration.project_root.to_s
|
78
|
+
Regexp.new("^(#{project_root}/)?#{Raven.configuration.app_dirs_pattern || APP_DIRS_PATTERN}")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
attr_writer :file, :number, :method, :module_name
|
85
|
+
end
|
86
|
+
|
87
|
+
APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test)/
|
88
|
+
|
89
|
+
# holder for an Array of Backtrace::Line instances
|
90
|
+
attr_reader :lines
|
91
|
+
|
92
|
+
def self.parse(backtrace, opts = {})
|
93
|
+
ruby_lines = backtrace.is_a?(Array) ? backtrace : backtrace.split(/\n\s*/)
|
94
|
+
|
95
|
+
filters = opts[:filters] || []
|
96
|
+
filtered_lines = ruby_lines.to_a.map do |line|
|
97
|
+
filters.reduce(line) do |nested_line, proc|
|
98
|
+
proc.call(nested_line)
|
99
|
+
end
|
100
|
+
end.compact
|
101
|
+
|
102
|
+
lines = filtered_lines.map do |unparsed_line|
|
103
|
+
Line.parse(unparsed_line)
|
104
|
+
end
|
105
|
+
|
106
|
+
new(lines)
|
107
|
+
end
|
108
|
+
|
109
|
+
def initialize(lines)
|
110
|
+
self.lines = lines
|
111
|
+
end
|
112
|
+
|
113
|
+
def inspect
|
114
|
+
"<Backtrace: " + lines.map(&:inspect).join(", ") + ">"
|
115
|
+
end
|
116
|
+
|
117
|
+
def to_s
|
118
|
+
content = []
|
119
|
+
lines.each do |line|
|
120
|
+
content << line
|
121
|
+
end
|
122
|
+
content.join("\n")
|
123
|
+
end
|
124
|
+
|
125
|
+
def ==(other)
|
126
|
+
if other.respond_to?(:lines)
|
127
|
+
lines == other.lines
|
128
|
+
else
|
129
|
+
false
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
attr_writer :lines
|
136
|
+
end
|
137
|
+
end
|
data/lib/raven/base.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'raven/version'
|
2
|
+
require 'raven/backtrace'
|
3
|
+
require 'raven/breadcrumbs'
|
4
|
+
require 'raven/processor'
|
5
|
+
require 'raven/processor/sanitizedata'
|
6
|
+
require 'raven/processor/removecircularreferences'
|
7
|
+
require 'raven/processor/utf8conversion'
|
8
|
+
require 'raven/processor/cookies'
|
9
|
+
require 'raven/processor/post_data'
|
10
|
+
require 'raven/processor/http_headers'
|
11
|
+
require 'raven/configuration'
|
12
|
+
require 'raven/context'
|
13
|
+
require 'raven/client'
|
14
|
+
require 'raven/event'
|
15
|
+
require 'raven/linecache'
|
16
|
+
require 'raven/logger'
|
17
|
+
require 'raven/interfaces/message'
|
18
|
+
require 'raven/interfaces/exception'
|
19
|
+
require 'raven/interfaces/single_exception'
|
20
|
+
require 'raven/interfaces/stack_trace'
|
21
|
+
require 'raven/interfaces/http'
|
22
|
+
require 'raven/transports'
|
23
|
+
require 'raven/transports/http'
|
24
|
+
require 'raven/utils/deep_merge'
|
25
|
+
require 'raven/utils/real_ip'
|
26
|
+
require 'raven/instance'
|
27
|
+
|
28
|
+
require 'forwardable'
|
29
|
+
require 'English'
|
30
|
+
|
31
|
+
module Raven
|
32
|
+
AVAILABLE_INTEGRATIONS = %w(delayed_job railties sidekiq rack rack-timeout rake).freeze
|
33
|
+
|
34
|
+
class Error < StandardError
|
35
|
+
end
|
36
|
+
|
37
|
+
class << self
|
38
|
+
extend Forwardable
|
39
|
+
|
40
|
+
def instance
|
41
|
+
@instance ||= Raven::Instance.new
|
42
|
+
end
|
43
|
+
|
44
|
+
def_delegators :instance, :client=, :configuration=, :context, :logger, :configuration,
|
45
|
+
:client, :report_status, :configure, :send_event, :capture, :capture_type,
|
46
|
+
:last_event_id, :annotate_exception, :user_context,
|
47
|
+
:tags_context, :extra_context, :rack_context, :breadcrumbs
|
48
|
+
|
49
|
+
def_delegator :instance, :report_status, :report_ready
|
50
|
+
def_delegator :instance, :capture_type, :capture_message
|
51
|
+
def_delegator :instance, :capture_type, :capture_exception
|
52
|
+
# For cross-language compatibility
|
53
|
+
def_delegator :instance, :capture_type, :captureException
|
54
|
+
def_delegator :instance, :capture_type, :captureMessage
|
55
|
+
def_delegator :instance, :annotate_exception, :annotateException
|
56
|
+
def_delegator :instance, :annotate_exception, :annotate
|
57
|
+
|
58
|
+
# Injects various integrations. Default behavior: inject all available integrations
|
59
|
+
def inject
|
60
|
+
inject_only(*Raven::AVAILABLE_INTEGRATIONS)
|
61
|
+
end
|
62
|
+
|
63
|
+
def inject_without(*exclude_integrations)
|
64
|
+
include_integrations = Raven::AVAILABLE_INTEGRATIONS - exclude_integrations.map(&:to_s)
|
65
|
+
inject_only(*include_integrations)
|
66
|
+
end
|
67
|
+
|
68
|
+
def inject_only(*only_integrations)
|
69
|
+
only_integrations = only_integrations.map(&:to_s)
|
70
|
+
integrations_to_load = Raven::AVAILABLE_INTEGRATIONS & only_integrations
|
71
|
+
not_found_integrations = only_integrations - integrations_to_load
|
72
|
+
if not_found_integrations.any?
|
73
|
+
logger.warn "Integrations do not exist: #{not_found_integrations.join ', '}"
|
74
|
+
end
|
75
|
+
integrations_to_load &= Gem.loaded_specs.keys
|
76
|
+
# TODO(dcramer): integrations should have some additional checks baked-in
|
77
|
+
# or we should break them out into their own repos. Specifically both the
|
78
|
+
# rails and delayed_job checks are not always valid (i.e. Rails 2.3) and
|
79
|
+
# https://github.com/getsentry/raven-ruby/issues/180
|
80
|
+
integrations_to_load.each do |integration|
|
81
|
+
load_integration(integration)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def load_integration(integration)
|
86
|
+
require "raven/integrations/#{integration}"
|
87
|
+
rescue Exception => error
|
88
|
+
logger.warn "Unable to load raven/integrations/#{integration}: #{error}"
|
89
|
+
end
|
90
|
+
|
91
|
+
def safely_prepend(module_name, opts = {})
|
92
|
+
return if opts[:to].nil? || opts[:from].nil?
|
93
|
+
if opts[:to].respond_to?(:prepend, true)
|
94
|
+
opts[:to].send(:prepend, opts[:from].const_get(module_name))
|
95
|
+
else
|
96
|
+
opts[:to].send(:include, opts[:from].const_get("Old" + module_name))
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def sys_command(command)
|
101
|
+
result = `#{command} 2>&1` rescue nil
|
102
|
+
return if result.nil? || result.empty? || $CHILD_STATUS.exitstatus != 0
|
103
|
+
result.strip
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Raven
|
2
|
+
class Breadcrumb
|
3
|
+
attr_accessor :category, :data, :message, :level, :timestamp, :type
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@category = nil
|
7
|
+
@data = {}
|
8
|
+
@level = nil
|
9
|
+
@message = nil
|
10
|
+
@timestamp = Time.now.to_i
|
11
|
+
@type = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_hash
|
15
|
+
{
|
16
|
+
:category => @category,
|
17
|
+
:data => @data,
|
18
|
+
:level => @level,
|
19
|
+
:message => @message,
|
20
|
+
:timestamp => @timestamp,
|
21
|
+
:type => @type
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module Raven
|
28
|
+
class BreadcrumbBuffer
|
29
|
+
include Enumerable
|
30
|
+
|
31
|
+
attr_accessor :buffer
|
32
|
+
|
33
|
+
def self.current
|
34
|
+
Thread.current[:sentry_breadcrumbs] ||= new
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.clear!
|
38
|
+
Thread.current[:sentry_breadcrumbs] = nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize(size = 100)
|
42
|
+
@buffer = Array.new(size)
|
43
|
+
end
|
44
|
+
|
45
|
+
def record(crumb = nil)
|
46
|
+
if block_given?
|
47
|
+
crumb = Breadcrumb.new if crumb.nil?
|
48
|
+
yield(crumb)
|
49
|
+
end
|
50
|
+
@buffer.slice!(0)
|
51
|
+
@buffer << crumb
|
52
|
+
end
|
53
|
+
|
54
|
+
def members
|
55
|
+
@buffer.compact
|
56
|
+
end
|
57
|
+
|
58
|
+
def peek
|
59
|
+
members.last
|
60
|
+
end
|
61
|
+
|
62
|
+
def each(&block)
|
63
|
+
members.each(&block)
|
64
|
+
end
|
65
|
+
|
66
|
+
def empty?
|
67
|
+
!members.any?
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_hash
|
71
|
+
{
|
72
|
+
:values => members.map(&:to_hash)
|
73
|
+
}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Raven
|
2
|
+
module ActiveSupportBreadcrumbs
|
3
|
+
class << self
|
4
|
+
def add(name, started, _finished, _unique_id, data)
|
5
|
+
Raven.breadcrumbs.record do |crumb|
|
6
|
+
crumb.data = data
|
7
|
+
crumb.category = name
|
8
|
+
crumb.timestamp = started.to_i
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def inject
|
13
|
+
ActiveSupport::Notifications.subscribe(/.*/) do |name, started, finished, unique_id, data|
|
14
|
+
add(name, started, finished, unique_id, data)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Raven
|
4
|
+
module BreadcrumbLogger
|
5
|
+
LEVELS = {
|
6
|
+
::Logger::DEBUG => 'debug',
|
7
|
+
::Logger::INFO => 'info',
|
8
|
+
::Logger::WARN => 'warn',
|
9
|
+
::Logger::ERROR => 'error',
|
10
|
+
::Logger::FATAL => 'fatal'
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
EXC_FORMAT = /^([a-zA-Z0-9]+)\:\s(.*)$/
|
14
|
+
|
15
|
+
def self.parse_exception(message)
|
16
|
+
lines = message.split(/\n\s*/)
|
17
|
+
# TODO: wat
|
18
|
+
return nil unless lines.length > 2
|
19
|
+
|
20
|
+
match = lines[0].match(EXC_FORMAT)
|
21
|
+
return nil unless match
|
22
|
+
|
23
|
+
_, type, value = match.to_a
|
24
|
+
[type, value]
|
25
|
+
end
|
26
|
+
|
27
|
+
def add(*args)
|
28
|
+
add_breadcrumb(*args)
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def add_breadcrumb(severity, message = nil, progname = nil)
|
33
|
+
message = progname if message.nil? # see Ruby's Logger docs for why
|
34
|
+
return if ignored_logger?(progname)
|
35
|
+
return if message.nil? || message == ""
|
36
|
+
|
37
|
+
# some loggers will add leading/trailing space as they (incorrectly, mind you)
|
38
|
+
# think of logging as a shortcut to std{out,err}
|
39
|
+
message = message.strip
|
40
|
+
|
41
|
+
last_crumb = Raven.breadcrumbs.peek
|
42
|
+
# try to avoid dupes from logger broadcasts
|
43
|
+
if last_crumb.nil? || last_crumb.message != message
|
44
|
+
error = Raven::BreadcrumbLogger.parse_exception(message)
|
45
|
+
# TODO(dcramer): we need to filter out the "currently captured error"
|
46
|
+
if error
|
47
|
+
Raven.breadcrumbs.record do |crumb|
|
48
|
+
crumb.level = Raven::BreadcrumbLogger::LEVELS.fetch(severity, nil)
|
49
|
+
crumb.category = progname || 'error'
|
50
|
+
crumb.type = 'error'
|
51
|
+
crumb.data = {
|
52
|
+
:type => error[0],
|
53
|
+
:value => error[1]
|
54
|
+
}
|
55
|
+
end
|
56
|
+
else
|
57
|
+
Raven.breadcrumbs.record do |crumb|
|
58
|
+
crumb.level = Raven::BreadcrumbLogger::LEVELS.fetch(severity, nil)
|
59
|
+
crumb.category = progname || 'logger'
|
60
|
+
crumb.message = message
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def ignored_logger?(progname)
|
69
|
+
progname == "sentry" ||
|
70
|
+
Raven.configuration.exclude_loggers.include?(progname)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
module OldBreadcrumbLogger
|
74
|
+
def self.included(base)
|
75
|
+
base.class_eval do
|
76
|
+
include Raven::BreadcrumbLogger
|
77
|
+
alias_method :add_without_raven, :add
|
78
|
+
alias_method :add, :add_with_raven
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def add_with_raven(*args)
|
83
|
+
add_breadcrumb(*args)
|
84
|
+
add_without_raven(*args)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
Raven.safely_prepend(
|
90
|
+
"BreadcrumbLogger",
|
91
|
+
:from => Raven,
|
92
|
+
:to => ::Logger
|
93
|
+
)
|