honeybadger 1.0.0
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.
- data/Gemfile +13 -0
- data/Gemfile.lock +114 -0
- data/Guardfile +5 -0
- data/MIT-LICENSE +22 -0
- data/README.md +271 -0
- data/Rakefile +261 -0
- data/SUPPORTED_RAILS_VERSIONS +26 -0
- data/TESTING.md +33 -0
- data/features/metal.feature +18 -0
- data/features/rack.feature +56 -0
- data/features/rails.feature +211 -0
- data/features/rake.feature +27 -0
- data/features/sinatra.feature +29 -0
- data/features/step_definitions/file_steps.rb +10 -0
- data/features/step_definitions/metal_steps.rb +23 -0
- data/features/step_definitions/rack_steps.rb +23 -0
- data/features/step_definitions/rails_application_steps.rb +394 -0
- data/features/step_definitions/rake_steps.rb +17 -0
- data/features/support/env.rb +17 -0
- data/features/support/honeybadger_shim.rb.template +8 -0
- data/features/support/rails.rb +201 -0
- data/features/support/rake/Rakefile +68 -0
- data/features/support/terminal.rb +107 -0
- data/generators/honeybadger/honeybadger_generator.rb +94 -0
- data/generators/honeybadger/lib/insert_commands.rb +34 -0
- data/generators/honeybadger/lib/rake_commands.rb +24 -0
- data/generators/honeybadger/templates/capistrano_hook.rb +6 -0
- data/generators/honeybadger/templates/honeybadger_tasks.rake +25 -0
- data/generators/honeybadger/templates/initializer.rb +6 -0
- data/honeybadger.gemspec +109 -0
- data/lib/honeybadger.rb +162 -0
- data/lib/honeybadger/backtrace.rb +123 -0
- data/lib/honeybadger/capistrano.rb +43 -0
- data/lib/honeybadger/configuration.rb +273 -0
- data/lib/honeybadger/notice.rb +314 -0
- data/lib/honeybadger/rack.rb +55 -0
- data/lib/honeybadger/rails.rb +34 -0
- data/lib/honeybadger/rails/action_controller_catcher.rb +30 -0
- data/lib/honeybadger/rails/controller_methods.rb +69 -0
- data/lib/honeybadger/rails/middleware/exceptions_catcher.rb +29 -0
- data/lib/honeybadger/rails3_tasks.rb +84 -0
- data/lib/honeybadger/railtie.rb +45 -0
- data/lib/honeybadger/rake_handler.rb +65 -0
- data/lib/honeybadger/sender.rb +120 -0
- data/lib/honeybadger/shared_tasks.rb +36 -0
- data/lib/honeybadger/tasks.rb +82 -0
- data/lib/honeybadger_tasks.rb +65 -0
- data/lib/rails/generators/honeybadger/honeybadger_generator.rb +99 -0
- data/rails/init.rb +1 -0
- data/resources/README.md +34 -0
- data/resources/ca-bundle.crt +3376 -0
- data/script/integration_test.rb +38 -0
- data/test/test_helper.rb +143 -0
- data/test/unit/backtrace_test.rb +180 -0
- data/test/unit/capistrano_test.rb +34 -0
- data/test/unit/configuration_test.rb +201 -0
- data/test/unit/honeybadger_tasks_test.rb +163 -0
- data/test/unit/logger_test.rb +72 -0
- data/test/unit/notice_test.rb +406 -0
- data/test/unit/notifier_test.rb +245 -0
- data/test/unit/rack_test.rb +56 -0
- data/test/unit/rails/action_controller_catcher_test.rb +300 -0
- data/test/unit/rails_test.rb +35 -0
- data/test/unit/sender_test.rb +257 -0
- metadata +315 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
# Mostly pinched from http://github.com/ryanb/nifty-generators/tree/master
|
2
|
+
|
3
|
+
Rails::Generator::Commands::Base.class_eval do
|
4
|
+
def file_contains?(relative_destination, line)
|
5
|
+
File.read(destination_path(relative_destination)).include?(line)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
Rails::Generator::Commands::Create.class_eval do
|
10
|
+
def append_to(file, line)
|
11
|
+
logger.insert "#{line} appended to #{file}"
|
12
|
+
unless options[:pretend] || file_contains?(file, line)
|
13
|
+
File.open(file, "a") do |file|
|
14
|
+
file.puts
|
15
|
+
file.puts line
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
Rails::Generator::Commands::Destroy.class_eval do
|
22
|
+
def append_to(file, line)
|
23
|
+
logger.remove "#{line} removed from #{file}"
|
24
|
+
unless options[:pretend]
|
25
|
+
gsub_file file, "\n#{line}", ''
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Rails::Generator::Commands::List.class_eval do
|
31
|
+
def append_to(file, line)
|
32
|
+
logger.insert "#{line} appended to #{file}"
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Rails::Generator::Commands::Create.class_eval do
|
2
|
+
def rake(cmd, opts = {})
|
3
|
+
logger.rake "rake #{cmd}"
|
4
|
+
unless system("rake #{cmd}")
|
5
|
+
logger.rake "#{cmd} failed. Rolling back"
|
6
|
+
command(:destroy).invoke!
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
Rails::Generator::Commands::Destroy.class_eval do
|
12
|
+
def rake(cmd, opts = {})
|
13
|
+
unless opts[:generate_only]
|
14
|
+
logger.rake "rake #{cmd}"
|
15
|
+
system "rake #{cmd}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
Rails::Generator::Commands::List.class_eval do
|
21
|
+
def rake(cmd, opts = {})
|
22
|
+
logger.rake "rake #{cmd}"
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Don't load anything when running the gems:* tasks.
|
2
|
+
# Otherwise, honeybadger will be considered a framework gem.
|
3
|
+
# https://thoughtbot.lighthouseapp.com/projects/14221/tickets/629
|
4
|
+
unless ARGV.any? {|a| a =~ /^gems/}
|
5
|
+
|
6
|
+
Dir[File.join(Rails.root, 'vendor', 'gems', 'honeybadger-*')].each do |vendored_notifier|
|
7
|
+
$: << File.join(vendored_notifier, 'lib')
|
8
|
+
end
|
9
|
+
|
10
|
+
begin
|
11
|
+
require 'honeybadger/tasks'
|
12
|
+
rescue LoadError => exception
|
13
|
+
namespace :honeybadger do
|
14
|
+
%w(deploy test log_stdout).each do |task_name|
|
15
|
+
desc "Missing dependency for honeybadger:#{task_name}"
|
16
|
+
task task_name do
|
17
|
+
$stderr.puts "Failed to run honeybadger:#{task_name} because of missing dependency."
|
18
|
+
$stderr.puts "You probably need to run `rake gems:install` to install the honeybadger gem"
|
19
|
+
abort exception.inspect
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/honeybadger.gemspec
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.specification_version = 2 if s.respond_to? :specification_version=
|
3
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
4
|
+
s.rubygems_version = '1.3.5'
|
5
|
+
|
6
|
+
s.name = 'honeybadger'
|
7
|
+
s.version = '1.0.0'
|
8
|
+
s.date = '2012-06-27'
|
9
|
+
|
10
|
+
s.summary = "Error reports you can be happy about."
|
11
|
+
s.description = "Make managing application errors a more pleasant experience."
|
12
|
+
|
13
|
+
s.authors = ["Joshua Wood"]
|
14
|
+
s.email = 'josh@honeybadger.io'
|
15
|
+
s.homepage = 'http://www.honeybadger.io'
|
16
|
+
|
17
|
+
s.require_paths = %w[lib]
|
18
|
+
|
19
|
+
s.rdoc_options = ["--charset=UTF-8", "--markup tomdoc"]
|
20
|
+
s.extra_rdoc_files = %w[README.md MIT-LICENSE]
|
21
|
+
|
22
|
+
s.add_dependency("json")
|
23
|
+
s.add_dependency("activesupport")
|
24
|
+
|
25
|
+
s.add_development_dependency("actionpack", "~> 2.3.8")
|
26
|
+
s.add_development_dependency("activerecord", "~> 2.3.8")
|
27
|
+
s.add_development_dependency("activesupport", "~> 2.3.8")
|
28
|
+
s.add_development_dependency("bourne", ">= 1.0")
|
29
|
+
s.add_development_dependency("cucumber", "~> 0.10.6")
|
30
|
+
s.add_development_dependency("rspec", "~> 2.6.0")
|
31
|
+
s.add_development_dependency("fakeweb", "~> 1.3.0")
|
32
|
+
s.add_development_dependency("sham_rack", "~> 1.3.0")
|
33
|
+
s.add_development_dependency("shoulda", "~> 2.11.3")
|
34
|
+
s.add_development_dependency("capistrano", "~> 2.8.0")
|
35
|
+
|
36
|
+
## Leave this section as-is. It will be automatically generated from the
|
37
|
+
## contents of your Git repository via the gemspec task. DO NOT REMOVE
|
38
|
+
## THE MANIFEST COMMENTS, they are used as delimiters by the task.
|
39
|
+
# = MANIFEST =
|
40
|
+
s.files = %w[
|
41
|
+
Gemfile
|
42
|
+
Gemfile.lock
|
43
|
+
Guardfile
|
44
|
+
MIT-LICENSE
|
45
|
+
README.md
|
46
|
+
Rakefile
|
47
|
+
SUPPORTED_RAILS_VERSIONS
|
48
|
+
TESTING.md
|
49
|
+
features/metal.feature
|
50
|
+
features/rack.feature
|
51
|
+
features/rails.feature
|
52
|
+
features/rake.feature
|
53
|
+
features/sinatra.feature
|
54
|
+
features/step_definitions/file_steps.rb
|
55
|
+
features/step_definitions/metal_steps.rb
|
56
|
+
features/step_definitions/rack_steps.rb
|
57
|
+
features/step_definitions/rails_application_steps.rb
|
58
|
+
features/step_definitions/rake_steps.rb
|
59
|
+
features/support/env.rb
|
60
|
+
features/support/honeybadger_shim.rb.template
|
61
|
+
features/support/rails.rb
|
62
|
+
features/support/rake/Rakefile
|
63
|
+
features/support/terminal.rb
|
64
|
+
generators/honeybadger/honeybadger_generator.rb
|
65
|
+
generators/honeybadger/lib/insert_commands.rb
|
66
|
+
generators/honeybadger/lib/rake_commands.rb
|
67
|
+
generators/honeybadger/templates/capistrano_hook.rb
|
68
|
+
generators/honeybadger/templates/honeybadger_tasks.rake
|
69
|
+
generators/honeybadger/templates/initializer.rb
|
70
|
+
honeybadger.gemspec
|
71
|
+
lib/honeybadger.rb
|
72
|
+
lib/honeybadger/backtrace.rb
|
73
|
+
lib/honeybadger/capistrano.rb
|
74
|
+
lib/honeybadger/configuration.rb
|
75
|
+
lib/honeybadger/notice.rb
|
76
|
+
lib/honeybadger/rack.rb
|
77
|
+
lib/honeybadger/rails.rb
|
78
|
+
lib/honeybadger/rails/action_controller_catcher.rb
|
79
|
+
lib/honeybadger/rails/controller_methods.rb
|
80
|
+
lib/honeybadger/rails/middleware/exceptions_catcher.rb
|
81
|
+
lib/honeybadger/rails3_tasks.rb
|
82
|
+
lib/honeybadger/railtie.rb
|
83
|
+
lib/honeybadger/rake_handler.rb
|
84
|
+
lib/honeybadger/sender.rb
|
85
|
+
lib/honeybadger/shared_tasks.rb
|
86
|
+
lib/honeybadger/tasks.rb
|
87
|
+
lib/honeybadger_tasks.rb
|
88
|
+
lib/rails/generators/honeybadger/honeybadger_generator.rb
|
89
|
+
rails/init.rb
|
90
|
+
resources/README.md
|
91
|
+
resources/ca-bundle.crt
|
92
|
+
script/integration_test.rb
|
93
|
+
test/test_helper.rb
|
94
|
+
test/unit/backtrace_test.rb
|
95
|
+
test/unit/capistrano_test.rb
|
96
|
+
test/unit/configuration_test.rb
|
97
|
+
test/unit/honeybadger_tasks_test.rb
|
98
|
+
test/unit/logger_test.rb
|
99
|
+
test/unit/notice_test.rb
|
100
|
+
test/unit/notifier_test.rb
|
101
|
+
test/unit/rack_test.rb
|
102
|
+
test/unit/rails/action_controller_catcher_test.rb
|
103
|
+
test/unit/rails_test.rb
|
104
|
+
test/unit/sender_test.rb
|
105
|
+
]
|
106
|
+
# = MANIFEST =
|
107
|
+
|
108
|
+
s.test_files = s.files.select { |path| path =~ /^test\/.*_test\.rb/ }
|
109
|
+
end
|
data/lib/honeybadger.rb
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/https'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'active_support'
|
7
|
+
require 'active_support/core_ext'
|
8
|
+
rescue LoadError
|
9
|
+
require 'activesupport'
|
10
|
+
require 'activesupport/core_ext'
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'honeybadger/configuration'
|
14
|
+
require 'honeybadger/backtrace'
|
15
|
+
require 'honeybadger/notice'
|
16
|
+
require 'honeybadger/rack'
|
17
|
+
require 'honeybadger/sender'
|
18
|
+
|
19
|
+
require 'honeybadger/railtie' if defined?(Rails::Railtie)
|
20
|
+
|
21
|
+
module Honeybadger
|
22
|
+
VERSION = '0.0.1'
|
23
|
+
LOG_PREFIX = "** [Honeybadger] "
|
24
|
+
|
25
|
+
HEADERS = {
|
26
|
+
'Content-type' => 'application/json',
|
27
|
+
'Accept' => 'text/json, application/json'
|
28
|
+
}
|
29
|
+
|
30
|
+
class << self
|
31
|
+
# The sender object is responsible for delivering formatted data to the
|
32
|
+
# Honeybadger server. Must respond to #send_to_honeybadger. See Honeybadger::Sender.
|
33
|
+
attr_accessor :sender
|
34
|
+
|
35
|
+
# A Honeybadger configuration object. Must act like a hash and return sensible
|
36
|
+
# values for all Honeybadger configuration options. See Honeybadger::Configuration.
|
37
|
+
attr_writer :configuration
|
38
|
+
end
|
39
|
+
|
40
|
+
# Tell the log that the Notifier is good to go
|
41
|
+
def self.report_ready
|
42
|
+
write_verbose_log("Notifier #{VERSION} ready to catch errors")
|
43
|
+
end
|
44
|
+
|
45
|
+
# Prints out the environment info to the log for debugging help
|
46
|
+
def self.report_environment_info
|
47
|
+
write_verbose_log("Environment Info: #{environment_info}")
|
48
|
+
end
|
49
|
+
|
50
|
+
# Prints out the response body from Honeybadger for debugging help
|
51
|
+
def self.report_response_body(response)
|
52
|
+
write_verbose_log("Response from Honeybadger: \n#{response}")
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns the Ruby version, Rails version, and current Rails environment
|
56
|
+
def self.environment_info
|
57
|
+
info = "[Ruby: #{RUBY_VERSION}]"
|
58
|
+
info << " [#{configuration.framework}]" if configuration.framework
|
59
|
+
info << " [Env: #{configuration.environment_name}]" if configuration.environment_name
|
60
|
+
end
|
61
|
+
|
62
|
+
# Writes out the given message to the #logger
|
63
|
+
def self.write_verbose_log(message)
|
64
|
+
logger.info LOG_PREFIX + message if logger
|
65
|
+
end
|
66
|
+
|
67
|
+
# Look for the Rails logger currently defined
|
68
|
+
def self.logger
|
69
|
+
self.configuration.logger
|
70
|
+
end
|
71
|
+
|
72
|
+
# Public: Call this method to modify defaults in your initializers.
|
73
|
+
#
|
74
|
+
# Examples:
|
75
|
+
#
|
76
|
+
# Honeybadger.configure do |config|
|
77
|
+
# config.api_key = '1234567890abcdef'
|
78
|
+
# config.secure = false
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
# Yields Honeybadger configuration
|
82
|
+
def self.configure(silent = false)
|
83
|
+
yield(configuration)
|
84
|
+
self.sender = Sender.new(configuration)
|
85
|
+
report_ready unless silent
|
86
|
+
self.sender
|
87
|
+
end
|
88
|
+
|
89
|
+
# Public: The configuration object.
|
90
|
+
# See Honeybadger.configure
|
91
|
+
#
|
92
|
+
# Returns Honeybadger configuration
|
93
|
+
def self.configuration
|
94
|
+
@configuration ||= Configuration.new
|
95
|
+
end
|
96
|
+
|
97
|
+
# Public: Sends an exception manually using this method, even when you are not in a controller.
|
98
|
+
#
|
99
|
+
# exception - The exception you want to notify Honeybadger about.
|
100
|
+
# options - Data that will be sent to Honeybadger.
|
101
|
+
# :api_key - The API key for this project. The API key is a unique identifier
|
102
|
+
# that Honeybadger uses for identification.
|
103
|
+
# :error_message - The error returned by the exception (or the message you want to log).
|
104
|
+
# :backtrace - A backtrace, usually obtained with +caller+.
|
105
|
+
# :rack_env - The Rack environment.
|
106
|
+
# :session - The contents of the user's session.
|
107
|
+
# :environment_name - The application environment name.
|
108
|
+
#
|
109
|
+
# Returns exception ID from Honeybadger on success, false on failure
|
110
|
+
def self.notify(exception, options = {})
|
111
|
+
send_notice(build_notice_for(exception, options))
|
112
|
+
end
|
113
|
+
|
114
|
+
# Public: Sends the notice unless it is one of the default ignored exceptions
|
115
|
+
# see Honeybadger.notify
|
116
|
+
def self.notify_or_ignore(exception, opts = {})
|
117
|
+
notice = build_notice_for(exception, opts)
|
118
|
+
send_notice(notice) unless notice.ignore?
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.build_lookup_hash_for(exception, options = {})
|
122
|
+
notice = build_notice_for(exception, options)
|
123
|
+
|
124
|
+
result = {}
|
125
|
+
result[:action] = notice.action rescue nil
|
126
|
+
result[:component] = notice.component rescue nil
|
127
|
+
result[:error_class] = notice.error_class if notice.error_class
|
128
|
+
result[:environment_name] = 'production'
|
129
|
+
|
130
|
+
unless notice.backtrace.lines.empty?
|
131
|
+
result[:file] = notice.backtrace.lines.first.file
|
132
|
+
result[:line_number] = notice.backtrace.lines.first.number
|
133
|
+
end
|
134
|
+
|
135
|
+
result
|
136
|
+
end
|
137
|
+
|
138
|
+
private
|
139
|
+
|
140
|
+
def self.send_notice(notice)
|
141
|
+
if configuration.public?
|
142
|
+
sender.send_to_honeybadger(notice.to_json)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def self.build_notice_for(exception, opts = {})
|
147
|
+
exception = unwrap_exception(exception)
|
148
|
+
opts = opts.merge(:exception => exception) if exception.is_a?(Exception)
|
149
|
+
opts = opts.merge(exception.to_hash) if exception.respond_to?(:to_hash)
|
150
|
+
Notice.new(configuration.merge(opts))
|
151
|
+
end
|
152
|
+
|
153
|
+
def self.unwrap_exception(exception)
|
154
|
+
if exception.respond_to?(:original_exception)
|
155
|
+
exception.original_exception
|
156
|
+
elsif exception.respond_to?(:continued_exception)
|
157
|
+
exception.continued_exception
|
158
|
+
else
|
159
|
+
exception
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module Honeybadger
|
2
|
+
# Public: Front end to parsing the backtrace for each notice
|
3
|
+
class Backtrace
|
4
|
+
|
5
|
+
# Public: Handles backtrace parsing line by line
|
6
|
+
class Line
|
7
|
+
# regexp (optionnally allowing leading X: for windows support)
|
8
|
+
INPUT_FORMAT = %r{^((?:[a-zA-Z]:)?[^:]+):(\d+)(?::in `([^']+)')?$}.freeze
|
9
|
+
|
10
|
+
# Public: The file portion of the line (such as app/models/user.rb)
|
11
|
+
attr_reader :file
|
12
|
+
|
13
|
+
# Public: The line number portion of the line
|
14
|
+
attr_reader :number
|
15
|
+
|
16
|
+
# Public: The method of the line (such as index)
|
17
|
+
attr_reader :method
|
18
|
+
|
19
|
+
# Public: Parses a single line of a given backtrace
|
20
|
+
#
|
21
|
+
# unparsed_line - The raw line from +caller+ or some backtrace
|
22
|
+
#
|
23
|
+
# Returns the parsed backtrace line
|
24
|
+
def self.parse(unparsed_line)
|
25
|
+
_, file, number, method = unparsed_line.match(INPUT_FORMAT).to_a
|
26
|
+
new(file, number, method)
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize(file, number, method)
|
30
|
+
self.file = file
|
31
|
+
self.number = number
|
32
|
+
self.method = method
|
33
|
+
end
|
34
|
+
|
35
|
+
# Public: Reconstructs the line in a readable fashion
|
36
|
+
def to_s
|
37
|
+
"#{file}:#{number}:in `#{method}'"
|
38
|
+
end
|
39
|
+
|
40
|
+
def ==(other)
|
41
|
+
to_s == other.to_s
|
42
|
+
end
|
43
|
+
|
44
|
+
def inspect
|
45
|
+
"<Line:#{to_s}>"
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
attr_writer :file, :number, :method
|
51
|
+
end
|
52
|
+
|
53
|
+
# Public: holder for an Array of Backtrace::Line instances
|
54
|
+
attr_reader :lines
|
55
|
+
|
56
|
+
def self.parse(ruby_backtrace, opts = {})
|
57
|
+
ruby_lines = split_multiline_backtrace(ruby_backtrace)
|
58
|
+
|
59
|
+
filters = opts[:filters] || []
|
60
|
+
filtered_lines = ruby_lines.to_a.map do |line|
|
61
|
+
filters.inject(line) do |line, proc|
|
62
|
+
proc.call(line)
|
63
|
+
end
|
64
|
+
end.compact
|
65
|
+
|
66
|
+
lines = filtered_lines.collect do |unparsed_line|
|
67
|
+
Line.parse(unparsed_line)
|
68
|
+
end
|
69
|
+
|
70
|
+
instance = new(lines)
|
71
|
+
end
|
72
|
+
|
73
|
+
def initialize(lines)
|
74
|
+
self.lines = lines
|
75
|
+
end
|
76
|
+
|
77
|
+
# Public
|
78
|
+
#
|
79
|
+
# Returns array containing backtrace lines
|
80
|
+
def to_ary
|
81
|
+
lines.map { |l| { :number => l.number, :file => l.file, :method => l.method } }
|
82
|
+
end
|
83
|
+
alias :to_a :to_ary
|
84
|
+
|
85
|
+
# Public: JSON support
|
86
|
+
#
|
87
|
+
# Returns JSON representation of backtrace
|
88
|
+
def as_json(options = {})
|
89
|
+
to_ary
|
90
|
+
end
|
91
|
+
|
92
|
+
# Public: Creates JSON
|
93
|
+
#
|
94
|
+
# Returns valid JSON representation of backtrace
|
95
|
+
def to_json(*a)
|
96
|
+
as_json.to_json(*a)
|
97
|
+
end
|
98
|
+
|
99
|
+
def inspect
|
100
|
+
"<Backtrace: " + lines.collect { |line| line.inspect }.join(", ") + ">"
|
101
|
+
end
|
102
|
+
|
103
|
+
def ==(other)
|
104
|
+
if other.respond_to?(:lines)
|
105
|
+
lines == other.lines
|
106
|
+
else
|
107
|
+
false
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
attr_writer :lines
|
114
|
+
|
115
|
+
def self.split_multiline_backtrace(backtrace)
|
116
|
+
if backtrace.to_a.size == 1
|
117
|
+
backtrace.to_a.first.split(/\n\s*/)
|
118
|
+
else
|
119
|
+
backtrace
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|